diff options
Diffstat (limited to 'fpga/usrp3/lib/io_cap_gen/cat_input_lvds.v')
| -rw-r--r-- | fpga/usrp3/lib/io_cap_gen/cat_input_lvds.v | 609 |
1 files changed, 609 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/io_cap_gen/cat_input_lvds.v b/fpga/usrp3/lib/io_cap_gen/cat_input_lvds.v new file mode 100644 index 000000000..9b24ca6ca --- /dev/null +++ b/fpga/usrp3/lib/io_cap_gen/cat_input_lvds.v @@ -0,0 +1,609 @@ +// +// Copyright 2016 Ettus Research, A National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// +// Module: cat_input_lvds +// +// Description: +// +// Receive interface to AD9361 (Catalina) in LVDS mode. +// +// Use Xilinx SERDES to deserialize interleaved sample data off +// half-word-width LVDS differential data bus from the Catalina. +// +// Use FRAME signal to initially synchronize to incoming data after reset +// de-asserts. +// +// In all modes (SISO or MIMO) we output a clock of 1/4 the frequency +// of the Catalina source-synchronous bus clock to be used as the radio_clk. +// +// In SISO mode, every cycle of the radio_clk supplies a new RX sample which +// is routed to both radios, even if only one is actively receiving. +// +// In MIMO mode, every cycle of the radio clock supplies a pair of +// time aligned MIMO samples which are routed to different radios. +// +// The frame_sample signal controls the expected frame signal timing. When +// frame_sample is 0, the period of the ddr_frame signal is expected to equal +// two samples (e.g., one from each channel). When frame_sample is 1, the frame +// period is expected to equal the length of one sample. This allows the module +// to be used for 2R2T (frame_sample = 1) or 1R1T mode (frame_sample = 0). +// + + +module cat_input_lvds #( + parameter INVERT_FRAME_RX = 0, + parameter INVERT_DATA_RX = 6'b00_0000, + parameter USE_CLOCK_DELAY = 1, + parameter USE_DATA_DELAY = 1, + parameter CLOCK_DELAY_MODE = "VAR_LOAD", + parameter DATA_DELAY_MODE = "VAR_LOAD", + parameter CLOCK_DELAY = 0, + parameter DATA_DELAY = 0, + parameter WIDTH = 6, + parameter GROUP = "DEFAULT", + parameter USE_BUFG = 1 +) ( + input clk200, + input rst, + + // Data and frame timing (synchronous to radio_clk) + input mimo, // Output one channel (MIMO=0) or two (MIMO=1) + input frame_sample, // Two samples per frame period (frame_sample=0) or one sample per frame (frame_sample=1) + + // Region local Clocks for I/O cells. + output ddr_clk, + output sdr_clk, + + // Source Synchronous external input clock + input ddr_clk_p, + input ddr_clk_n, + + // Source Synchronous data lines + input [WIDTH-1:0] ddr_data_p, + input [WIDTH-1:0] ddr_data_n, + input ddr_frame_p, + input ddr_frame_n, + + // Delay control interface + input ctrl_clk, + input [4:0] ctrl_data_delay, + input [4:0] ctrl_clk_delay, + input ctrl_ld_data_delay, + input ctrl_ld_clk_delay, + + // Global output clocks, ddr_clk/4 & ddr_clk/2 + output radio_clk, + output radio_clk_2x, + + // SDR Data buses + output reg [(WIDTH*2)-1:0] i0, + output reg [(WIDTH*2)-1:0] q0, + output reg [(WIDTH*2)-1:0] i1, + output reg [(WIDTH*2)-1:0] q1, + output reg rx_aligned + +); + + //------------------------------------------------------------------ + // UG471 says take reset high asynchronously, and de-assert + // synchronized to CLKDIV (sdr_clk) for SERDES. + //------------------------------------------------------------------ + (* ASYNC_REG = "TRUE" *) reg rst_sdr_sync, rst_sdr_sync_ms; + + always @(posedge sdr_clk or posedge rst) + if (rst) begin + rst_sdr_sync_ms <= 1'b1; + rst_sdr_sync <= 1'b1; + end else begin + rst_sdr_sync_ms <= 1'b0; + rst_sdr_sync <= rst_sdr_sync_ms; + end + + + //------------------------------------------------------------------ + // IDELAY is calibrated using (mandatory) IDELAYCTRL cell. + // Must be feed stable free running clock specified by: FIDELAYCTRL_REF.(200MHz) + // Mandatory async reset required, min pulse of: TIDELAYCTRL_RPW (~60nS) + //------------------------------------------------------------------ + (* IODELAY_GROUP = GROUP *) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL + IDELAYCTRL IDELAYCTRL_i0 ( + .REFCLK (clk200), + .RST (rst_sdr_sync), + .RDY () + ); + + + //------------------------------------------------------------------ + // Clock input + //------------------------------------------------------------------ + wire ddr_clk_dly, ddr_clk_unbuf; + + IBUFDS #( + .DIFF_TERM("TRUE") + ) clk_ibufds ( + .O(ddr_clk_unbuf), + .I(ddr_clk_p), + .IB(ddr_clk_n) + ); + + generate + if (USE_CLOCK_DELAY) begin : gen_clock_delay + (* IODELAY_GROUP = GROUP *) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL + IDELAYE2 #( + .CINVCTRL_SEL ("FALSE"), // Enable dynamic clock inversion (FALSE, TRUE) + .DELAY_SRC ("IDATAIN"), // Delay input (IDATAIN, DATAIN) + .HIGH_PERFORMANCE_MODE ("FALSE"), // Reduced jitter ("TRUE"), Reduced power ("FALSE") + .IDELAY_TYPE (CLOCK_DELAY_MODE), + .IDELAY_VALUE (CLOCK_DELAY), + .PIPE_SEL ("FALSE"), + .REFCLK_FREQUENCY (200.0), + .SIGNAL_PATTERN ("CLOCK") + ) ddr_clk_idelaye2 ( + .CNTVALUEOUT (), // 5-bit output: Counter value output + .DATAOUT (ddr_clk_dly), // 1-bit output: Delayed data output + .C (ctrl_clk), // 1-bit input: Clock input + .CE (1'b0), // 1-bit input: Active high enable increment/decrement input + .CINVCTRL (1'b0), // 1-bit input: Dynamic clock inversion input + .CNTVALUEIN (ctrl_clk_delay), // 5-bit input: Counter value input + .DATAIN (1'b0), // 1-bit input: Internal delay data input + .IDATAIN (ddr_clk_unbuf), // 1-bit input: Data input from the I/O + .INC (1'b0), // 1-bit input: Increment / Decrement tap delay input + .LD (ctrl_ld_clk_delay), // 1-bit input: Load IDELAY_VALUE input + .LDPIPEEN (1'b0), // 1-bit input: Enable PIPELINE register to load data input + .REGRST (1'b0) // 1-bit input: Active-high reset tap-delay input + ); + end + else begin + assign ddr_clk_dly = ddr_clk_unbuf; + end + + endgenerate + + // IO CLock is DDR freq. This drives SERDES and other I/O elements with minimal clock skew. + BUFIO ddr_clk_bufio (.O(ddr_clk),.I(ddr_clk_dly)); + + // SDR clock is one quarter DDR freq and local to regio using BUFR + // BUFR is a constraint of the SERDES since we need frequency agnostic clock division. + // UG471 states can use BUFIO and BUFR divided to directly drive a SERDES legally. + // (Other option is pair of BUFG's plus an MMCM - But MMCM has fixed frequency) + wire sdr_clk_2x; + + BUFR #( + .BUFR_DIVIDE ("2"), + .SIM_DEVICE ("7SERIES") + ) sdr_clk_2x_bufr ( + .O (sdr_clk_2x), + .CE (1'b1), + .CLR (1'b0), + .I (ddr_clk_dly) + ); + + BUFR #( + .BUFR_DIVIDE("4"), + .SIM_DEVICE("7SERIES") + ) sdr_clk_bufr ( + .O(sdr_clk), + .CE(1'b1), + .CLR(1'b0), + .I(ddr_clk_dly) + ); + + generate + if (USE_BUFG) begin : gen_BUFG + // radio_clock is sdr_clk re-buffered with BUFG, and radio_clk_2x is + // sdr_clk_2x re-buffered, so both can be used globally. This introduces skew + // between sdr_clk -> radio_clock so we must hand data between them carefully + // even though they have a fixed phase relationship. + BUFG radio_clk_1x_bufg (.O(radio_clk), .I(sdr_clk)); + BUFG radio_clk_2x_bufg (.O(radio_clk_2x), .I(sdr_clk_2x)); + end else begin + assign radio_clk = sdr_clk; + assign radio_clk_2x = sdr_clk_2x; + end + endgenerate + + + + //------------------------------------------------------------------ + // Frame Signal + //------------------------------------------------------------------ + wire ddr_frame, ddr_frame_dly; + wire [7:0] des_frame; // deserialized frame signal + reg bitslip; + reg aligned; + + + // + // Use FRAME signal to get bitstream word aligned. + // + // In MIMO mode, FRAME is asserted during the entirety of channel 0, and + // deasserts during the entirety of channel 1. + // + localparam IDLE = 0; + localparam SEARCH = 1; + localparam SLIP1 = 3; + localparam SLIP2 = 2; + localparam SLIP3 = 4; + localparam SLIP4 = 5; + localparam SYNC = 6; + + + reg [2:0] frame_state; + + // + // Delay start of framesync operation for 64 clocks after reset de-asserts to + // SERDES to be sure they are in a steady state. + // + // Each time we assert bitslip we then have to wait 2 cycles before we can + // examine the results. + // + // Checking for 0xF0 and 0xCC allows us to support 1R1T and 2R2T timing, + // which have different frame periods. + wire frame_is_aligned = + (!frame_sample && (des_frame[7:0] == (INVERT_FRAME_RX ? 8'h0F : 8'hF0))) || + ( frame_sample && (des_frame[7:0] == (INVERT_FRAME_RX ? 8'h33 : 8'hCC))); + + reg [5:0] sync_delay; + reg run_sync; + + + always @(posedge sdr_clk) + if (rst_sdr_sync) begin + sync_delay <= 6'h0; + run_sync <= 1'b0; + end else if (sync_delay == 6'h3F) + run_sync <= 1'b1; + else + sync_delay <= sync_delay + 1'b1; + + always @(posedge sdr_clk) + begin + if (!run_sync) begin + frame_state <= IDLE; + bitslip <= 1'b0; + aligned <= 1'b0; + end else begin + case (frame_state) + IDLE: begin + bitslip <= 1'b0; + aligned <= 1'b0; + frame_state <= SEARCH; + end + + SEARCH: begin + if (frame_is_aligned) begin + frame_state <= SYNC; + bitslip <= 1'b0; + aligned <= 1'b1; + end else begin + // Bitslip until captured frame is aligned + bitslip <= 1'b1; + frame_state <= SLIP1; + aligned <= 1'b0; + end + end + + SLIP1: begin + frame_state <= SLIP2; + bitslip <= 1'b0; + aligned <= 1'b0; + end + + SLIP2: begin + frame_state <= SLIP3; + bitslip <= 1'b0; + aligned <= 1'b0; + end + + SLIP3: begin + frame_state <= SLIP4; + bitslip <= 1'b0; + aligned <= 1'b0; + end + + SLIP4: begin + frame_state <= SEARCH; + bitslip <= 1'b0; + aligned <= 1'b0; + end + + SYNC: begin + if (frame_is_aligned) begin + frame_state <= SYNC; + aligned <= 1'b1; + end else begin + frame_state <= SEARCH; + aligned <= 1'b0; + end + end + + endcase // case(frame_state) + + end + end + + + IBUFDS #( + .DIFF_TERM ("TRUE") + ) ddr_frame_ibufds ( + .O (ddr_frame), + .I (ddr_frame_p), + .IB (ddr_frame_n) + ); + + generate + if (USE_DATA_DELAY) begin : gen_frame_delay + (* IODELAY_GROUP = GROUP *) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL + IDELAYE2 #( + .CINVCTRL_SEL ("FALSE"), // Enable dynamic clock inversion (FALSE, TRUE) + .DELAY_SRC ("IDATAIN"), // Delay input (IDATAIN, DATAIN) + .HIGH_PERFORMANCE_MODE ("FALSE"), // Reduced jitter ("TRUE"), Reduced power ("FALSE") + .IDELAY_TYPE (DATA_DELAY_MODE), + .IDELAY_VALUE (DATA_DELAY), + .PIPE_SEL ("FALSE"), + .REFCLK_FREQUENCY (200.0), + .SIGNAL_PATTERN ("DATA") + ) ddr_frame_idelaye2 ( + .CNTVALUEOUT (), // 5-bit output: Counter value output + .DATAOUT (ddr_frame_dly), // 1-bit output: Delayed data output + .C (ctrl_clk), // 1-bit input: Clock input + .CE (1'b0), // 1-bit input: Active high enable increment/decrement input + .CINVCTRL (1'b0), // 1-bit input: Dynamic clock inversion input + .CNTVALUEIN (ctrl_data_delay), // 5-bit input: Counter value input + .DATAIN (1'b0), // 1-bit input: Internal delay data input + .IDATAIN (ddr_frame), // 1-bit input: Data input from the I/O + .INC (1'b0), // 1-bit input: Increment / Decrement tap delay input + .LD (ctrl_ld_data_delay), // 1-bit input: Load IDELAY_VALUE input + .LDPIPEEN (1'b0), // 1-bit input: Enable PIPELINE register to load data input + .REGRST (1'b0) // 1-bit input: Active-high reset tap-delay input + ); + end + else begin + assign ddr_frame_dly = ddr_frame; + end + endgenerate + + ISERDESE2 #( + .DATA_RATE ("DDR"), // DDR, SDR + .DATA_WIDTH (8), // Parallel data width (2-8,10,14) + .DYN_CLKDIV_INV_EN ("FALSE"), // Enable DYNCLKDIVINVSEL inversion (FALSE, TRUE) + .DYN_CLK_INV_EN ("FALSE"), // Enable DYNCLKINVSEL inversion (FALSE, TRUE) + // INIT_Q1 - INIT_Q4: Initial value on the Q outputs (0/1) + .INIT_Q1 (1'b0), + .INIT_Q2 (1'b0), + .INIT_Q3 (1'b0), + .INIT_Q4 (1'b0), + .INTERFACE_TYPE ("NETWORKING"), + .IOBDELAY ("BOTH"), + .NUM_CE (1), + .OFB_USED ("FALSE"), + .SERDES_MODE ("MASTER"), + // SRVAL_Q1 - SRVAL_Q4: Q output values when SR is used (0/1) + .SRVAL_Q1 (1'b0), + .SRVAL_Q2 (1'b0), + .SRVAL_Q3 (1'b0), + .SRVAL_Q4 (1'b0) + ) ddr_frame_serdese2 ( + .O (), // 1-bit output: Combinatorial output + // Q1 - Q8: 1-bit (each) output: Registered data outputs + .Q1 (des_frame[0]), + .Q2 (des_frame[1]), + .Q3 (des_frame[2]), + .Q4 (des_frame[3]), + .Q5 (des_frame[4]), + .Q6 (des_frame[5]), + .Q7 (des_frame[6]), + .Q8 (des_frame[7]), + // SHIFTOUT1, SHIFTOUT2: 1-bit (each) output: Data width expansion output ports + .SHIFTOUT1 (), + .SHIFTOUT2 (), + // 1-bit input: The BITSLIP pin performs a Bitslip operation synchronous to + // CLKDIV when asserted (active High). Subsequently, the data seen on the Q1 + // to Q8 output ports will shift, as in a barrel-shifter operation, one + // position every time Bitslip is invoked (DDR operation is different from SDR) + .BITSLIP (bitslip), + // CE1, CE2: 1-bit (each) input: Data register clock enable inputs + .CE1 (1'b1), + .CE2 (1'b1), + .CLKDIVP (1'b0), // 1-bit input: TBD + // Clocks: 1-bit (each) input: ISERDESE2 clock input ports + .CLK (ddr_clk), // 1-bit input: High-speed clock + .CLKB (~ddr_clk), // 1-bit input: High-speed secondary clock + .CLKDIV (sdr_clk), // 1-bit input: Divided clock + .OCLK (1'b0), // 1-bit input: High-speed output clock used when INTERFACE_TYPE="MEMORY" + // Dynamic Clock Inversions: 1-bit (each) input: Dynamic clock inversion pins to switch clock polarity + .DYNCLKDIVSEL (1'b0), // 1-bit input: Dynamic CLKDIV inversion + .DYNCLKSEL (1'b0), // 1-bit input: Dynamic CLK/CLKB inversion + // Input Data: 1-bit (each) input: ISERDESE2 data input ports + .D (1'b0), // 1-bit input: Data input + .DDLY (ddr_frame_dly), // 1-bit input: Serial data from IDELAYE2 + .OFB (1'b0), // 1-bit input: Data feedback from OSERDESE2 + .OCLKB (1'b0), // 1-bit input: High-speed negative edge output clock + .RST (rst_sdr_sync), // 1-bit input: Active high asynchronous reset + // SHIFTIN1, SHIFTIN2: 1-bit (each) input: Data width expansion input ports + .SHIFTIN1 (1'b0), + .SHIFTIN2 (1'b0) + ); + + + //------------------------------------------------------------------ + // Data Bus + //------------------------------------------------------------------ + wire [WIDTH-1:0] ddr_data; + wire [WIDTH-1:0] ddr_data_dly; + wire [(WIDTH*2)-1:0] data_i0, data_i1; + wire [(WIDTH*2)-1:0] data_q0, data_q1; + + + genvar i; + generate + for (i=0 ; i<WIDTH ; i=i+1) begin : generate_data_bus + + IBUFDS #( + .DIFF_TERM ("TRUE") + ) ddr_data_ibufds ( + .O (ddr_data[i]), + .I (ddr_data_p[i]), + .IB (ddr_data_n[i]) + ); + + if (USE_DATA_DELAY) begin : gen_data_delay + (* IODELAY_GROUP = GROUP *) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL + IDELAYE2 #( + .CINVCTRL_SEL ("FALSE"), // Enable dynamic clock inversion (FALSE, TRUE) + .DELAY_SRC ("IDATAIN"), // Delay input (IDATAIN, DATAIN) + .HIGH_PERFORMANCE_MODE ("FALSE"), // Reduced jitter ("TRUE"), Reduced power ("FALSE") + .IDELAY_TYPE (DATA_DELAY_MODE), + .IDELAY_VALUE (DATA_DELAY), + .PIPE_SEL ("FALSE"), + .REFCLK_FREQUENCY (200.0), + .SIGNAL_PATTERN ("DATA") + ) ddr_data_idelaye2 ( + .CNTVALUEOUT (), // 5-bit output: Counter value output + .DATAOUT (ddr_data_dly[i]), // 1-bit output: Delayed data output + .C (ctrl_clk), // 1-bit input: Clock input + .CE (1'b0), // 1-bit input: Active high enable increment/decrement input + .CINVCTRL (1'b0), // 1-bit input: Dynamic clock inversion input + .CNTVALUEIN (ctrl_data_delay), // 5-bit input: Counter value input + .DATAIN (1'b0), // 1-bit input: Internal delay data input + .IDATAIN (ddr_data[i]), // 1-bit input: Data input from the I/O + .INC (1'b0), // 1-bit input: Increment / Decrement tap delay input + .LD (ctrl_ld_data_delay), // 1-bit input: Load IDELAY_VALUE input + .LDPIPEEN (1'b0), // 1-bit input: Enable PIPELINE register to load data input + .REGRST (1'b0) // 1-bit input: Active-high reset tap-delay input + ); + end + else begin + assign ddr_data_dly[i] = ddr_data[i]; + end + + ISERDESE2 #( + .DATA_RATE ("DDR"), // DDR, SDR + .DATA_WIDTH (8), // Parallel data width (2-8,10,14) + .DYN_CLKDIV_INV_EN ("FALSE"), // Enable DYNCLKDIVINVSEL inversion (FALSE, TRUE) + .DYN_CLK_INV_EN ("FALSE"), // Enable DYNCLKINVSEL inversion (FALSE, TRUE) + // INIT_Q1 - INIT_Q4: Initial value on the Q outputs (0/1) + .INIT_Q1 (1'b0), + .INIT_Q2 (1'b0), + .INIT_Q3 (1'b0), + .INIT_Q4 (1'b0), + .INTERFACE_TYPE ("NETWORKING"), + .IOBDELAY ("BOTH"), + .NUM_CE (1), + .OFB_USED ("FALSE"), + .SERDES_MODE ("MASTER"), + // SRVAL_Q1 - SRVAL_Q4: Q output values when SR is used (0/1) + .SRVAL_Q1 (1'b0), + .SRVAL_Q2 (1'b0), + .SRVAL_Q3 (1'b0), + .SRVAL_Q4 (1'b0) + ) ddr_data_serdese2 ( + .O (), // 1-bit output: Combinatorial output + // Q1 - Q8: 1-bit (each) output: Registered data outputs + .Q1 (data_q1[i]), + .Q2 (data_i1[i]), + .Q3 (data_q1[WIDTH+i]), + .Q4 (data_i1[WIDTH+i]), + .Q5 (data_q0[i]), + .Q6 (data_i0[i]), + .Q7 (data_q0[WIDTH+i]), + .Q8 (data_i0[WIDTH+i]), + // SHIFTOUT1, SHIFTOUT2: 1-bit (each) output: Data width expansion output ports + .SHIFTOUT1 (), + .SHIFTOUT2 (), + // 1-bit input: The BITSLIP pin performs a Bitslip operation synchronous to + // CLKDIV when asserted (active High). Subsequently, the data seen on the Q1 + // to Q8 output ports will shift, as in a barrel-shifter operation, one + // position every time Bitslip is invoked (DDR operation is different from SDR) + .BITSLIP (bitslip), + // CE1, CE2: 1-bit (each) input: Data register clock enable inputs + .CE1 (1'b1), + .CE2 (1'b1), + .CLKDIVP (1'b0), // 1-bit input: TBD + // Clocks: 1-bit (each) input: ISERDESE2 clock input ports + .CLK (ddr_clk), // 1-bit input: High-speed clock + .CLKB (~ddr_clk), // 1-bit input: High-speed secondary clock + .CLKDIV (sdr_clk), // 1-bit input: Divided clock + .OCLK (1'b0), // 1-bit input: High-speed output clock used when INTERFACE_TYPE="MEMORY" + // Dynamic Clock Inversions: 1-bit (each) input: Dynamic clock inversion pins to switch clock polarity + .DYNCLKDIVSEL (1'b0), // 1-bit input: Dynamic CLKDIV inversion + .DYNCLKSEL (1'b0), // 1-bit input: Dynamic CLK/CLKB inversion + // Input Data: 1-bit (each) input: ISERDESE2 data input ports + .D (1'b0), // 1-bit input: Data input + .DDLY (ddr_data_dly[i]), // 1-bit input: Serial data from IDELAYE2 + .OFB (1'b0), // 1-bit input: Data feedback from OSERDESE2 + .OCLKB (1'b0), // 1-bit input: High-speed negative edge output clock + .RST (rst_sdr_sync), // 1-bit input: Active high asynchronous reset + // SHIFTIN1, SHIFTIN2: 1-bit (each) input: Data width expansion input ports + .SHIFTIN1 (1'b0), + .SHIFTIN2 (1'b0) + ); + + end // block: generate_data_bus + endgenerate + + // + // Cross these cycles to radio_clk using negative edge. This give 1/2 a radio + // clock period + BUFG insertion delay for signals to propagate. Thats > 6nS. + // + reg [(WIDTH*2)-1:0] radio_data_i0, radio_data_i1, radio_data_q0, radio_data_q1; + reg radio_aligned; + + always @(negedge radio_clk) + begin + radio_data_i0[(WIDTH*2)-1:0] <= data_i0[(WIDTH*2)-1:0] ^ {INVERT_DATA_RX,INVERT_DATA_RX}; + radio_data_q0[(WIDTH*2)-1:0] <= data_q0[(WIDTH*2)-1:0] ^ {INVERT_DATA_RX,INVERT_DATA_RX}; + radio_data_i1[(WIDTH*2)-1:0] <= data_i1[(WIDTH*2)-1:0] ^ {INVERT_DATA_RX,INVERT_DATA_RX}; + radio_data_q1[(WIDTH*2)-1:0] <= data_q1[(WIDTH*2)-1:0] ^ {INVERT_DATA_RX,INVERT_DATA_RX}; + radio_aligned <= aligned; + end + + always @(posedge radio_clk) + begin + i0 <= radio_data_i0; + q0 <= radio_data_q0; + if (mimo) { i1, q1 } <= { radio_data_i1, radio_data_q1 }; + else { i1, q1 } <= { radio_data_i0, radio_data_q0 }; // dup single valid channel to both radios + rx_aligned <= radio_aligned; + end + + /******************************************************************* + * Debug only logic below here. + ******************************************************************/ +/*-----\/----- EXCLUDED -----\/----- + (* keep = "true", max_fanout = 10 *) reg [7:0] des_frame_reg; + (* keep = "true", max_fanout = 10 *) reg rst_sdr_sync_reg; + (* keep = "true", max_fanout = 10 *) reg run_sync_reg; + (* keep = "true", max_fanout = 10 *) reg bitslip_reg; + (* keep = "true", max_fanout = 10 *) reg aligned_reg; + (* keep = "true", max_fanout = 10 *) reg [2:0] frame_state_reg; + + always @(posedge sdr_clk) + begin + des_frame_reg <= des_frame; + rst_sdr_sync_reg <= rst_sdr_sync; + run_sync_reg <= run_sync; + bitslip_reg <= bitslip; + aligned_reg <= aligned; + frame_state_reg <= frame_state; + end + + ila64 ila64_i ( + .clk(sdr_clk), // input clk + .probe0( + { + des_frame_reg, + rst_sdr_sync_reg, + run_sync_reg, + bitslip_reg, + aligned_reg, + frame_state_reg + } + ) + ); + -----/\----- EXCLUDED -----/\----- */ + +endmodule + |
