ad9467: register map changes

main
Rejeesh Kutty 2014-07-30 15:31:09 -04:00
parent c215eab696
commit dfd11cb809
5 changed files with 489 additions and 678 deletions

View File

@ -37,7 +37,7 @@
// ***************************************************************************
// ***************************************************************************
`timescale 1ns/1ns
`timescale 1ns/100ps
module axi_ad9467(
@ -47,8 +47,8 @@ module axi_ad9467(
adc_clk_in_n,
adc_data_in_p,
adc_data_in_n,
adc_data_or_p,
adc_data_or_n,
adc_or_in_p,
adc_or_in_n,
// delay_clock
@ -57,9 +57,11 @@ module axi_ad9467(
// dma interface
adc_clk,
adc_dwr,
adc_ddata,
adc_doverflow,
adc_valid,
adc_enable,
adc_data,
adc_dovf,
adc_dunf,
// axi interface
@ -81,8 +83,7 @@ module axi_ad9467(
s_axi_rvalid,
s_axi_rresp,
s_axi_rdata,
s_axi_rready
);
s_axi_rready);
// parameters
@ -90,8 +91,8 @@ module axi_ad9467(
parameter PCORE_BUFTYPE = 0;
parameter PCORE_IODELAY_GROUP = "dev_if_delay_group";
parameter C_S_AXI_MIN_SIZE = 32'hffff;
parameter C_BASEADDR = 32'hffffffff;
parameter C_HIGHADDR = 32'h00000000;
parameter C_HIGHADDR = 32'hffffffff;
parameter C_BASEADDR = 32'h00000000;
// physical interface
@ -99,8 +100,8 @@ module axi_ad9467(
input adc_clk_in_n;
input [ 7:0] adc_data_in_p;
input [ 7:0] adc_data_in_n;
input adc_data_or_p;
input adc_data_or_n;
input adc_or_in_p;
input adc_or_in_n;
// delay clk
@ -109,9 +110,11 @@ module axi_ad9467(
// dma interface
output adc_clk;
output adc_dwr;
output [15:0] adc_ddata;
input adc_doverflow;
output adc_valid;
output adc_enable;
output [15:0] adc_data;
input adc_dovf;
input adc_dunf;
// axi interface
@ -136,59 +139,59 @@ module axi_ad9467(
input s_axi_rready;
// internal registers
reg [31:0] up_rdata = 32'b0;
reg up_ack = 1'b0;
// internal clock and resets
reg [31:0] up_rdata = 'd0;
reg up_ack = 'd0;
// internal clocks & resets
wire adc_rst;
wire up_clk;
wire up_rstn;
wire adc_rst;
wire adc_clk;
// internal signals
wire up_sel_s;
wire up_wr_s;
wire [13:0] up_addr_s;
wire [31:0] up_wdata_s;
wire [15:0] adc_data_if_s;
wire [15:0] adc_data_s;
wire adc_or_s;
wire up_adc_or_s;
wire adc_ddr_edgesel_s;
wire delay_rst_s;
wire delay_sel_s;
wire delay_rwn_s;
wire [ 7:0] delay_addr_s;
wire [ 4:0] delay_wdata_s;
wire delay_rst;
wire delay_ack_s;
wire [ 4:0] delay_rdata_s;
wire delay_ack_t_s;
wire delay_locked_s;
wire adc_pn_oos_s;
wire adc_pn_err_s;
wire [31:0] up_rdata_common;
wire [31:0] up_rdata_channel;
wire up_ack_common;
wire up_ack_channel;
wire adc_pn_type_s;
wire [15:0] adc_channel_data_s;
wire adc_enable_s;
wire up_status_pn_err_s;
wire up_status_pn_oos_s;
wire up_status_or_s;
wire [31:0] up_rdata_s[0:1];
wire up_ack_s[0:1];
wire up_sel_s;
wire up_wr_s;
wire [13:0] up_addr_s;
wire [31:0] up_wdata_s;
//defaults
assign up_clk = s_axi_aclk;
assign up_rstn = s_axi_aresetn;
assign adc_dwr = 1'b1;
assign adc_ddata = adc_data_if_s;
assign adc_valid = 1'b1;
// processor read interface
always @(negedge up_rstn or posedge up_clk) begin
if (up_rstn == 0) begin
up_rdata <= 32'd0;
up_ack <= 1'd0;
end else begin
up_rdata <= up_rdata_channel | up_rdata_common;
up_ack <= up_ack_channel | up_ack_common;
up_rdata <= up_rdata_s[0] | up_rdata_s[1];
up_ack <= up_ack_s[0] | up_ack_s[1];
end
end
// ADC data interface
// main (device interface)
axi_ad9467_if #(
.PCORE_BUFTYPE (PCORE_BUFTYPE),
.PCORE_IODELAY_GROUP (PCORE_IODELAY_GROUP))
@ -197,88 +200,92 @@ module axi_ad9467(
.adc_clk_in_n (adc_clk_in_n),
.adc_data_in_p (adc_data_in_p),
.adc_data_in_n (adc_data_in_n),
.adc_data_or_p (adc_data_or_p),
.adc_data_or_n (adc_data_or_n),
.adc_or_in_p (adc_or_in_p),
.adc_or_in_n (adc_or_in_n),
.adc_clk (adc_clk),
.adc_data (adc_data_if_s),
.adc_data (adc_data_s),
.adc_or (adc_or_s),
.adc_ddr_edgesel (adc_ddr_edgesel_s),
.delay_clk (delay_clk),
.delay_rst (delay_rst_s),
.delay_sel (delay_sel_s),
.delay_rwn (delay_rwn_s),
.delay_addr (delay_addr_s),
.delay_wdata (delay_wdata_s),
.delay_clk (delay_clk),
.delay_ack (delay_ack_s),
.delay_rst (delay_rst),
.delay_rdata (delay_rdata_s),
.delay_ack_t (delay_ack_t),
.delay_locked (delay_locked_s));
// channel
axi_ad9467_channel #(.CHID(0)) i_channel (
.adc_clk(adc_clk),
.adc_rst(adc_rst),
.adc_data(adc_data_if_s),
.adc_or(adc_or_s),
.adc_dfmt_data(adc_channel_data_s),
.adc_enable(adc_enable_s),
.up_adc_pn_err(adc_pn_err_s),
.up_adc_pn_oos(adc_pn_oos_s),
.up_adc_or(up_adc_or_s),
.up_rstn(up_rstn),
.up_clk(up_clk),
.up_sel(up_sel_s),
.up_wr(up_wr_s),
.up_addr(up_addr_s),
.up_wdata(up_wdata_s),
.up_rdata(up_rdata_channel),
.up_ack(up_ack_channel));
.adc_clk (adc_clk),
.adc_rst (adc_rst),
.adc_data (adc_data_s),
.adc_or (adc_or_s),
.adc_dfmt_data (adc_data),
.adc_enable (adc_enable),
.up_adc_pn_err (up_status_pn_err_s),
.up_adc_pn_oos (up_status_pn_oos_s),
.up_adc_or (up_status_or_s),
.up_rstn (up_rstn),
.up_clk (up_clk),
.up_sel (up_sel_s),
.up_wr (up_wr_s),
.up_addr (up_addr_s),
.up_wdata (up_wdata_s),
.up_rdata (up_rdata_s[0]),
.up_ack (up_ack_s[0]));
// common processor control
up_adc_common #(.PCORE_ID(PCORE_ID))
i_up_adc_common(
.mmcm_rst(),
.delay_clk(delay_clk),
.delay_ack_t(delay_ack_s),
.delay_locked(delay_locked_s),
.delay_rst(delay_rst),
.delay_sel(delay_sel_s),
.delay_rwn(delay_rwn_s),
.delay_addr(delay_addr_s),
.delay_wdata(delay_wdata_s),
.delay_rdata(delay_rdata_s),
.adc_clk(adc_clk),
.adc_rst(adc_rst),
.adc_r1_mode(),
.adc_ddr_edgesel(adc_ddr_edgesel_s),
.adc_pin_mode(),
.adc_status(1'b1),
.adc_status_pn_err(adc_pn_err_s),
.adc_status_pn_oos(adc_pn_oos_s),
.adc_status_or(up_adc_or_s),
.adc_clk_ratio(32'b1),
.adc_status_ovf(adc_doverflow),
.adc_status_unf(1'b0),
.drp_clk(1'b0),
.drp_rdata(16'b0),
.drp_rst(),
.drp_sel(),
.drp_wr(),
.drp_addr(),
.drp_wdata(),
.drp_ready(1'b0),
.drp_locked(1'b1),
.up_rstn(up_rstn),
.up_clk(up_clk),
.up_sel(up_sel_s),
.up_wr(up_wr_s),
.up_addr(up_addr_s),
.up_wdata(up_wdata_s),
.up_rdata(up_rdata_common),
.up_ack(up_ack_common),
.up_usr_chanmax(),
.adc_usr_chanmax(8'b0));
// axi interface
up_adc_common #(.PCORE_ID(PCORE_ID)) i_up_adc_common (
.mmcm_rst (),
.adc_clk (adc_clk),
.adc_rst (adc_rst),
.adc_r1_mode (),
.adc_ddr_edgesel (adc_ddr_edgesel_s),
.adc_pin_mode (),
.adc_status (1'b1),
.adc_status_ovf (adc_dovf),
.adc_status_unf (adc_dunf),
.adc_clk_ratio (32'b1),
.up_status_pn_err (up_status_pn_err_s),
.up_status_pn_oos (up_status_pn_oos_s),
.up_status_or (up_status_or_s),
.delay_clk (delay_clk),
.delay_rst (delay_rst_s),
.delay_sel (delay_sel_s),
.delay_rwn (delay_rwn_s),
.delay_addr (delay_addr_s),
.delay_wdata (delay_wdata_s),
.delay_rdata (delay_rdata_s),
.delay_ack_t (delay_ack_t),
.delay_locked (delay_locked_s),
.drp_clk (1'b0),
.drp_rst (),
.drp_sel (),
.drp_wr (),
.drp_addr (),
.drp_wdata (),
.drp_rdata (16'b0),
.drp_ready (1'b0),
.drp_locked (1'b1),
.up_usr_chanmax (),
.adc_usr_chanmax (8'd1),
.up_adc_gpio_in (32'd0),
.up_adc_gpio_out (),
.up_rstn (up_rstn),
.up_clk (up_clk),
.up_sel (up_sel_s),
.up_wr (up_wr_s),
.up_addr (up_addr_s),
.up_wdata (up_wdata_s),
.up_rdata (up_rdata_s[1]),
.up_ack (up_ack_s[1]));
// up bus interface
up_axi #(
.PCORE_BASEADDR (C_BASEADDR),
.PCORE_HIGHADDR (C_HIGHADDR))
@ -310,3 +317,6 @@ module axi_ad9467(
.up_ack (up_ack));
endmodule
// ***************************************************************************
// ***************************************************************************

View File

@ -34,23 +34,20 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
// ***************************************************************************
`timescale 1ns/1ns
`timescale 1ns/100ps
//------------------------------------------------------------------------------
//----------- Module Declaration -----------------------------------------------
//------------------------------------------------------------------------------
module axi_ad9467_channel(
// adc interface
adc_clk,
adc_rst,
adc_data,
adc_or,
// channel interface
adc_dfmt_data,
adc_enable,
up_adc_pn_err,
@ -58,6 +55,7 @@ module axi_ad9467_channel(
up_adc_or,
// processor interface
up_rstn,
up_clk,
up_sel,
@ -67,16 +65,19 @@ module axi_ad9467_channel(
up_rdata,
up_ack);
// core parameter
// parameters
parameter CHID = 0;
// adc interface
input adc_clk;
input adc_rst;
input [15:0] adc_data;
input adc_or;
// channel interface
output [15:0] adc_dfmt_data;
output adc_enable;
output up_adc_pn_err;
@ -84,6 +85,7 @@ module axi_ad9467_channel(
output up_adc_or;
// processor interface
input up_rstn;
input up_clk;
input up_sel;
@ -93,20 +95,23 @@ module axi_ad9467_channel(
output [31:0] up_rdata;
output up_ack;
wire adc_pn_err_s;
// internal signals
wire adc_pn_oos_s;
wire adc_pn_type_s;
wire adc_pn_err_s;
wire [ 3:0] adc_pnseq_sel_s;
wire adc_dfmt_enable_s;
wire adc_dfmt_type_s;
wire adc_dfmt_se_s;
// PN sequence monitor
// instantiations
axi_ad9467_pnmon i_axi_ad9467_pnmon (
.adc_clk (adc_clk),
.adc_data (adc_data),
.adc_pn_oos (adc_pn_oos_s),
.adc_pn_err (adc_pn_err_s),
.up_pn_type (adc_pn_type_s));
.adc_pnseq_sel (adc_pnseq_sel_s));
ad_datafmt #(.DATA_WIDTH(16)) i_datafmt (
.clk(adc_clk),
@ -118,22 +123,21 @@ module axi_ad9467_channel(
.dfmt_type(adc_dfmt_type_s),
.dfmt_se(adc_dfmt_se_s));
// adc channel control
up_adc_channel #(.PCORE_ADC_CHID(0)) i_up_adc_channel (
.adc_clk (adc_clk),
.adc_rst (adc_rst),
.adc_enable (adc_enable),
.adc_pn_sel (),
.adc_iqcor_enb (),
.adc_dcfilt_enb (),
.adc_dfmt_se (adc_dfmt_se_s),
.adc_dfmt_type (adc_dfmt_type_s),
.adc_dfmt_enable (adc_dfmt_enable_s),
.adc_pn_type (adc_pn_type_s),
.adc_dcfilt_offset (),
.adc_dcfilt_coeff (),
.adc_iqcor_coeff_1 (),
.adc_iqcor_coeff_2 (),
.adc_pnseq_sel (adc_pnseq_sel_s),
.adc_data_sel (),
.adc_pn_err (adc_pn_err_s),
.adc_pn_oos (adc_pn_oos_s),
.adc_or (adc_or),
@ -164,3 +168,6 @@ module axi_ad9467_channel(
.up_ack (up_ack));
endmodule
// ***************************************************************************
// ***************************************************************************

View File

@ -44,65 +44,74 @@
module axi_ad9467_if (
// adc interface (clk, data, over-range)
adc_clk_in_p,
adc_clk_in_n,
adc_data_in_p,
adc_data_in_n,
adc_data_or_p,
adc_data_or_n,
adc_or_in_p,
adc_or_in_n,
// interface outputs
adc_clk,
adc_data,
adc_or,
// processor interface
adc_ddr_edgesel,
// delay control signals
delay_clk,
delay_rst,
delay_sel,
delay_rwn,
delay_addr,
delay_wdata,
delay_clk,
delay_ack,
delay_rst,
delay_rdata,
delay_ack_t,
delay_locked);
// This parameter controls the buffer type based on the target device.
// buffer type based on the target device.
parameter PCORE_BUFTYPE = 0;
parameter C_DEVICE_7SERIES = 0;
parameter C_DEVICE_VIRTEX6 = 1;
parameter PCORE_IODELAY_GROUP = "dev_if_delay_group";
// adc interface (clk, data, over-range)
input adc_clk_in_p;
input adc_clk_in_n;
input [ 7:0] adc_data_in_p;
input [ 7:0] adc_data_in_n;
input adc_data_or_p;
input adc_data_or_n;
input adc_or_in_p;
input adc_or_in_n;
// interface outputs
output adc_clk;
output [15:0] adc_data;
output adc_or;
// processor interface
input adc_ddr_edgesel;
// delay control signals
input delay_clk;
input delay_rst;
input delay_sel;
input delay_rwn;
input [ 7:0] delay_addr;
input [ 4:0] delay_wdata;
input delay_clk;
input delay_rst;
output delay_ack;
output [ 4:0] delay_rdata;
output delay_ack_t;
output delay_locked;
// internal registers
reg [ 7:0] adc_data_p = 'd0;
reg [ 7:0] adc_data_n = 'd0;
reg [ 7:0] adc_data_n_d = 'd0;
@ -113,25 +122,20 @@ module axi_ad9467_if (
reg adc_or_n = 'd0;
reg adc_or = 'd0;
reg [ 8:0] delay_ld = 'd0;
reg delay_ack = 'd0;
reg delay_ack_t = 'd0;
reg [ 4:0] delay_rdata = 'd0;
// internal signals
wire [ 4:0] delay_rdata_s[8:0];
wire [ 7:0] adc_data_ibuf_s;
wire [ 7:0] adc_data_idelay_s;
wire [ 7:0] adc_data_p_s;
wire [ 7:0] adc_data_n_s;
wire adc_or_ibuf_s;
wire adc_or_idelay_s;
wire adc_or_p_s;
wire adc_or_n_s;
wire adc_clk_ibuf_s;
genvar l_inst;
// The adc data is 8bits ddr, and here it is demuxed to 16bits.
// The samples may be selected to be either positive first,
// or negative first.
// sample select (p/n) swap
always @(posedge adc_clk) begin
adc_data_p <= adc_data_p_s;
@ -164,8 +168,8 @@ module axi_ad9467_if (
end
end
// The delay write interface, each delay element can be individually
// addressed, and a delay value can be directly loaded (no INC/DEC stuff)
// delay write interface, each delay element can be individually
// addressed, and a delay value can be directly loaded (no inc/dec stuff)
always @(posedge delay_clk) begin
if ((delay_sel == 1'b1) && (delay_rwn == 1'b0)) begin
@ -204,198 +208,60 @@ module axi_ad9467_if (
default: delay_rdata <= 5'd0;
endcase
if (delay_sel == 1'b1) begin
delay_ack <= ~delay_ack;
delay_ack_t <= ~delay_ack_t;
end
end
// The data interface, data signals goes through a LVDS input buffer, then
// a delay element (1/32th of a 200MHz clock) and finally an input DDR demux.
// data interface
generate
for (l_inst = 0; l_inst <= 7; l_inst = l_inst + 1) begin : g_adc_if
IBUFDS i_data_ibuf (
.I (adc_data_in_p[l_inst]),
.IB (adc_data_in_n[l_inst]),
.O (adc_data_ibuf_s[l_inst]));
if (PCORE_BUFTYPE == C_DEVICE_VIRTEX6) begin
(* IODELAY_GROUP = PCORE_IODELAY_GROUP *)
IODELAYE1 #(
.CINVCTRL_SEL ("FALSE"),
.DELAY_SRC ("I"),
.HIGH_PERFORMANCE_MODE ("TRUE"),
.IDELAY_TYPE ("VAR_LOADABLE"),
.IDELAY_VALUE (0),
.ODELAY_TYPE ("FIXED"),
.ODELAY_VALUE (0),
.REFCLK_FREQUENCY (200.0),
.SIGNAL_PATTERN ("DATA"))
i_data_idelay (
.T (1'b1),
.CE (1'b0),
.INC (1'b0),
.CLKIN (1'b0),
.DATAIN (1'b0),
.ODATAIN (1'b0),
.CINVCTRL (1'b0),
.C (delay_clk),
.IDATAIN (adc_data_ibuf_s[l_inst]),
.DATAOUT (adc_data_idelay_s[l_inst]),
.RST (delay_ld[l_inst]),
.CNTVALUEIN (delay_wdata),
.CNTVALUEOUT (delay_rdata_s[l_inst]));
end else begin
(* IODELAY_GROUP = PCORE_IODELAY_GROUP *)
IDELAYE2 #(
.CINVCTRL_SEL ("FALSE"),
.DELAY_SRC ("IDATAIN"),
.HIGH_PERFORMANCE_MODE ("FALSE"),
.IDELAY_TYPE ("VAR_LOAD"),
.IDELAY_VALUE (0),
.REFCLK_FREQUENCY (200.0),
.PIPE_SEL ("FALSE"),
.SIGNAL_PATTERN ("DATA"))
i_data_idelay (
.CE (1'b0),
.INC (1'b0),
.DATAIN (1'b0),
.LDPIPEEN (1'b0),
.CINVCTRL (1'b0),
.REGRST (1'b0),
.C (delay_clk),
.IDATAIN (adc_data_ibuf_s[l_inst]),
.DATAOUT (adc_data_idelay_s[l_inst]),
.LD (delay_ld[l_inst]),
.CNTVALUEIN (delay_wdata),
.CNTVALUEOUT (delay_rdata_s[l_inst]));
end
IDDR #(
.INIT_Q1 (1'b0),
.INIT_Q2 (1'b0),
.DDR_CLK_EDGE ("SAME_EDGE_PIPELINED"),
.SRTYPE ("ASYNC"))
i_data_ddr (
.CE (1'b1),
.R (1'b0),
.S (1'b0),
.C (adc_clk),
.D (adc_data_idelay_s[l_inst]),
.Q1 (adc_data_p_s[l_inst]),
.Q2 (adc_data_n_s[l_inst]));
ad_lvds_in #(
.BUFTYPE (PCORE_BUFTYPE),
.IODELAY_CTRL (0),
.IODELAY_GROUP (PCORE_IODELAY_GROUP))
i_adc_data (
.rx_clk (adc_clk),
.rx_data_in_p (adc_data_in_p[l_inst]),
.rx_data_in_n (adc_data_in_n[l_inst]),
.rx_data_p (adc_data_p_s[l_inst]),
.rx_data_n (adc_data_n_s[l_inst]),
.delay_clk (delay_clk),
.delay_rst (delay_rst),
.delay_ld (delay_ld[l_inst]),
.delay_wdata (delay_wdata),
.delay_rdata (delay_rdata_s[l_inst]),
.delay_locked ());
end
endgenerate
// The over-range interface, it follows a similar path as the data signals.
// over-range interface
IBUFDS i_or_ibuf (
.I (adc_data_or_p),
.IB (adc_data_or_n),
.O (adc_or_ibuf_s));
ad_lvds_in #(
.BUFTYPE (PCORE_BUFTYPE),
.IODELAY_CTRL (1),
.IODELAY_GROUP (PCORE_IODELAY_GROUP))
i_adc_or (
.rx_clk (adc_clk),
.rx_data_in_p (adc_or_in_p),
.rx_data_in_n (adc_or_in_n),
.rx_data_p (adc_or_p_s),
.rx_data_n (adc_or_n_s),
.delay_clk (delay_clk),
.delay_rst (delay_rst),
.delay_ld (delay_ld[8]),
.delay_wdata (delay_wdata),
.delay_rdata (delay_rdata_s[8]),
.delay_locked (delay_locked));
generate
if (PCORE_BUFTYPE == C_DEVICE_VIRTEX6) begin
(* IODELAY_GROUP = PCORE_IODELAY_GROUP *)
IODELAYE1 #(
.CINVCTRL_SEL ("FALSE"),
.DELAY_SRC ("I"),
.HIGH_PERFORMANCE_MODE ("TRUE"),
.IDELAY_TYPE ("VAR_LOADABLE"),
.IDELAY_VALUE (0),
.ODELAY_TYPE ("FIXED"),
.ODELAY_VALUE (0),
.REFCLK_FREQUENCY (200.0),
.SIGNAL_PATTERN ("DATA"))
i_or_idelay (
.T (1'b1),
.CE (1'b0),
.INC (1'b0),
.CLKIN (1'b0),
.DATAIN (1'b0),
.ODATAIN (1'b0),
.CINVCTRL (1'b0),
.C (delay_clk),
.IDATAIN (adc_or_ibuf_s),
.DATAOUT (adc_or_idelay_s),
.RST (delay_ld[8]),
.CNTVALUEIN (delay_wdata),
.CNTVALUEOUT (delay_rdata_s[8]));
end else begin
(* IODELAY_GROUP = PCORE_IODELAY_GROUP *)
IDELAYE2 #(
.CINVCTRL_SEL ("FALSE"),
.DELAY_SRC ("IDATAIN"),
.HIGH_PERFORMANCE_MODE ("FALSE"),
.IDELAY_TYPE ("VAR_LOAD"),
.IDELAY_VALUE (0),
.REFCLK_FREQUENCY (200.0),
.PIPE_SEL ("FALSE"),
.SIGNAL_PATTERN ("DATA"))
i_or_idelay (
.CE (1'b0),
.INC (1'b0),
.DATAIN (1'b0),
.LDPIPEEN (1'b0),
.CINVCTRL (1'b0),
.REGRST (1'b0),
.C (delay_clk),
.IDATAIN (adc_or_ibuf_s),
.DATAOUT (adc_or_idelay_s),
.LD (delay_ld[8]),
.CNTVALUEIN (delay_wdata),
.CNTVALUEOUT (delay_rdata_s[8]));
end
endgenerate
// clock
IDDR #(
.INIT_Q1 (1'b0),
.INIT_Q2 (1'b0),
.DDR_CLK_EDGE ("SAME_EDGE_PIPELINED"),
.SRTYPE ("ASYNC"))
i_or_ddr (
.CE (1'b1),
.R (1'b0),
.S (1'b0),
.C (adc_clk),
.D (adc_or_idelay_s),
.Q1 (adc_or_p_s),
.Q2 (adc_or_n_s));
// The clock path is a simple clock buffer after a LVDS input buffer.
// It is possible for this logic to be replaced with a OSERDES based data capture.
// The reason for such a simple interface here is because this reference design
// is used for various boards (native fmc and/or evaluation boards). The pinouts
// of the FPGA - ADC interface is probably do not allow a OSERDES placement.
IBUFGDS i_clk_ibuf (
.I (adc_clk_in_p),
.IB (adc_clk_in_n),
.O (adc_clk_ibuf_s));
generate
if (PCORE_BUFTYPE == C_DEVICE_VIRTEX6) begin
BUFR #(.BUFR_DIVIDE ("BYPASS")) i_clk_gbuf (
.CLR (1'b0),
.CE (1'b1),
.I (adc_clk_ibuf_s),
.O (adc_clk));
end else begin
BUFG i_clk_gbuf (
.I (adc_clk_ibuf_s),
.O (adc_clk));
end
endgenerate
// The delay controller. Refer to Xilinx doc. for details.
// The GROUP directive controls which delay elements this is associated with.
(* IODELAY_GROUP = PCORE_IODELAY_GROUP *)
IDELAYCTRL i_delay_ctrl (
.RST (delay_rst),
.REFCLK (delay_clk),
.RDY (delay_locked));
ad_lvds_clk #(
.BUFTYPE (PCORE_BUFTYPE))
i_adc_clk (
.clk_in_p (adc_clk_in_p),
.clk_in_n (adc_clk_in_n),
.clk (adc_clk));
endmodule

View File

@ -6,7 +6,10 @@ source $ad_hdl_dir/library/scripts/adi_ip.tcl
adi_ip_create axi_ad9467
adi_ip_files axi_ad9467 [list \
"$ad_hdl_dir/library/common/ad_rst.v" \
"$ad_hdl_dir/library/common/ad_lvds_clk.v" \
"$ad_hdl_dir/library/common/ad_lvds_in.v" \
"$ad_hdl_dir/library/common/ad_datafmt.v" \
"$ad_hdl_dir/library/common/ad_pnmon.v" \
"$ad_hdl_dir/library/common/up_xfer_status.v" \
"$ad_hdl_dir/library/common/up_xfer_cntrl.v" \
"$ad_hdl_dir/library/common/up_clock_mon.v" \

View File

@ -43,47 +43,36 @@
module axi_ad9467_pnmon (
// adc interface
adc_clk,
adc_data,
// pn out of sync and error
adc_pn_oos,
adc_pn_err,
// processor interface PN9 (0x0), PN23 (0x1)
up_pn_type);
adc_pnseq_sel);
// adc interface
input adc_clk;
input [15:0] adc_data;
// pn out of sync and error
output adc_pn_oos;
output adc_pn_err;
input [ 3:0] adc_pnseq_sel;
// processor interface PN9 (0x0), PN23 (0x1)
input up_pn_type;
// internal registers
reg adc_pn_type_m1 = 'd0;
reg adc_pn_type_m2 = 'd0;
reg adc_pn_type = 'd0;
reg adc_pn_en = 'd0;
reg [15:0] adc_data_d = 'd0;
reg [31:0] adc_pn_data = 'd0;
reg adc_pn_en_d = 'd0;
reg adc_pn_match = 'd0;
reg [ 6:0] adc_pn_oos_count = 'd0;
reg adc_pn_oos = 'd0;
reg [ 4:0] adc_pn_err_count = 'd0;
reg adc_pn_err = 'd0;
reg adc_valid_in = 'd0;
reg [31:0] adc_pn_data_in = 'd0;
reg [31:0] adc_pn_data_pn = 'd0;
// internal signals
wire [31:0] adc_pn_data_in_s;
wire adc_pn_match0_s;
wire adc_pn_match1_s;
wire adc_pn_match2_s;
wire adc_pn_match_s;
wire [31:0] adc_pn_data_s;
wire adc_pn_err_s;
// PN23 function
@ -169,93 +158,29 @@ module axi_ad9467_pnmon (
end
endfunction
// This PN sequence checking algorithm is commonly used is most applications.
// It is a simple function generated based on the OOS status.
// If OOS is asserted (PN is OUT of sync):
// The next sequence is generated from the incoming data.
// If 16 sequences match CONSECUTIVELY, OOS is cleared (de-asserted).
// If OOS is de-asserted (PN is IN sync)
// The next sequence is generated from the current sequence.
// If 64 sequences mismatch CONSECUTIVELY, OOS is set (asserted).
// If OOS is de-asserted, any spurious mismatches sets the ERROR register.
// Ideally, processor should make sure both OOS == 0x0 AND ERR == 0x0.
// pn sequence select
assign adc_pn_data_in_s[31:16] = {~adc_data_d[15], adc_data_d[14:0]};
assign adc_pn_data_in_s[15:0] = {~adc_data[15], adc_data[14:0]};
assign adc_pn_match0_s = (adc_pn_data_in_s[31:16] == adc_pn_data[31:16]) ? 1'b1 : 1'b0;
assign adc_pn_match1_s = (adc_pn_data_in_s[15:0] == adc_pn_data[15:0]) ? 1'b1 : 1'b0;
assign adc_pn_match2_s = ((adc_data == 16'd0) && (adc_data_d == 16'd0)) ? 1'b0 : 1'b1;
assign adc_pn_match_s = adc_pn_match0_s & adc_pn_match1_s & adc_pn_match2_s;
assign adc_pn_data_s = (adc_pn_oos == 1'b1) ? adc_pn_data_in_s : adc_pn_data;
assign adc_pn_err_s = ~(adc_pn_oos | adc_pn_match);
// PN running sequence
assign adc_pn_data_pn_s = (adc_pn_oos == 1'b1) ? adc_pn_data_in : adc_pn_data_pn;
always @(posedge adc_clk) begin
adc_pn_type_m1 <= up_pn_type;
adc_pn_type_m2 <= adc_pn_type_m1;
adc_pn_type <= adc_pn_type_m2;
adc_pn_en <= ~adc_pn_en;
adc_data_d <= adc_data;
if (adc_pn_en == 1'b1) begin
if (adc_pn_type == 1'b0) begin
adc_pn_data <= pn9(adc_pn_data_s);
adc_valid_in <= ~adc_valid_in;
adc_pn_data_in <= {adc_pn_data_in[15:0], ~adc_data[15], adc_data[14:0]};
if (adc_pnseq_sel == 4'd0) begin
adc_pn_data_pn <= pn9(adc_pn_data_pn_s);
end else begin
adc_pn_data <= pn23(adc_pn_data_s);
end
adc_pn_data_pn <= pn23(adc_pn_data_pn_s);
end
end
// PN OOS and counters (16 to clear, 64 to set). These numbers are actually determined
// based on BER parameters set by the system (usually in network applications).
// pn oos & pn err
always @(posedge adc_clk) begin
adc_pn_en_d <= adc_pn_en;
adc_pn_match <= adc_pn_match_s;
if (adc_pn_en_d == 1'b1) begin
if (adc_pn_oos == 1'b1) begin
if (adc_pn_match == 1'b1) begin
if (adc_pn_oos_count >= 16) begin
adc_pn_oos_count <= 'd0;
adc_pn_oos <= 'd0;
end else begin
adc_pn_oos_count <= adc_pn_oos_count + 1'b1;
adc_pn_oos <= 'd1;
end
end else begin
adc_pn_oos_count <= 'd0;
adc_pn_oos <= 'd1;
end
end else begin
if (adc_pn_match == 1'b0) begin
if (adc_pn_oos_count >= 64) begin
adc_pn_oos_count <= 'd0;
adc_pn_oos <= 'd1;
end else begin
adc_pn_oos_count <= adc_pn_oos_count + 1'b1;
adc_pn_oos <= 'd0;
end
end else begin
adc_pn_oos_count <= 'd0;
adc_pn_oos <= 'd0;
end
end
end
end
// The error state is streched to multiple adc clocks such that processor
// has enough time to sample the error condition.
always @(posedge adc_clk) begin
if (adc_pn_en_d == 1'b1) begin
if (adc_pn_err_s == 1'b1) begin
adc_pn_err_count <= 5'h10;
end else if (adc_pn_err_count[4] == 1'b1) begin
adc_pn_err_count <= adc_pn_err_count + 1'b1;
end
end
adc_pn_err <= adc_pn_err_count[4];
end
ad_pnmon #(.DATA_WIDTH(32)) i_pnmon (
.adc_clk (adc_clk),
.adc_valid_in (adc_valid_in),
.adc_data_in (adc_pn_data_in),
.adc_data_pn (adc_pn_data_pn),
.adc_pn_oos (adc_pn_oos),
.adc_pn_err (adc_pn_err));
endmodule