📄 tx_client_fifo.v
字号:
begin
ll_frame_transmitted_toggle <= 3'b000;
ll_frame_transmitted <= 1'b0;
end
else
begin
ll_frame_transmitted_toggle[0] <= frame_transmitted_toggle;
ll_frame_transmitted_toggle[1] <= ll_frame_transmitted_toggle[0];
ll_frame_transmitted_toggle[2] <= ll_frame_transmitted_toggle[1];
ll_frame_transmitted <= ll_frame_transmitted_toggle[2] ^ ll_frame_transmitted_toggle[1];
end
end
// Repeat for frame_retransmit pulse
always @(posedge write_clock_in)
begin
if (ll_reset == 1'b1)
begin
ll_frame_retransmit_toggle <= 3'b000;
ll_frame_retransmit <= 1'b0;
end
else
begin
ll_frame_retransmit_toggle[0] <= frame_retransmit_toggle;
ll_frame_retransmit_toggle[1] <= ll_frame_retransmit_toggle[0];
ll_frame_retransmit_toggle[2] <= ll_frame_retransmit_toggle[1];
ll_frame_retransmit <= ll_frame_retransmit_toggle[2] ^ ll_frame_retransmit_toggle[1];
end
end
// Generate frame count on write clock
// **If the FIFO is expanded to use more BRAM, ensure frame count signals are
// wide enough to count the maximum number of frames that can be stored in FIFO**
always @(posedge write_clock_in)
begin
if (ll_reset == 1'b1)
ll_frame_count <= 9'd0;
else
begin
if (ll_frame_transmitted == 1'b1 && frame_received == 1'b0)
ll_frame_count <= ll_frame_count - 1;
else if ((ll_frame_transmitted == 1'b0 && frame_received == 1'b1 && ll_frame_retransmit == 1'b0) ||
(ll_frame_retransmit == 1'b1 && frame_received == 1'b0))
ll_frame_count <= ll_frame_count + 1;
else if (ll_frame_retransmit == 1'b1 && frame_received == 1'b1)
ll_frame_count <= ll_frame_count + 2;
end
end
//---------------------------------------------------------------------------
// As the frame_count information will be used by the transmitter logic, we
// need to convert the frame count( signal back to the transmit clock domain.
// This is done using gray code.
//---------------------------------------------------------------------------
// Convert the ll_frame_count signal to gray code
always @(posedge write_clock_in)
begin
if (ll_reset == 1'b1)
ll_frame_count_gray <= 9'd0;
else
begin
ll_frame_count_gray[8] <= ll_frame_count[8];
ll_frame_count_gray[7] <= ll_frame_count[8] ^ ll_frame_count[7];
ll_frame_count_gray[6] <= ll_frame_count[7] ^ ll_frame_count[6];
ll_frame_count_gray[5] <= ll_frame_count[6] ^ ll_frame_count[5];
ll_frame_count_gray[4] <= ll_frame_count[5] ^ ll_frame_count[4];
ll_frame_count_gray[3] <= ll_frame_count[4] ^ ll_frame_count[3];
ll_frame_count_gray[2] <= ll_frame_count[3] ^ ll_frame_count[2];
ll_frame_count_gray[1] <= ll_frame_count[2] ^ ll_frame_count[1];
ll_frame_count_gray[0] <= ll_frame_count[1] ^ ll_frame_count[0];
end
end
// Clock this onto the tx_clk.
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
frame_count_gray <= 9'd0;
else if (tx_enable == 1'b1)
frame_count_gray <= ll_frame_count_gray;
end
// Convert this back to binary.
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
frame_count <= 9'd0;
else if (tx_enable == 1'b1)
begin
frame_count[8] <= frame_count_gray[8];
frame_count[7] <= frame_count_gray[8] ^ frame_count_gray[7];
frame_count[6] <= frame_count_gray[8] ^ frame_count_gray[7]
^ frame_count_gray[6];
frame_count[5] <= frame_count_gray[8] ^ frame_count_gray[7]
^ frame_count_gray[6] ^ frame_count_gray[5];
frame_count[4] <= frame_count_gray[8] ^ frame_count_gray[7]
^ frame_count_gray[6] ^ frame_count_gray[5]
^ frame_count_gray[4];
frame_count[3] <= frame_count_gray[8] ^ frame_count_gray[7]
^ frame_count_gray[6] ^ frame_count_gray[5]
^ frame_count_gray[4] ^ frame_count_gray[3];
frame_count[2] <= frame_count_gray[8] ^ frame_count_gray[7]
^ frame_count_gray[6] ^ frame_count_gray[5]
^ frame_count_gray[4] ^ frame_count_gray[3]
^ frame_count_gray[2];
frame_count[1] <= frame_count_gray[8] ^ frame_count_gray[7]
^ frame_count_gray[6] ^ frame_count_gray[5]
^ frame_count_gray[4] ^ frame_count_gray[3]
^ frame_count_gray[2] ^ frame_count_gray[1];
frame_count[0] <= frame_count_gray[8] ^ frame_count_gray[7]
^ frame_count_gray[6] ^ frame_count_gray[5]
^ frame_count_gray[4] ^ frame_count_gray[3]
^ frame_count_gray[2] ^ frame_count_gray[1]
^ frame_count_gray[0];
end
end
// Indicator signal for one or more frames in the fifo
assign frame_in_fifo = (frame_count == 9'd0) ? 1'b0 : 1'b1;
//--------------------------------------------------------------------
// We want to count up through the frame data after we have received
// an ack back from the MAC. When data_valid goes low then we stop.
// If frame_in_fifo_held is low then the signal is de-asserted to
// prevent an underrun.
//--------------------------------------------------------------------
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
frame_in_progress <= 1'b0;
else if (tx_enable == 1'b1)
begin
if (tx_data_valid_pipe == 1'b0 || frame_in_fifo_held == 1'b0)
frame_in_progress <= 1'b0;
else if (tx_ack == 1'b1)
frame_in_progress <= 1'b1;
end
end
assign not_frame_in_progress = !(frame_in_progress);
//---------------------------------------------------------------------------
// Hold the frame_in_fifo signal until the frame has been completely
// transmitted. This will be used to gate the data_valid output.
//---------------------------------------------------------------------------
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
frame_in_fifo_held <= 1'b0;
else if (tx_enable == 1'b1)
begin
if ((frame_in_progress == 1'b1 && tx_data_valid_pipe == 1'b0) || frame_in_fifo == 1'b1)
frame_in_fifo_held <= frame_in_fifo;
end
end
//--------------------------------------------------------------------
// At the start of each frame we need to clock the first byte of
// data from the memory as we have to change this as soon as ack is
// received.
//--------------------------------------------------------------------
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
queue <= 1'b0;
else if (tx_enable == 1'b1)
queue <= (frame_in_fifo & !(frame_in_fifo_held) & !(queue_for_retransmit_held));
end
//--------------------------------------------------------------------
// We have to calculate the occupancy of the fifo as we need to drop
// frames when it is about to overflow. This will be calculated on
// the write clock and so we need to get the tx_addr into the write clock
// domain. To do this we first convert the tx_addr to gray codes as
// this helps to counter problems with the 2 addresses being on
// different clock domains. This gray code representation of the
// tx_addr is then clocked onto the write clock and converted back to
// binary. The binary version can then be compared to to the
// write_addr on the write clock.
// **If the FIFO is expanded to use more BRAM, increase tx_addr_gray,
// ll_tx_addr_gray and ll_tx_addr_bin size as required **
//--------------------------------------------------------------------
// Convert tx address to gray codes.
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
tx_addr_gray <= 12'h001;
else if (tx_enable == 1'b1)
begin
tx_addr_gray[11] <= tx_addr_reg[11] ;
tx_addr_gray[10] <= tx_addr_reg[11] ^ tx_addr_reg[10];
tx_addr_gray[9] <= tx_addr_reg[10] ^ tx_addr_reg[9];
tx_addr_gray[8] <= tx_addr_reg[9] ^ tx_addr_reg[8];
tx_addr_gray[7] <= tx_addr_reg[8] ^ tx_addr_reg[7];
tx_addr_gray[6] <= tx_addr_reg[7] ^ tx_addr_reg[6];
tx_addr_gray[5] <= tx_addr_reg[6] ^ tx_addr_reg[5];
tx_addr_gray[4] <= tx_addr_reg[5] ^ tx_addr_reg[4];
tx_addr_gray[3] <= tx_addr_reg[4] ^ tx_addr_reg[3];
tx_addr_gray[2] <= tx_addr_reg[3] ^ tx_addr_reg[2];
tx_addr_gray[1] <= tx_addr_reg[2] ^ tx_addr_reg[1];
tx_addr_gray[0] <= tx_addr_reg[1] ^ tx_addr_reg[0];
end
end
// Clock this onto the write clock.
always @(posedge write_clock_in)
begin
if (ll_reset == 1'b1)
ll_tx_addr_gray <= 12'h001;
else
ll_tx_addr_gray <= tx_addr_gray;
end
// Convert this back to binary.
always @(posedge write_clock_in)
begin
if (ll_reset == 1'b1)
ll_tx_addr_bin <= 12'h001;
else
begin
ll_tx_addr_bin[11] <= ll_tx_addr_gray[11];
ll_tx_addr_bin[10] <= ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10];
ll_tx_addr_bin[9] <= ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
^ ll_tx_addr_gray[9];
ll_tx_addr_bin[8] <= ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
^ ll_tx_addr_gray[9] ^ ll_tx_addr_gray[8];
ll_tx_addr_bin[7] <= ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
^ ll_tx_addr_gray[9] ^ ll_tx_addr_gray[8]
^ ll_tx_addr_gray[7];
ll_tx_addr_bin[6] <= ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
^ ll_tx_addr_gray[9] ^ ll_tx_addr_gray[8]
^ ll_tx_addr_gray[7] ^ ll_tx_addr_gray[6];
ll_tx_addr_bin[5] <= ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
^ ll_tx_addr_gray[9] ^ ll_tx_addr_gray[8]
^ ll_tx_addr_gray[7] ^ ll_tx_addr_gray[6]
^ ll_tx_addr_gray[5];
ll_tx_addr_bin[4] <= ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
^ ll_tx_addr_gray[9] ^ ll_tx_addr_gray[8]
^ ll_tx_addr_gray[7] ^ ll_tx_addr_gray[6]
^ ll_tx_addr_gray[5] ^ ll_tx_addr_gray[4];
ll_tx_addr_bin[3] <= ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
^ ll_tx_addr_gray[9] ^ ll_tx_addr_gray[8]
^ ll_tx_addr_gray[7] ^ ll_tx_addr_gray[6]
^ ll_tx_addr_gray[5] ^ ll_tx_addr_gray[4]
^ ll_tx_addr_gray[3];
ll_tx_addr_bin[2] <= ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
^ ll_tx_addr_gray[9] ^ ll_tx_addr_gray[8]
^ ll_tx_addr_gray[7] ^ ll_tx_addr_gray[6]
^ ll_tx_addr_gray[5] ^ ll_tx_addr_gray[4]
^ ll_tx_addr_gray[3] ^ ll_tx_addr_gray[2];
ll_tx_addr_bin[1] <= ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
^ ll_tx_addr_gray[9] ^ ll_tx_addr_gray[8]
^ ll_tx_addr_gray[7] ^ ll_tx_addr_gray[6]
^ ll_tx_addr_gray[5] ^ ll_tx_addr_gray[4]
^ ll_tx_addr_gray[3] ^ ll_tx_addr_gray[2]
^ ll_tx_addr_gray[1];
ll_tx_addr_bin[0] <= ll_tx_addr_gray[11] ^ ll_tx_addr_gray[10]
^ ll_tx_addr_gray[9] ^ ll_tx_addr_gray[8]
^ ll_tx_addr_gray[7] ^ ll_tx_addr_gray[6]
^ ll_tx_addr_gray[5] ^ ll_tx_addr_gray[4]
^ ll_tx_addr_gray[3] ^ ll_tx_addr_gray[2]
^ ll_tx_addr_gray[1] ^ ll_tx_addr_gray[0];
end
end
// Subtract the tx address from the write address
always @(posedge write_clock_in)
begin
if (ll_reset == 1'b1)
ll_add_sub <= 12'h001;
else
ll_add_sub <= ll_tx_addr_bin - write_addr_reg;
end
// Set the full flag to go up when the rx address is 16 bytes
// away from the tx address.
assign full_pulse = ((ll_add_sub < 12'd22)
&& (ll_add_sub > 12'd1)) ? 1'b1 : 1'b0;
// Calculate the fifo status from the difference in addresses
assign fifo_status_full = write_addr_reg - ll_tx_addr_bin + 1;
// Truncate to give the 4 bit output signal
assign fifo_status_out = fifo_status_full[11:8];
//---------------------------------------------------------------------------
// Set overflow to 1 when the full pulse goes high and there are no frames
// in fifo to be transmitted. For this to happen an oversize frame must have
// been written into the fifo.
//---------------------------------------------------------------------------
always @(posedge write_clock_in)
begin
if (ll_reset == 1'b1)
overflow_int <= 1'b0;
else if (frame_in_fifo_held == 1'b0)
overflow_int <= full_pulse;
end
////-------------------------------------------------------------------------
// Hold this signal until the eof signals the
// end of the overflow frame has arrived.
//---------------------------------------------------------------------------
always @(posedge write_clock_in)
begin
if (ll_reset == 1'b1)
overflow_int_held <= 1'b0;
else if (overflow_int == 1'b1)
overflow_int_held <= 1'b1;
else if (overflow_eof_in_n_reg_reg == 1'b0 && overflow_eof_in_n_reg_reg_reg == 1'b1)
overflow_int_held <= 1'b0;
end
// Assign overflow output indicator to signal that current frame is being dropped
assign overflow = overflow_int_held;
//---------------------------------------------------------------------------
// Set the memory full pulse to go high when the write address is 16 bytes
// away from the tx start address. This protects a frame from being overwritten
// until there is no possibility of a further request for retransmission.
// Convert tx_start_address onto local link clock via gray code
// **If the FIFO is expanded to use more BRAM, increase tx_start_addr_gray
// ll_tx_start_addr_gray and ll_tx_start_addr size as required **
//---------------------------------------------------------------------------
// Convert tx address to gray codes.
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
tx_start_addr_gray <= 12'h001;
else if (tx_enable == 1'b1)
begin
tx_start_addr_gray[11] <= tx_start_addr[11];
tx_start_addr_gray[10] <= tx_start_addr[11] ^ tx_start_addr[10];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -