2024-03-14 11:12:29 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Contribution by matteo serva
|
|
|
|
* https://github.com/matteoserva
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
`include "lvds_clock_sync.v"
|
2023-05-30 11:33:08 +00:00
|
|
|
module lvds_tx (
|
|
|
|
input i_rst_b,
|
|
|
|
input i_ddr_clk,
|
2024-03-14 11:12:29 +00:00
|
|
|
input i_sys_clk, // FPGA Clock
|
2023-07-03 11:40:33 +00:00
|
|
|
output reg[1:0] o_ddr_data,
|
2023-05-30 11:33:08 +00:00
|
|
|
|
|
|
|
input i_fifo_empty,
|
|
|
|
output o_fifo_read_clk,
|
2023-07-03 11:40:33 +00:00
|
|
|
output o_fifo_pull,
|
2024-04-23 10:10:28 +00:00
|
|
|
input [15:0] i_fifo_data,
|
2023-07-03 11:40:33 +00:00
|
|
|
input [3:0] i_sample_gap,
|
2023-05-30 11:33:08 +00:00
|
|
|
input i_tx_state,
|
|
|
|
input i_sync_input,
|
2023-07-03 11:40:33 +00:00
|
|
|
input i_debug_lb,
|
|
|
|
output o_tx_state_bit,
|
|
|
|
output o_sync_state_bit,
|
2024-03-14 11:18:46 +00:00
|
|
|
output o_heartbeat,
|
|
|
|
output [7:0] o_debug_word,
|
|
|
|
input [7:0] i_tx_control_word,
|
2023-05-30 11:33:08 +00:00
|
|
|
);
|
|
|
|
|
2023-07-03 11:40:33 +00:00
|
|
|
// STATES and PARAMS
|
|
|
|
localparam
|
2024-04-23 10:10:28 +00:00
|
|
|
tx_state_init = 4'b0000,
|
2024-03-14 11:18:46 +00:00
|
|
|
tx_state_sync = 4'b0001,
|
|
|
|
tx_state_pretx = 4'b0010,
|
2024-04-23 10:10:28 +00:00
|
|
|
tx_state_tx = 4'b0100,
|
2024-03-14 11:18:46 +00:00
|
|
|
tx_state_debugtx = 4'b1000;
|
|
|
|
|
|
|
|
localparam sync_duration_frames = 8'd10; // at least 2.5usec
|
|
|
|
localparam zero_frame = 32'b00000000_00000000_00000000_00000000;
|
|
|
|
localparam lb_frame = 32'b10000000_00000000_01000000_00000000;
|
|
|
|
localparam sync_frame = 32'b10000000_00000001_01000000_00000000;
|
|
|
|
localparam data_mask = 32'b00111110_11111110_00111111_11111110;
|
|
|
|
localparam test_frame = 32'b00100000_00000000_00010000_00000000;
|
2023-05-30 11:33:08 +00:00
|
|
|
// Internal Registers
|
2024-03-14 11:18:46 +00:00
|
|
|
reg [7:0] r_sync_count;
|
|
|
|
reg [3:0] r_state;
|
|
|
|
|
|
|
|
reg [31:0] r_fifo_data;
|
2023-07-03 11:40:33 +00:00
|
|
|
reg r_pulled;
|
2023-05-16 13:28:08 +00:00
|
|
|
|
2024-03-14 11:18:46 +00:00
|
|
|
|
|
|
|
reg [3:0] reset_shift;
|
|
|
|
|
|
|
|
//bus state check
|
|
|
|
reg [9:0] lvds_start_delay_counter;
|
|
|
|
reg [6:0] lvds_timeout_counter;
|
|
|
|
reg lvds_heartbeat;
|
|
|
|
wire lvds_ready;
|
|
|
|
reg [2:0] lvds_heartbeat_synchronizer;
|
|
|
|
wire lvds_heartbeat_sbe;
|
|
|
|
wire lvds_hearbeat_lost;
|
|
|
|
|
2023-05-30 11:33:08 +00:00
|
|
|
// Initial conditions
|
|
|
|
initial begin
|
2023-07-03 11:40:33 +00:00
|
|
|
r_fifo_data <= zero_frame;
|
2023-05-30 11:33:08 +00:00
|
|
|
end
|
2023-05-16 13:28:08 +00:00
|
|
|
|
2024-03-14 11:18:46 +00:00
|
|
|
assign o_fifo_read_clk = i_ddr_clk;
|
|
|
|
assign o_tx_state_bit = 1'b0;
|
2023-07-03 11:40:33 +00:00
|
|
|
assign o_sync_state_bit = 1'b0;
|
2024-03-14 11:18:46 +00:00
|
|
|
|
|
|
|
assign o_fifo_pull = r_pulled ;
|
|
|
|
assign o_debug_word = {i_sample_gap,r_state};
|
|
|
|
|
2024-03-14 11:12:29 +00:00
|
|
|
wire lvds_ready_syncd;
|
|
|
|
wire w_data_sbe_ddr;
|
|
|
|
lvds_clock_sync lvds_clock_inst (
|
|
|
|
.i_rst_b(i_rst_b),
|
|
|
|
.i_ddr_clk(i_ddr_clk),
|
|
|
|
.i_sys_clk(i_sys_clk),
|
|
|
|
.o_lvds_ready_ddr(lvds_ready_syncd),
|
|
|
|
.o_data_sbe_ddr(w_data_sbe_ddr),
|
|
|
|
);
|
2024-03-14 11:18:46 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
LVDS BUS OUTPUT
|
|
|
|
*/
|
|
|
|
|
|
|
|
reg [32:0] r_fifo_shift;
|
|
|
|
always @(posedge i_ddr_clk) begin
|
|
|
|
|
|
|
|
o_ddr_data[1:0] <= {r_fifo_shift[32], r_fifo_shift[31]};
|
|
|
|
r_fifo_shift <= {r_fifo_shift[30:0], 2'd0};
|
|
|
|
|
|
|
|
if(w_data_sbe_ddr) begin
|
|
|
|
r_fifo_shift[31:0] <= r_fifo_data;
|
|
|
|
lvds_heartbeat <= !lvds_heartbeat;
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2023-05-30 11:33:08 +00:00
|
|
|
|
2024-03-14 11:18:46 +00:00
|
|
|
/*
|
|
|
|
HEARTBEAT
|
|
|
|
*/
|
|
|
|
reg [31:0] r_clock_count;
|
|
|
|
reg r_heartbeat;
|
2023-07-03 11:40:33 +00:00
|
|
|
always @(posedge i_ddr_clk) begin
|
2024-03-14 11:18:46 +00:00
|
|
|
begin
|
|
|
|
r_clock_count <= r_clock_count + 1;
|
|
|
|
r_heartbeat <= r_clock_count[20] && r_clock_count[21] && r_clock_count[22] && r_clock_count[23] && r_clock_count[24] && r_clock_count[25];
|
2023-07-03 11:40:33 +00:00
|
|
|
end
|
|
|
|
end
|
2024-03-14 11:18:46 +00:00
|
|
|
assign o_heartbeat = r_heartbeat;
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-07-03 11:40:33 +00:00
|
|
|
// SYNC AND MANAGEMENT
|
2023-05-30 11:33:08 +00:00
|
|
|
always @(posedge i_ddr_clk) begin
|
2024-03-14 11:18:46 +00:00
|
|
|
if (lvds_ready_syncd == 1'b0) begin
|
2024-04-23 10:10:28 +00:00
|
|
|
r_state <= tx_state_init;
|
|
|
|
r_pulled <= 1'b0;
|
2023-07-03 11:40:33 +00:00
|
|
|
r_fifo_data <= zero_frame;
|
2024-03-14 11:18:46 +00:00
|
|
|
r_sync_count <= 8'd200;
|
2023-05-30 11:33:08 +00:00
|
|
|
end else begin
|
2024-03-14 11:18:46 +00:00
|
|
|
r_pulled <= 1'b0;
|
|
|
|
case (r_state)
|
2024-04-23 10:10:28 +00:00
|
|
|
tx_state_init:
|
|
|
|
if( !i_fifo_empty) begin
|
|
|
|
r_pulled <= i_fifo_data[0];
|
|
|
|
r_state <= tx_state_sync;
|
|
|
|
end
|
2024-03-14 11:18:46 +00:00
|
|
|
tx_state_sync:
|
|
|
|
begin
|
|
|
|
r_fifo_data <= zero_frame;
|
|
|
|
|
|
|
|
if( i_fifo_empty == 1'b1 /*&& i_debug_lb == 1'b0*/ ) begin
|
2023-07-03 11:40:33 +00:00
|
|
|
r_sync_count <= sync_duration_frames;
|
2024-03-14 11:18:46 +00:00
|
|
|
end else if (r_sync_count == 8'd0) begin
|
|
|
|
r_state <= tx_state_pretx;
|
|
|
|
r_pulled <= 1'b1;
|
|
|
|
end else if (w_data_sbe_ddr) begin
|
|
|
|
r_sync_count <= r_sync_count - 1;
|
2023-07-03 11:40:33 +00:00
|
|
|
end
|
2024-03-14 11:18:46 +00:00
|
|
|
|
|
|
|
end
|
|
|
|
tx_state_pretx:
|
|
|
|
begin
|
|
|
|
|
2024-04-23 10:10:28 +00:00
|
|
|
r_state <= tx_state_tx;
|
|
|
|
r_fifo_data[31:16] <= ({2'b00, i_fifo_data[15:2]} & data_mask[31:16]) | (sync_frame[31:16]);
|
|
|
|
r_pulled <= 1'b1;
|
|
|
|
end
|
|
|
|
|
|
|
|
tx_state_tx:
|
|
|
|
begin
|
|
|
|
r_state <= tx_state_debugtx;
|
|
|
|
r_fifo_data[15:0] <= ({2'b00, i_fifo_data[15:2]} & data_mask[15:0]) | (sync_frame[15:0]);
|
|
|
|
r_pulled <= 1'b0;
|
2024-03-14 11:18:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
tx_state_debugtx:
|
|
|
|
begin
|
|
|
|
|
|
|
|
|
|
|
|
if (w_data_sbe_ddr) begin
|
|
|
|
r_state <= tx_state_sync;
|
2023-07-03 11:40:33 +00:00
|
|
|
end
|
2024-04-23 10:10:28 +00:00
|
|
|
r_sync_count <= {4'd0,i_sample_gap};
|
2024-03-14 11:18:46 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
endcase
|
|
|
|
end
|
|
|
|
|
2023-05-30 11:33:08 +00:00
|
|
|
end
|
2023-05-16 13:28:08 +00:00
|
|
|
|
2023-05-30 11:33:08 +00:00
|
|
|
endmodule
|