📄 rx_client_fifo.v
字号:
// Block Ram for upper address space (rx_addr(11) = '1')
RAMB16_S9_S9 ramgen_u
(
.WEA (rx_mem_enable_u),
.ENA (rx_enable),
.SSRA (rx_reset),
.CLKA (rx_clk),
.ADDRA (rx_addr[10:0]),
.DIA (rx_data_reg),
.DIPA (rx_dv_dv),
.WEB (GND),
.ENB (read_mem_enable_u),
.SSRB (ll_reset),
.CLKB (read_clock_in),
.ADDRB (read_addr[10:0]),
.DIB (GND_BUS[7:0]),
.DIPB (GND_BUS[0:0]),
.DOB (read_data_int_u),
.DOPB (read_dv_dv_u));
//---------------------------------------------------------------------------
// Enable the read from each Block Ram
// **If the FIFO is expanded to use more BRAM, create read_mem_enable signals
// for each BRAM, using read_addr[max:11]**
//---------------------------------------------------------------------------
assign read_mem_enable_u = read_addr_enable_int & read_addr[11];
assign read_mem_enable_l = read_addr_enable_int & !read_addr[11];
//---------------------------------------------------------------------------
// Choose the output data from the Block RAM given the read address and
// convert the parity signal from type std_logic_vector to std_logic.
// **If the FIFO is expanded to use more BRAM, increase the MUX width to take
// in all BRAM data outputs, and select based on read_addr_reg[max:11]**
//---------------------------------------------------------------------------
assign read_data_int = read_addr_reg[11] ? read_data_int_u : read_data_int_l;
assign read_data_valid_int = read_addr_reg[11] ? read_dv_dv_u[0] : read_dv_dv_l[0];
//---------------------------------------------------------------------------
// The block ram output data is registered in the data pipe whenever valid
// data is being read from the block ram
//---------------------------------------------------------------------------
assign read_pipe_enable = read_addr_enable_reg_int;
//---------------------------------------------------------------------------
// Register the output of the Block Ram in a data pipe.
//---------------------------------------------------------------------------
always @(posedge read_clock_in)
begin
if (ll_reset == 1'b1)
begin
read_data_pipe[1] <= 8'h00;
read_data_pipe[0] <= 8'h00;
end
else
begin
if (read_pipe_enable == 1'b1)
begin
read_data_pipe[0] <= read_data_int;
read_data_pipe[1] <= read_data_pipe[0];
end
end
end
always @(posedge read_clock_in)
begin
if (ll_reset == 1'b1)
begin
read_data_valid_pipe[0] <= 8'h00;
read_data_valid_pipe[1] <= 8'h00;
end
else
begin
if (read_pipe_enable == 1'b1)
begin
read_data_valid_pipe[0] <= read_data_valid_int;
read_data_valid_pipe[1] <= read_data_valid_pipe[0];
end
end
end
//---------------------------------------------------------------------------
// Construct the local link control signals from the state of data in the
// output data and data valid pipe. All control signals are active low.
//---------------------------------------------------------------------------
always @(posedge read_clock_in)
begin
if (ll_reset == 1'b1)
begin
sof_out_n_int <= 1'b1;
eof_out_n_int <= 1'b1;
src_rdy_out_n_int <= 1'b1;
end
else
begin
if (read_pipe_enable == 1'b1)
begin
eof_out_n_int <= read_data_valid_int | !read_data_valid_pipe[0];
sof_out_n_int <= read_data_valid_pipe[1] | !read_data_valid_pipe[0];
src_rdy_out_n_int <= !read_data_valid_pipe[0];
end
end
end
//---------------------------------------------------------------------------
// Generate control signal to indicate when a frame is in the process of
// being tranmitted on the interface.
//---------------------------------------------------------------------------
// sending frame signal goes high at sof and low at eof
always @(posedge read_clock_in)
begin
if (ll_reset == 1'b1)
sending_frame <= 1'b0;
else if (read_pipe_enable == 1'b1 && read_data_valid_pipe[1] == 1'b0 && read_data_valid_pipe[0] == 1'b1)
sending_frame <= 1'b1;
else if (read_pipe_enable == 1'b1 && read_data_valid_int == 1'b0 && read_data_valid_pipe[0] == 1'b1)
sending_frame <= 1'b0;
end
// register sending_frame signal but only register a zero signal when data is
// being being accepted by upstream user. This ensures the signal stays high
// until the eof signal has been read by the user.
always @(posedge read_clock_in)
begin
if (ll_reset == 1'b1)
sending_frame_reg <= 1'b0;
else if (sending_frame == 1'b1)
sending_frame_reg <= 1'b1;
else if (sending_frame == 1'b0 && dst_rdy_in_n == 1'b0)
sending_frame_reg <= 1'b0;
end
//---------------------------------------------------------------------------
// Assign Local-link Output Signals
// All control signals are active low
//---------------------------------------------------------------------------
assign data_out = read_data_pipe[1];
assign rem_out = 1'b1;
assign sof_out_n = sof_out_n_int;
assign eof_out_n = eof_out_n_int;
assign src_rdy_out_n = src_rdy_out_n_int | !(sending_frame | sending_frame_reg);
//---------------------------------------------------------------------------
// We need to drop bad frames. Therefore we have to keep a note of the address
// in the fifo that the first byte of data has been written to. This means
// that in the event of a bad frame occuring we can go back to its' first
// byte and write over it with the next frame. By looking at the
// rx_data_valid signal we can see when the gap between the frames is and
// go back to this address when a bad frame indicator is sent.
// **If the FIFO is expanded to use more BRAM, increase start_addr size as
// required **
//---------------------------------------------------------------------------
always @(posedge rx_clk)
begin
if (rx_reset == 1'b1)
start_addr <= 12'h000;
else if (rx_enable == 1'b1)
begin
if (rx_good_frame_reg == 1'b1 && overflow_int_held == 1'b0)
// End address of the last good frame.
start_addr <= rx_addr;
end
end
//---------------------------------------------------------------------------
// Now do the rx_addr generation. We want to count up basically when
// rx_data_valid is high. We also want one cycle where data valid is
// low to seperate the frames. So we'll count up when data_valid or
// data_valid_reg is high.
// **If the FIFO is expanded to use more BRAM, increase rx_addr_int size as
// required **
//---------------------------------------------------------------------------
always @(posedge rx_clk)
begin
if (rx_reset == 1'b1)
rx_addr_int <= 12'h000;
else if (rx_enable == 1'b1)
begin
if (overflow_int_held == 1'b1 || rx_bad_frame_reg == 1'b1)
rx_addr_int <= start_addr;
else if (rx_addr_enable == 1'b1)
rx_addr_int <= rx_addr + 1;
end
end
//--------------------------------------------------------------------
// The receiver address counter is enabled when the data_valid or
// the registered data_valid is high. This will enable the frame data
// and 1 extra empty byte to be stored.
//--------------------------------------------------------------------
assign rx_addr_enable = (rx_data_valid | rx_data_valid_reg) & rx_enable;
assign rx_addr = rx_addr_int;
//---------------------------------------------------------------------------
// A signal that indicates that there has been a frame received
//---------------------------------------------------------------------------
always @(posedge rx_clk)
begin
if (rx_reset == 1'b1)
frame_received_toggle <= 1'b0;
else if (rx_enable == 1'b1)
begin
if (rx_good_frame_reg == 1'b1 && overflow_int_held == 1'b0)
frame_received_toggle <= !(frame_received_toggle);
end
end
//---------------------------------------------------------------------------
// Now on to the read side.
// read_addr will count up when there is a data to be transmitted
// **If the FIFO is expanded to use more BRAM, increase rx_addr_int size as
// required **
//---------------------------------------------------------------------------
always @(posedge read_clock_in)
begin
if (ll_reset == 1'b1)
read_addr_int <= 12'h001;
else if (read_addr_enable_int == 1'b1)
read_addr_int <= read_addr + 1;
end
assign read_addr = read_addr_int;
//--------------------------------------------------------------------
// The read address counter is enabled when there is a frame
// in the FIFO, the data_valid output from the block memory is high,
// the frame is being transmitted, or when the it is necessary to
// 'queue' the data up. This may be necessary to get the first byte of
// the frame at the output of the circuit.
//--------------------------------------------------------------------
assign read_addr_enable = queue ? 1'b1 : (
((frame_in_progress == 1'b1 || frame_transmitted == 1'b1) &&
(read_data_valid_int == 1'b1 || frame_in_fifo == 1'b1) && frame_in_fifo_held == 1'b1) ? 1'b1 : 1'b0);
// The enable signal is held low if the upstream local link user is not
// accepting data, to hold the output of the bram until data at the interface
// is accepted
assign read_addr_enable_int = read_addr_enable & !dst_rdy_in_n;
//---------------------------------------------------------------------------
// Register the address enable signal for use as the data pipe enable.
//---------------------------------------------------------------------------
always @(posedge read_clock_in)
begin
if (ll_reset == 1'b1)
read_addr_enable_reg <= 1'b0;
else if (dst_rdy_in_n == 1'b0)
read_addr_enable_reg <= read_addr_enable;
end
// The pipe enable signal is held low if when the upstream local link user is
// not acceptiong data.
assign read_addr_enable_reg_int = read_addr_enable_reg & !dst_rdy_in_n;
//---------------------------------------------------------------------------
// A signal that indicates that there has been a frame transmitted
//---------------------------------------------------------------------------
always @(posedge read_clock_in)
begin
if (ll_reset == 1'b1)
frame_transmitted <= 1'b0;
else if (dst_rdy_in_n == 1'b0 && frame_in_fifo == 1'b1 && read_data_valid_int == 1'b1 && read_data_valid_pipe[0] == 1'b0)
frame_transmitted <= 1'b1;
else
frame_transmitted <= 1'b0;
end
always @(posedge read_clock_in)
begin
if (ll_reset == 1'b1)
frame_transmitted_reg <= 1'b0;
else
frame_transmitted_reg <= frame_transmitted;
end
// ensure that the frame transmitted signal is only one clock cycle long
assign frame_transmitted_pulse = frame_transmitted & !frame_transmitted_reg;
//--------------------------------------------------------------------
// In order to gauge whether there is a frame in the fifo we have to
// generate a counter that holds the number of frames that are
// present. If a frame is received then we increment this, if one
// is transmitted then we decrement it. The ll_frame_received_toggle
// signal is the frame_received_toggle signal re-clocked onto
// tx_clk. The ll_frame_received signal is asserted for 1 cycle when
// an edge is detected on ll_frame_received_toggle.
//--------------------------------------------------------------------
always @(posedge read_clock_in)
begin
if (ll_reset == 1'b1)
begin
ll_frame_received_toggle <= 3'b000;
ll_frame_received <= 1'b0;
end
else
begin
ll_frame_received_toggle[0] <= frame_received_toggle;
ll_frame_received_toggle[1] <= ll_frame_received_toggle[0];
ll_frame_received_toggle[2] <= ll_frame_received_toggle[1];
ll_frame_received <= ll_frame_received_toggle[2] ^ ll_frame_received_toggle[1];
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -