From 125a843908a2828ee96a9676adef42fd01adf7df Mon Sep 17 00:00:00 2001 From: David Michaeli Date: Mon, 3 Jul 2023 14:40:33 +0300 Subject: [PATCH] update lvds tx verilog --- firmware/lvds_rx.v | 17 ++++--- firmware/lvds_tx.v | 115 ++++++++++++++++++++++++++++++++++++-------- firmware/smi_ctrl.v | 19 ++++++-- firmware/sys_ctrl.v | 19 +++++++- firmware/top.v | 67 ++++++++++---------------- 5 files changed, 164 insertions(+), 73 deletions(-) diff --git a/firmware/lvds_rx.v b/firmware/lvds_rx.v index 86432c7..8ede82e 100644 --- a/firmware/lvds_rx.v +++ b/firmware/lvds_rx.v @@ -5,7 +5,7 @@ module lvds_rx ( input i_fifo_full, output o_fifo_write_clk, - output reg o_fifo_push, + output o_fifo_push, output reg [31:0] o_fifo_data, input i_sync_input, output [ 1:0] o_debug_state @@ -44,23 +44,25 @@ module lvds_rx ( state_idle: begin if (i_ddr_data == modem_i_sync) begin r_state_if <= state_i_phase; - o_fifo_data[1:0] <= 2'b10; + o_fifo_data <= {30'b000000000000000000000000000000, i_ddr_data}; r_sync_input <= i_sync_input; // mark the sync input for this sample end - r_phase_count <= 3'b110; + r_phase_count <= 3'b111; o_fifo_push <= 1'b0; end state_i_phase: begin - if (r_phase_count == 3'b111) begin + if (r_phase_count == 3'b000) begin if (i_ddr_data == modem_q_sync) begin + r_phase_count <= 3'b110; r_state_if <= state_q_phase; end else begin r_state_if <= state_idle; end - end + end else begin r_phase_count <= r_phase_count - 1; + end o_fifo_push <= 1'b0; o_fifo_data <= {o_fifo_data[29:0], i_ddr_data}; end @@ -69,12 +71,13 @@ module lvds_rx ( if (r_phase_count == 3'b000) begin o_fifo_push <= ~i_fifo_full; r_state_if <= state_idle; + o_fifo_data <= {o_fifo_data[29:0], i_ddr_data[1], r_sync_input}; end else begin o_fifo_push <= 1'b0; + r_phase_count <= r_phase_count - 1; + o_fifo_data <= {o_fifo_data[29:0], i_ddr_data}; end - o_fifo_data <= {o_fifo_data[29:0], i_ddr_data}; - r_phase_count <= r_phase_count - 1; end endcase end diff --git a/firmware/lvds_tx.v b/firmware/lvds_tx.v index c5de798..ff21be2 100644 --- a/firmware/lvds_tx.v +++ b/firmware/lvds_tx.v @@ -1,51 +1,124 @@ module lvds_tx ( input i_rst_b, input i_ddr_clk, - output [1:0] o_ddr_data, + output reg[1:0] o_ddr_data, input i_fifo_empty, output o_fifo_read_clk, - output reg o_fifo_pull, + output o_fifo_pull, input [31:0] i_fifo_data, + input [3:0] i_sample_gap, input i_tx_state, input i_sync_input, - output [ 1:0] o_debug_state + input i_debug_lb, + output o_tx_state_bit, + output o_sync_state_bit, ); + // STATES and PARAMS + localparam + tx_state_sync = 1'b0, + tx_state_tx = 1'b1; + localparam sync_duration_frames = 4'd10; // at least 2.5usec + localparam zero_frame = 32'b00000000_00000000_00000000_00000000; + localparam lb_frame = 32'b10000100_00000011_01110000_01001000; // Internal Registers - reg [ 4:0] r_phase_count; + reg [3:0] r_sync_count; + wire frame_pull_clock; + wire frame_assign_clock; + reg r_state; + reg [3:0] r_phase_count; reg [31:0] r_fifo_data; + reg r_pulled; + reg r_schedule_zero_frame; // Initial conditions initial begin - r_phase_count = 5'd31; + r_phase_count = 4'd15; + r_fifo_data <= zero_frame; end assign o_fifo_read_clk = i_ddr_clk; + assign o_tx_state_bit = r_state; + assign o_sync_state_bit = 1'b0; + assign o_fifo_pull = r_pulled; - - // Main Process / shift register + // SHIFT REGISTER + always @(posedge i_ddr_clk) begin + if (i_rst_b == 1'b0) begin + r_phase_count <= 4'd15; + end else begin + o_ddr_data[1:0] <= r_fifo_data[2*r_phase_count+1 : 2*r_phase_count]; + r_phase_count <= r_phase_count - 1; + end + end + // SYNC AND MANAGEMENT always @(posedge i_ddr_clk) begin if (i_rst_b == 1'b0) begin - o_fifo_pull <= 1'b0; - r_phase_count <= 5'd31; - r_fifo_data <= 32'b00000000000000000000000000000000; + r_state <= tx_state_sync; + r_pulled <= 1'b0; + r_fifo_data <= zero_frame; + r_sync_count <= sync_duration_frames; + r_schedule_zero_frame <= 1'b0; end else begin - if (r_phase_count == 5'd3) begin - o_fifo_pull <= ~i_fifo_empty; - end else if (r_phase_count == 5'd1) begin - if (i_tx_state) begin - r_fifo_data <= i_fifo_data; + case (r_state) + //---------------------------------------------- + tx_state_sync: + begin + if (r_phase_count == 4'd0) begin + if (r_schedule_zero_frame) begin + r_fifo_data <= zero_frame; + r_schedule_zero_frame <= 1'b0; + end + end else if (r_phase_count == 4'd1) begin + if (r_sync_count == 4'd0) begin + if (i_debug_lb && !i_tx_state) begin + r_fifo_data <= lb_frame; + r_state <= tx_state_sync; + end else if (!i_debug_lb && i_tx_state) begin + r_pulled <= !i_fifo_empty; + r_state <= tx_state_tx; + end else begin + r_sync_count <= sync_duration_frames; + r_state <= tx_state_sync; + r_fifo_data <= zero_frame; + end end else begin - r_fifo_data <= 32'b00000000000000000000000000000000; + r_sync_count <= r_sync_count - 1; + r_schedule_zero_frame <= 1'b1; + //r_fifo_data <= zero_frame; + r_state <= tx_state_sync; end - o_fifo_pull <= 1'b0; + end + end + //---------------------------------------------- + tx_state_tx: + begin + if (i_debug_lb || !i_tx_state) begin + r_state <= tx_state_sync; + r_sync_count <= sync_duration_frames; + r_pulled <= 1'b0; + end else if (r_phase_count == 4'd1) begin + r_pulled <= !i_fifo_empty; + r_state <= tx_state_tx; + end else if (r_phase_count == 4'd0) begin + if (r_pulled == 1'b0) begin + r_sync_count <= sync_duration_frames; + r_fifo_data <= zero_frame; + r_state <= tx_state_sync; end else begin - o_fifo_pull <= 1'b0; + r_fifo_data <= i_fifo_data; + if (i_sample_gap > 0) begin + r_sync_count <= i_sample_gap; + r_state <= tx_state_sync; + end else begin + r_state <= tx_state_tx; + end + end + r_pulled <= 1'b0; end - - o_ddr_data <= r_fifo_data[r_phase_count:r_phase_count-1]; - r_phase_count <= r_phase_count - 2; + end + endcase end end diff --git a/firmware/smi_ctrl.v b/firmware/smi_ctrl.v index 127c031..520dc39 100644 --- a/firmware/smi_ctrl.v +++ b/firmware/smi_ctrl.v @@ -2,7 +2,6 @@ module smi_ctrl ( input i_rst_b, input i_sys_clk, // FPGA Clock - input i_fast_clk, input [4:0] i_ioc, input [7:0] i_data_in, @@ -30,6 +29,7 @@ module smi_ctrl output o_smi_write_req, input i_smi_test, output o_channel, + output o_dir, // TX CONDITIONAL output reg o_cond_tx, @@ -43,7 +43,8 @@ module smi_ctrl localparam ioc_module_version = 5'b00000, // read only ioc_fifo_status = 5'b00001, // read-only - ioc_channel_select = 5'b00010; + ioc_channel_select = 5'b00010, + ioc_dir_select = 5'b00011; // --------------------------------- // MODULE SPECIFIC PARAMS @@ -55,10 +56,13 @@ module smi_ctrl // MODULE CONTROL // --------------------------------------- assign o_channel = r_channel; + assign o_dir = r_dir; always @(posedge i_sys_clk or negedge i_rst_b) begin if (i_rst_b == 1'b0) begin o_address_error <= 1'b0; + r_dir <= 1'b0; + r_channel <= 1'b0; end else begin if (i_cs == 1'b1) begin //============================================= @@ -75,7 +79,8 @@ module smi_ctrl o_data_out[1] <= i_tx_fifo_full; o_data_out[2] <= r_channel; o_data_out[3] <= i_smi_test; - o_data_out[7:4] <= 4'b0000; + o_data_out[4] <= r_dir; + o_data_out[7:4] <= 3'b000; end endcase end @@ -88,6 +93,10 @@ module smi_ctrl ioc_channel_select: begin r_channel <= i_data_in[0]; end + //---------------------------------------------- + ioc_dir_select: begin + r_dir <= i_data_in[0]; + end endcase end end @@ -104,6 +113,7 @@ module smi_ctrl reg r_fifo_pull_1; wire w_fifo_pull_trigger; reg r_channel; + reg r_dir; reg [31:0] r_fifo_pulled_data; wire soe_and_reset; @@ -169,6 +179,8 @@ module smi_ctrl reg r_fifo_push; reg r_fifo_push_1; wire w_fifo_push_trigger; + wire swe_and_reset; + assign o_smi_write_req = !i_tx_fifo_full; assign o_tx_fifo_push = !r_fifo_push_1 && r_fifo_push && !i_tx_fifo_full; assign swe_and_reset = i_rst_b & i_smi_swe_srw; @@ -235,6 +247,7 @@ module smi_ctrl begin if (i_smi_data_in[7] == 1'b0) begin o_tx_fifo_pushed_data <= {r_fifo_pushed_data[31:8], i_smi_data_in[6:0], 1'b0}; + //o_tx_fifo_pushed_data <= {i_smi_data_in[6:0], 1'b0, r_fifo_pushed_data[15:8], r_fifo_pushed_data[23:16], r_fifo_pushed_data[31:24]}; //o_tx_fifo_pushed_data <= {2'b10, cnt, 1'b1, 2'b01, 13'h3F, 1'b0}; //o_tx_fifo_pushed_data <= {cnt, cnt, 6'b111111}; //cnt <= cnt + 1024; diff --git a/firmware/sys_ctrl.v b/firmware/sys_ctrl.v index 7c78bc7..4c3c85c 100644 --- a/firmware/sys_ctrl.v +++ b/firmware/sys_ctrl.v @@ -14,6 +14,8 @@ module sys_ctrl output o_debug_fifo_push, output o_debug_fifo_pull, output o_debug_smi_test, + output o_debug_loopback_tx, + output [3:0] o_tx_sample_gap, ); // MODULE SPECIFIC IOC LIST @@ -23,7 +25,8 @@ module sys_ctrl ioc_system_version = 5'b00001, // read only ioc_manu_id = 5'b00010, // read only ioc_error_state = 5'b00011, // read only - ioc_debug_modes = 5'b00101; // write only + ioc_debug_modes = 5'b00101, // write only + ioc_tx_sample_gap = 5'b00110; // read / write // MODULE SPECIFIC PARAMS // ---------------------- @@ -37,6 +40,8 @@ module sys_ctrl reg debug_fifo_push; reg debug_fifo_pull; reg debug_smi_test; + reg debug_loopback_tx; + reg [3:0] tx_sample_gap; assign o_debug_fifo_push = debug_fifo_push; assign o_debug_fifo_pull = debug_fifo_pull; @@ -51,6 +56,8 @@ module sys_ctrl debug_fifo_push <= 1'b0; debug_fifo_pull <= 1'b0; debug_smi_test <= 1'b0; + debug_loopback_tx <= 1'b0; + tx_sample_gap <= 4'd0; end else if (i_cs == 1'b1) begin //============================================= // READ OPERATIONS @@ -60,6 +67,11 @@ module sys_ctrl ioc_module_version: o_data_out <= module_version; ioc_system_version: o_data_out <= system_version; ioc_manu_id: o_data_out <= manu_id; + //---------------------------------------------- + ioc_tx_sample_gap: begin + o_data_out[3:0] <= tx_sample_gap; + o_data_out[7:4] <= 4'd0; + end endcase end //============================================= @@ -72,7 +84,12 @@ module sys_ctrl debug_fifo_push <= i_data_in[0]; debug_fifo_pull <= i_data_in[1]; debug_smi_test <= i_data_in[2]; + debug_loopback_tx <= i_data_in[3]; end + //---------------------------------------------- + ioc_tx_sample_gap: begin + tx_sample_gap <= i_data_in[3:0]; + end endcase end end diff --git a/firmware/top.v b/firmware/top.v index e47e694..8b30f66 100644 --- a/firmware/top.v +++ b/firmware/top.v @@ -8,7 +8,7 @@ module top ( input i_glob_clock, - input i_rst_b, // i_smi_a1 + input i_rst_b, // RF FRONT-END PATH output o_rx_h_tx_l, @@ -141,11 +141,14 @@ module top ( .o_debug_fifo_push(), .o_debug_fifo_pull(), .o_debug_smi_test(), + .o_debug_loopback_tx(w_debug_lb_tx), + .o_tx_sample_gap(tx_sample_gap), ); wire w_debug_fifo_push; wire w_debug_fifo_pull; wire w_debug_smi_test; + wire w_debug_lb_tx; // IO CTRL io_ctrl io_ctrl_ins ( @@ -285,21 +288,6 @@ module top ( .D_OUT_1(w_lvds_tx_d0) ); - /*SB_IO #( - .PIN_TYPE(6'b0111_01), - ) tx_clk_neg ( - .PACKAGE_PIN(o_iq_tx_clk_n), - .OUTPUT_CLK(lvds_clock_buf), - .D_OUT_0(lvds_clock_buf), - ); - - SB_IO #( - .PIN_TYPE(6'b0101_01), - ) tx_clk_pos ( - .PACKAGE_PIN(o_iq_tx_clk_p), - .OUTPUT_CLK(lvds_clock_buf), - .D_OUT_0(lvds_clock_buf), - );*/ // Logic on a clock signal is very bad - try to use a dedicated // SB_IO @@ -389,16 +377,18 @@ module top ( wire w_lvds_tx_d1; // 180 degree lvds_tx lvds_tx_inst ( - .i_rst_b(1'b1/*i_rst_b*/), - .i_ddr_clk(lvds_clock_buf), + .i_rst_b(i_rst_b), + .i_ddr_clk(~lvds_clock_buf), .o_ddr_data({w_lvds_tx_d0, w_lvds_tx_d1}), .i_fifo_empty(w_tx_fifo_empty), .o_fifo_read_clk(w_tx_fifo_read_clk), .o_fifo_pull(w_tx_fifo_pull), .i_fifo_data(w_tx_fifo_pulled_data), - .i_tx_state(~i_smi_a2), + .i_sample_gap(tx_sample_gap), + .i_tx_state(~w_smi_data_direction), .i_sync_input(1'b0), - .o_debug_state() + .o_tx_state_bit(), + .o_sync_state_bit(), ); wire w_tx_fifo_full; @@ -409,6 +399,7 @@ module top ( wire [31:0] w_tx_fifo_data; wire w_tx_fifo_pull; wire [31:0] w_tx_fifo_pulled_data; + wire [3:0] tx_sample_gap; complex_fifo #( .ADDR_WIDTH(10), // 1024 samples @@ -434,7 +425,6 @@ module top ( smi_ctrl smi_ctrl_ins ( .i_rst_b(i_rst_b), .i_sys_clk(w_clock_sys), - .i_fast_clk(i_glob_clock), .i_ioc(w_ioc), .i_data_in(w_rx_data), .o_data_out(w_tx_data_smi), @@ -460,6 +450,7 @@ module top ( .o_smi_read_req(w_smi_read_req), .o_smi_write_req(w_smi_write_req), .o_channel(/*channel*/), + .o_dir (w_smi_data_direction), .i_smi_test(1'b0/*w_debug_smi_test*/), .o_cond_tx(), .o_address_error() @@ -469,18 +460,21 @@ module top ( wire [7:0] w_smi_data_input; wire w_smi_read_req; wire w_smi_write_req; + wire w_smi_data_direction; // the "Writing" flag indicates that the data[7:0] direction (inout) // from the FPGA's SMI module should be "output". This happens when the // SMI is in the READ mode - data flows from the FPGA to the RPI (RX mode) // The address has the MSB '1' when in RX mode. otherwise (when IDLE or TX) // the data is high-z, which is the more "recessive" mode + + assign w_smi_data_direction = i_smi_a2; SB_IO #( .PIN_TYPE(6'b1010_01), .PULLUP (1'b0) ) smi_io0 ( .PACKAGE_PIN(io_smi_data[0]), - .OUTPUT_ENABLE(i_smi_a2), + .OUTPUT_ENABLE(w_smi_data_direction), .D_OUT_0(w_smi_data_output[0]), .D_IN_0(w_smi_data_input[0]) ); @@ -489,7 +483,7 @@ module top ( .PULLUP (1'b0) ) smi_io1 ( .PACKAGE_PIN(io_smi_data[1]), - .OUTPUT_ENABLE(i_smi_a2), + .OUTPUT_ENABLE(w_smi_data_direction), .D_OUT_0(w_smi_data_output[1]), .D_IN_0(w_smi_data_input[1]) ); @@ -498,7 +492,7 @@ module top ( .PULLUP (1'b0) ) smi_io2 ( .PACKAGE_PIN(io_smi_data[2]), - .OUTPUT_ENABLE(i_smi_a2), + .OUTPUT_ENABLE(w_smi_data_direction), .D_OUT_0(w_smi_data_output[2]), .D_IN_0(w_smi_data_input[2]) ); @@ -507,7 +501,7 @@ module top ( .PULLUP (1'b0) ) smi_io3 ( .PACKAGE_PIN(io_smi_data[3]), - .OUTPUT_ENABLE(i_smi_a2), + .OUTPUT_ENABLE(w_smi_data_direction), .D_OUT_0(w_smi_data_output[3]), .D_IN_0(w_smi_data_input[3]) ); @@ -516,7 +510,7 @@ module top ( .PULLUP (1'b0) ) smi_io4 ( .PACKAGE_PIN(io_smi_data[4]), - .OUTPUT_ENABLE(i_smi_a2), + .OUTPUT_ENABLE(w_smi_data_direction), .D_OUT_0(w_smi_data_output[4]), .D_IN_0(w_smi_data_input[4]) ); @@ -525,7 +519,7 @@ module top ( .PULLUP (1'b0) ) smi_io5 ( .PACKAGE_PIN(io_smi_data[5]), - .OUTPUT_ENABLE(i_smi_a2), + .OUTPUT_ENABLE(w_smi_data_direction), .D_OUT_0(w_smi_data_output[5]), .D_IN_0(w_smi_data_input[5]) ); @@ -534,7 +528,7 @@ module top ( .PULLUP (1'b0) ) smi_io6 ( .PACKAGE_PIN(io_smi_data[6]), - .OUTPUT_ENABLE(i_smi_a2), + .OUTPUT_ENABLE(w_smi_data_direction), .D_OUT_0(w_smi_data_output[6]), .D_IN_0(w_smi_data_input[6]) ); @@ -543,24 +537,15 @@ module top ( .PULLUP (1'b0) ) smi_io7 ( .PACKAGE_PIN(io_smi_data[7]), - .OUTPUT_ENABLE(i_smi_a2), + .OUTPUT_ENABLE(w_smi_data_direction), .D_OUT_0(w_smi_data_output[7]), .D_IN_0(w_smi_data_input[7]) ); - //assign io_smi_data = (i_smi_a2)?w_smi_data_output:8'bZ; - //assign w_smi_data_input = io_smi_data; + // We need the 'o_smi_write_req' to be 1 only when the direction is TX - // (i_smi_a2 == 0) and the write fifo is not full - assign o_smi_read_req = (i_smi_a2) ? w_smi_read_req : w_smi_write_req; + // (w_smi_data_direction == 0) and the write fifo is not full + assign o_smi_read_req = (w_smi_data_direction) ? w_smi_read_req : w_smi_write_req; assign o_smi_write_req = 1'bZ; - //assign io_pmod[0] = w_rx_fifo_push; - //assign io_pmod[1] = w_rx_fifo_pull; - //assign io_pmod[2] = w_smi_read_req; - //assign io_pmod[3] = w_rx_fifo_full; - //assign io_pmod[4] = w_rx_fifo_empty; - //assign io_pmod[5] = i_smi_a2; - //assign io_pmod[6] = channel; - //assign io_pmod[7] = ...; endmodule // top