📄 tx_client_fifo.v
字号:
tx_start_addr_gray[9] <= tx_start_addr[10] ^ tx_start_addr[9];
tx_start_addr_gray[8] <= tx_start_addr[9] ^ tx_start_addr[8];
tx_start_addr_gray[7] <= tx_start_addr[8] ^ tx_start_addr[7];
tx_start_addr_gray[6] <= tx_start_addr[7] ^ tx_start_addr[6];
tx_start_addr_gray[5] <= tx_start_addr[6] ^ tx_start_addr[5];
tx_start_addr_gray[4] <= tx_start_addr[5] ^ tx_start_addr[4];
tx_start_addr_gray[3] <= tx_start_addr[4] ^ tx_start_addr[3];
tx_start_addr_gray[2] <= tx_start_addr[3] ^ tx_start_addr[2];
tx_start_addr_gray[1] <= tx_start_addr[2] ^ tx_start_addr[1];
tx_start_addr_gray[0] <= tx_start_addr[1] ^ tx_start_addr[0];
end
end
// Clock this onto the write clock.
always @(posedge write_clock_in)
begin
if (ll_reset == 1'b1)
ll_tx_start_addr_gray <= 12'h001;
else
ll_tx_start_addr_gray <= tx_start_addr_gray;
end
// Convert this back to binary.
always @(posedge write_clock_in)
begin
if (ll_reset == 1'b1)
ll_tx_start_addr <= 12'h001;
else
begin
ll_tx_start_addr[11] <= ll_tx_start_addr_gray[11];
ll_tx_start_addr[10] <= ll_tx_start_addr_gray[11] ^ ll_tx_start_addr_gray[10];
ll_tx_start_addr[9] <= ll_tx_start_addr_gray[11] ^ ll_tx_start_addr_gray[10]
^ ll_tx_start_addr_gray[9];
ll_tx_start_addr[8] <= ll_tx_start_addr_gray[11] ^ ll_tx_start_addr_gray[10]
^ ll_tx_start_addr_gray[9] ^ ll_tx_start_addr_gray[8];
ll_tx_start_addr[7] <= ll_tx_start_addr_gray[11] ^ ll_tx_start_addr_gray[10]
^ ll_tx_start_addr_gray[9] ^ ll_tx_start_addr_gray[8]
^ ll_tx_start_addr_gray[7];
ll_tx_start_addr[6] <= ll_tx_start_addr_gray[11] ^ ll_tx_start_addr_gray[10]
^ ll_tx_start_addr_gray[9] ^ ll_tx_start_addr_gray[8]
^ ll_tx_start_addr_gray[7] ^ ll_tx_start_addr_gray[6];
ll_tx_start_addr[5] <= ll_tx_start_addr_gray[11] ^ ll_tx_start_addr_gray[10]
^ ll_tx_start_addr_gray[9] ^ ll_tx_start_addr_gray[8]
^ ll_tx_start_addr_gray[7] ^ ll_tx_start_addr_gray[6]
^ ll_tx_start_addr_gray[5];
ll_tx_start_addr[4] <= ll_tx_start_addr_gray[11] ^ ll_tx_start_addr_gray[10]
^ ll_tx_start_addr_gray[9] ^ ll_tx_start_addr_gray[8]
^ ll_tx_start_addr_gray[7] ^ ll_tx_start_addr_gray[6]
^ ll_tx_start_addr_gray[5] ^ ll_tx_start_addr_gray[4];
ll_tx_start_addr[3] <= ll_tx_start_addr_gray[11] ^ ll_tx_start_addr_gray[10]
^ ll_tx_start_addr_gray[9] ^ ll_tx_start_addr_gray[8]
^ ll_tx_start_addr_gray[7] ^ ll_tx_start_addr_gray[6]
^ ll_tx_start_addr_gray[5] ^ ll_tx_start_addr_gray[4]
^ ll_tx_start_addr_gray[3];
ll_tx_start_addr[2] <= ll_tx_start_addr_gray[11] ^ ll_tx_start_addr_gray[10]
^ ll_tx_start_addr_gray[9] ^ ll_tx_start_addr_gray[8]
^ ll_tx_start_addr_gray[7] ^ ll_tx_start_addr_gray[6]
^ ll_tx_start_addr_gray[5] ^ ll_tx_start_addr_gray[4]
^ ll_tx_start_addr_gray[3] ^ ll_tx_start_addr_gray[2];
ll_tx_start_addr[1] <= ll_tx_start_addr_gray[11] ^ ll_tx_start_addr_gray[10]
^ ll_tx_start_addr_gray[9] ^ ll_tx_start_addr_gray[8]
^ ll_tx_start_addr_gray[7] ^ ll_tx_start_addr_gray[6]
^ ll_tx_start_addr_gray[5] ^ ll_tx_start_addr_gray[4]
^ ll_tx_start_addr_gray[3] ^ ll_tx_start_addr_gray[2]
^ ll_tx_start_addr_gray[1];
ll_tx_start_addr[0] <= ll_tx_start_addr_gray[11] ^ ll_tx_start_addr_gray[10]
^ ll_tx_start_addr_gray[9] ^ ll_tx_start_addr_gray[8]
^ ll_tx_start_addr_gray[7] ^ ll_tx_start_addr_gray[6]
^ ll_tx_start_addr_gray[5] ^ ll_tx_start_addr_gray[4]
^ ll_tx_start_addr_gray[3] ^ ll_tx_start_addr_gray[2]
^ ll_tx_start_addr_gray[1] ^ ll_tx_start_addr_gray[0];
end
end
// Subtract write address from tx start address
always @(posedge write_clock_in)
begin
if (ll_reset == 1'b1)
ll_start_add_sub <= 12'h001;
else
ll_start_add_sub <= ll_tx_start_addr - write_addr_reg;
end
assign memory_full_pulse = ((ll_start_add_sub < 12'd16) &&
(ll_start_add_sub > 12'd1)) ? 1'b1 : 1'b0;
always @(posedge write_clock_in)
begin
if (ll_reset == 1'b1)
memory_full <= 1'b0;
else
memory_full <= memory_full_pulse;
end
//---------------------------------------------------------------------------
// Register the write and tx addresses on their respective clocks.
// **If the FIFO is expanded to use more BRAM, increase write_addr_reg and
// tx_addr_reg size as required **
//---------------------------------------------------------------------------
always @(posedge write_clock_in)
begin
if (ll_reset == 1'b1)
write_addr_reg <= 12'h000;
else
write_addr_reg <= write_addr;
end
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
tx_addr_reg <= 12'h001;
else if (tx_enable == 1'b1)
tx_addr_reg <= tx_addr;
end
//---------------------------------------------------------------------------
// Half Duplex Operation
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// If the FIFO is to be used only in Full duplex operation, the current frame
// will never need to be retransmitted. This allows data to be written over
// any data that has been transmitted. This allows memory space to be freed
// up as quickly as possible.
//---------------------------------------------------------------------------
`ifdef FULL_DUPLEX_ONLY
// Start address is used to generate memory full signal. As frame can
// never be retransmitted, do not need to protect transmitted data.
// **If the FIFO is expanded to use more BRAM, increase tx_start_addr size as
// required **
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
tx_start_addr <= 12'h001;
else if (tx_enable == 1'b1)
tx_start_addr <= tx_addr - 3;
end
// Tie collision signals to ground
assign tx_idle_count = 10'b0000000000;
assign tx_length_count = 10'b0000000000;
assign col_no_retransmit = 1'b0;
assign tx_retransmit_reg = 1'b0;
assign tx_retransmit_reg_reg = 1'b0;
assign tx_retransmit_reg_reg_reg = 1'b0;
assign retransmit_fip = 1'b0;
assign tx_collision_reg = 1'b0;
assign queue_for_retransmit = 1'b0;
assign queue_for_retransmit_held = 1'b0;
`else
//---------------------------------------------------------------------------
// If the FIFO is to be used in half duplex operation then the current frame
// must be stored until it can no longer be retransmitted.
//---------------------------------------------------------------------------
//------------------------------------------------------------------------
// Store the tx_address at the start of a frame transmission or when the
// window for possible retransmission has expired.
// The window for retransmission expires when the frame has completely
// been transmitted by the MAC onto the network or the next frame is
// accepted by the MAC.
// The window for retranmission is calculated to expire after sufficient
// delay from the end of the frame being written from the FIFO has ensured
// that the frame will have been completely transmitted by the MAC.
// If a minimum length frame is passed to the MAC, then it will be padded
// in the MAC so the delay time is extended for a short frame to allow
// for any padding of the frame.
// **If the FIFO is expanded to use more BRAM, increase tx_start_addr size as
// required **
//------------------------------------------------------------------------
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
tx_start_addr <= 12'h001;
else if (tx_enable == 1'b1)
begin
if (tx_ack == 1'b1)
tx_start_addr <= tx_addr - 3;
else if ((tx_idle_count > 10'd20) && (tx_length_count_plus_tx_idle_count > 10'd528))
tx_start_addr <= tx_addr - 3;
end
end
// An adder to count tx_length_count plus tx_idle_count
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
tx_length_count_plus_tx_idle_count <= 11'd0;
else if (tx_enable == 1'b1)
tx_length_count_plus_tx_idle_count <= tx_length_count + tx_idle_count;
end
// A counter that records the length of the last frame sent, upto a length
// of 528 decimal. This is the minimum length frame allowed at 1Gig Half
// Duplex of 512 plus 8 bytes of preamble added by the MAC and a small margin
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
tx_length_count <= 10'd0;
else if (tx_enable == 1'b1)
begin
if (tx_ack == 1'b1)
tx_length_count <= 10'd0;
else if (frame_in_progress == 1'b1 && (tx_length_count < 10'd528))
tx_length_count <= tx_length_count + 1;
end
end
// A counter that records the no of clock cycles from the last byte of the
// last frame sent upto a value of 528 decimal.
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
tx_idle_count <= 10'd0;
else if (tx_enable == 1'b1)
begin
if (tx_ack == 1'b1)
tx_idle_count <= 10'd0;
else if (frame_in_progress == 1'b0 && (tx_idle_count < 10'd528))
tx_idle_count <= tx_idle_count + 1;
end
end
//---------------------------------------------------------------------------
// TX Half Duplex Collision handling circuit. On retransmit the circuit
// should go back to the start of the current frame and count up the
// frame counter. If a collision signal is seen without a retransmit
// then the circuit should drop the current frame.
//---------------------------------------------------------------------------
// If the collision is asserted without retransmit then we kill the rest
// of the frame
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
col_no_retransmit <= 1'b0;
else if (tx_enable == 1'b1)
begin
if (tx_collision_reg == 1'b1 && tx_retransmit_reg == 1'b0 &&
frame_in_progress == 1'b1 && tx_data_valid_pipe == 1'b1)
col_no_retransmit <= 1'b1;
else if (tx_data_valid_pipe == 1'b0 || frame_in_fifo_held == 1'b0)
col_no_retransmit <= 1'b0;
end
end
// If a retransmit comes in we have to queue up the data for retransmission.
// The queue for retransmit signal is asserted for one clock cycle after
// receiving tx_retransmit, to load data into the data pipe. The signal is
// held for two clock cycles if the fifo is not currently transmitting a frame
// or if the data pipe is empty.
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
queue_for_retransmit <= 1'b0;
else if (tx_enable == 1'b1)
begin
if (tx_retransmit_reg_reg == 1'b1)
queue_for_retransmit <= 1'b1;
else if (tx_retransmit_reg_reg_reg == 1'b1 &&
((frame_in_progress == 1'b0 && retransmit_fip == 1'b0) || tx_data_valid_pipe == 1'b0))
queue_for_retransmit <= 1'b1;
else
queue_for_retransmit <= 1'b0;
end
end
// queue_for_retransmit_held is used to turn off the signal queue from
// assersion of queue_for_retransmit until next tx_ack is recieved.
// It is also used to force the tx_mem_enable signal high until the
// frame is requeued
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
queue_for_retransmit_held <= 1'b0;
else if (tx_enable == 1'b1)
begin
if (queue_for_retransmit == 1'b1)
queue_for_retransmit_held <= 1'b1;
else if (tx_ack == 1'b1)
queue_for_retransmit_held <= 1'b0;
end
end
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
retransmit_fip <= 1'b0;
else if (tx_enable == 1'b1)
retransmit_fip <= frame_in_progress;
end
//---------------------------------------------------------------------------
// Generate the tx_retransmit_reg signal that is used to count back to
// the start of the frame.
//---------------------------------------------------------------------------
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
begin
tx_retransmit_reg <= 1'b0;
tx_retransmit_reg_reg <= 1'b0;
tx_retransmit_reg_reg_reg <= 1'b0;
end
else if (tx_enable == 1'b1)
begin
tx_retransmit_reg <= tx_retransmit;
tx_retransmit_reg_reg <= tx_retransmit_reg;
tx_retransmit_reg_reg_reg <= tx_retransmit_reg_reg;
end
end
always @(posedge tx_clk)
begin
if (tx_reset == 1'b1)
tx_collision_reg <= 1'b0;
else if (tx_enable == 1'b1)
tx_collision_reg <= tx_collision;
end
`endif
`ifdef FULL_DUPLEX_ONLY
`undef FULL_DUPLEX_ONLY
`endif
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -