📄 tx_client_fifo.v
字号:
//--------------------------------------------------------------------
// The RAMB16_S9_S9 primitive defines the parity inputs and outputs
// as signals of type std_logic_vector(0 downto 0). These are
// connected to single bit std_logic signals in the FIFO. The
// following line converts between the different types.
//--------------------------------------------------------------------
assign data_valid_reg[0] = write_data_valid_reg;
//---------------------------------------------------------------------------
// The fifo cannot accept data when delimiting the frame, by writing a zero
// value of data_valid_reg into the memory. Set dst_rdy_out_n to high when
// delimiting frame or when when fifo is full. The signal is also forced to
// zero when the fifo has overflown, so as to flush rest of frame from
// upstream source
//---------------------------------------------------------------------------
assign dst_rdy_out_n = overflow_int_held ? 1'b0 : (
(eof_in_n_reg == 1'b0 && eof_in_n_reg_reg == 1'b1) ? 1'b1 : (
memory_full ? 1'b1 : 1'b0));
//---------------------------------------------------------------------------
// The signal byte_accept indicates when input data is valid. For this to be
// true both src_rdy_in_n and dst_rdy_out_n must be low.
// The signal is active high
//---------------------------------------------------------------------------
assign byte_accept = (eof_in_n_reg == 1'b0 && eof_in_n_reg_reg == 1'b1) ? 1'b0 : (
memory_full ? 1'b0 : (
overflow_int_held ? 1'b0 : (
src_rdy_in_n ? 1'b0 : 1'b1 )));
//---------------------------------------------------------------------------
// In overflow condition the incoming data is to be ignored until the end of
// that frame is reached. Register input data to find end of frame
//---------------------------------------------------------------------------
assign overflow_accept = (overflow_eof_in_n_reg == 1'b0 && overflow_eof_in_n_reg_reg == 1'b1) ? 1'b0 : (
src_rdy_in_n ? 1'b0 : 1'b1 );
always @(posedge write_clock_in)
begin
if (ll_reset == 1'b1)
overflow_eof_in_n_reg <= 1'b1;
else if (overflow_accept == 1'b1)
overflow_eof_in_n_reg <= eof_in_n;
end
always @(posedge write_clock_in)
begin
if (ll_reset == 1'b1)
begin
overflow_eof_in_n_reg_reg <= 1'b1;
overflow_eof_in_n_reg_reg_reg <= 1'b1;
end
else
begin
overflow_eof_in_n_reg_reg <= overflow_eof_in_n_reg;
overflow_eof_in_n_reg_reg_reg <= overflow_eof_in_n_reg_reg;
end
end
//--------------------------------------------------------------------
// The write enable is asserted when the FIFO is receiving valid data
// or storing delimiter byte. Data is written to upper or lower block RAM
// dependant on the value of the upper address bit
// **If the FIFO is expanded to use more BRAM, create write_mem_enable signals
// for to address each BRAM using write_addr[max:11]**
//--------------------------------------------------------------------
assign write_mem_enable = write_data_valid_reg | (!eof_in_n_reg_reg & eof_in_n_reg_reg_reg);
assign write_mem_enable_l = write_mem_enable & !(write_addr[11]);
assign write_mem_enable_u = write_mem_enable & write_addr[11];
//---------------------------------------------------------------------------
// Now write the registered data and data_valid signals into the memory
// on the write clock. Starting and stopping the address will control the
// flow of data into the memory.
//
// **If the FIFO is expanded to use more BRAM, instantiate as below.
// To control the write side, create a write_mem_enable signal for each BRAM as
// above, data inputs and the write_addr[10:0] are common to all BRAMs.
// To control the transmit side, create a tx_mem_enable signal for each BRAM as
// below, and create tx_data_int and tx_dv_dv signals for each BRAM. Mux
// data outputs as shown below. The tx_addr[10:0] is common to all BRAMs.**
//---------------------------------------------------------------------------
// Block Ram for lower address space (write_addr(11) = 0)
RAMB16_S9_S9 ramgen_l
(.WEB (write_mem_enable_l),
.ENB (VCC),
.SSRB (ll_reset),
.CLKB (write_clock_in),
.ADDRB (write_addr[10:0]),
.DIB (data_in_reg),
.DIPB (data_valid_reg),
.WEA (GND),
.ENA (tx_mem_enable_l),
.SSRA (tx_reset),
.CLKA (tx_clk),
.ADDRA (tx_addr[10:0]),
.DIA (GND_BUS),
.DIPA (GND_BUS[0:0]),
.DOA (tx_data_int_l),
.DOPA (tx_dv_dv_l));
// Block Ram for upper address space (write_addr(11) = 1)
RAMB16_S9_S9 ramgen_u
(.WEB (write_mem_enable_u),
.ENB (VCC),
.SSRB (ll_reset),
.CLKB (write_clock_in),
.ADDRB (write_addr[10:0]),
.DIB (data_in_reg),
.DIPB (data_valid_reg),
.WEA (GND),
.ENA (tx_mem_enable_u),
.SSRA (tx_reset),
.CLKA (tx_clk),
.ADDRA (tx_addr[10:0]),
.DIA (GND_BUS),
.DIPA (GND_BUS[0:0]),
.DOA (tx_data_int_u),
.DOPA (tx_dv_dv_u));
//--------------------------------------------------------------------
// 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 tx_addr_reg[max:11]**
//--------------------------------------------------------------------
assign tx_data_valid_int = tx_addr_reg[11] ? tx_dv_dv_u[0] : tx_dv_dv_l[0];
assign tx_data_int = tx_addr_reg[11] ? tx_data_int_u : tx_data_int_l;
//--------------------------------------------------------------------
// The read enable for the memory is asserted whenever there is a frame in
// the fifo to be read out. Data is read from the upper or lower block RAM
// given by the top bit of the read address.
// **If the FIFO is expanded to use more BRAM, create tx_mem_enable signals
// for each BRAM, using tx_addr[max:11]**
//--------------------------------------------------------------------
assign tx_mem_enable = ((frame_in_fifo | frame_in_fifo_held) | queue_for_retransmit) & tx_enable;
assign tx_mem_enable_l = tx_mem_enable & !tx_addr[11];
assign tx_mem_enable_u = tx_mem_enable & tx_addr[11];
//---------------------------------------------------------------------------
// Register the output of the block ram. Derive the client output signals
// from the data.
//---------------------------------------------------------------------------
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
begin
tx_data_pipe <= 8'h00;
tx_data_valid_reg <= 1'b0;
end
else if (tx_enable == 1'b1)
begin
if (tx_ack == 1'b1 || tx_addr_enable_reg == 1'b1)
begin
tx_data_pipe <= tx_data_int;
tx_data_valid_reg <= tx_data_valid_int;
end
end
end
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
tx_data_valid_pipe <= 1'b0;
else if (tx_enable == 1'b1)
tx_data_valid_pipe <= tx_data_valid_int;
end
assign tx_data = tx_data_pipe;
assign tx_data_valid = tx_data_valid_reg & (frame_in_fifo_held | queue_for_retransmit_held)
& !(col_no_retransmit);
//---------------------------------------------------------------------------
// We need to drop frames if the FIFO is overloaded. 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 an oversize frame being written
// we can go back to its' first byte and write over it with the next frame.
// **If the FIFO is expanded to use more BRAM, increase start_addr size as
// required **
//---------------------------------------------------------------------------
always @(posedge write_clock_in)
begin
if (ll_reset == 1'b1)
start_addr <= 12'h000;
else if (eof_in_n_reg_reg == 1'b0 && eof_in_n_reg_reg_reg == 1'b1)
// end of last good frame
start_addr <= write_addr;
end
//---------------------------------------------------------------------------
// Now do the write_addr generation. We want to count up when valid data is
// being received and also one cycle at the end to delimit the frame. If the
// fifo overflows then the write address is set back to the start address.
// **If the FIFO is expanded to use more BRAM, increase write_addr_int size as
// required **
//---------------------------------------------------------------------------
always @(posedge write_clock_in)
begin
if (ll_reset == 1'b1)
write_addr_int <= 12'h0;
else if (overflow_int_held == 1'b1)
write_addr_int <= start_addr;
else if (write_addr_enable == 1'b1)
write_addr_int <= write_addr + 1;
end
assign write_addr = write_addr_int;
//--------------------------------------------------------------------
// The write address counter is enabled when write_data_valid is high or
// the end of frame is reached. This will enable the frame data
// and 1 extra empty byte to be stored.
//--------------------------------------------------------------------
assign write_addr_enable = write_data_valid | (!eof_in_n_reg & eof_in_n_reg_reg);
//---------------------------------------------------------------------------
// A signal that indicates that there has been a frame stored
//---------------------------------------------------------------------------
always @(posedge write_clock_in)
begin
if (ll_reset == 1'b1)
frame_received <= 1'b0;
else
frame_received <= !(eof_in_n_reg_reg) & eof_in_n_reg_reg_reg;
end
//---------------------------------------------------------------------------
// Now generate the read address on to the tx side.
// tx_addr will count up when there is a data to be transmitted
// **If the FIFO is expanded to use more BRAM, increase tx_addr_int and
// tx_addr_int_plus size as required **
//---------------------------------------------------------------------------
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
tx_addr_int <= 12'h001;
else if (tx_enable == 1'b1)
begin
if (tx_collision_reg == 1'b1 && tx_retransmit_reg == 1'b1)
tx_addr_int <= tx_start_addr ;
else if (tx_addr_enable == 1'b1)
tx_addr_int <= tx_addr + 1 ;
end
end
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
tx_addr_int_plus <= 12'h002;
else if (tx_enable == 1'b1)
begin
if (tx_addr_enable == 1'b1)
tx_addr_int_plus <= tx_addr + 2;
end
end
//--------------------------------------------------------------------
// When the acknowledge is received from the MAC the address is
// incremented. This ensures that the data is output correctly
//--------------------------------------------------------------------
assign tx_addr = (tx_ack == 1'b1) ? tx_addr_int_plus : tx_addr_int;
//--------------------------------------------------------------------
// The transmitter address counter is enabled when there is a frame
// in the FIFO, the data_valid output from the block memory is high,
// there is an acknowledge or an acknowledge has been received for the
// current frame 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, ready for an acknowledge signal from the MAC.
//--------------------------------------------------------------------
assign tx_addr_enable = (((tx_ack | frame_in_progress) &
((tx_data_valid_int & ((frame_in_fifo & !(queue_for_retransmit_held))
| tx_data_valid_pipe)) & frame_in_fifo_held)))
| queue | queue_for_retransmit;
//---------------------------------------------------------------------------
// Register the tx address enable for use on BRAM output data selection
//---------------------------------------------------------------------------
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
tx_addr_enable_reg <= 1'b0;
else if (tx_enable == 1'b1)
tx_addr_enable_reg <= tx_addr_enable;
end
//---------------------------------------------------------------------------
// A signal that indicates that there has been a frame transmitted
//---------------------------------------------------------------------------
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
frame_transmitted_toggle <= 1'b0;
else if (tx_enable == 1'b1)
begin
if (tx_ack == 1'b1)
frame_transmitted_toggle <= !frame_transmitted_toggle;
end
end
//---------------------------------------------------------------------------
// A signal that indicates that there has been a frame has been retransmitted
//---------------------------------------------------------------------------
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
frame_retransmit_toggle <= 1'b0;
else if (tx_enable == 1'b1)
begin
if (tx_retransmit_reg == 1'b1)
frame_retransmit_toggle <= !frame_retransmit_toggle;
end
end
//--------------------------------------------------------------------
// 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_transmitted_toggle
// signal is the frame_transmitted_toggle signal re-clocked onto
// write_clock, a faster clock. The ll_frame_transmitted signal is
// asserted for 1 cycle when an edge is detected on
// ll_frame_transmitted_toggle.
// This is repeated for the frame_retransmit_toggle
//--------------------------------------------------------------------
// Generate frame_transmitted pulse on write clock
always @(posedge write_clock_in)
begin
if (ll_reset == 1'b1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -