cariboulabs-cariboulite/firmware/lvds_tx.v

130 wiersze
4.7 KiB
Verilog

module lvds_tx (
input i_rst_b,
input i_ddr_clk,
output reg[1:0] o_ddr_data,
input i_fifo_empty,
output o_fifo_read_clk,
output o_fifo_pull,
input [31:0] i_fifo_data,
input [3:0] i_sample_gap,
input i_tx_state,
input i_sync_input,
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 [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 = 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;
// 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
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
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_sync_count <= r_sync_count - 1;
r_schedule_zero_frame <= 1'b1;
//r_fifo_data <= zero_frame;
r_state <= tx_state_sync;
end
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
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
end
endcase
end
end
endmodule