📄 tx_client_fifo_8.v
字号:
rd_nxt_state <= QUEUE2_s;
end
QUEUE2_s : begin
rd_nxt_state <= QUEUE3_s;
end
QUEUE3_s : begin
rd_nxt_state <= QUEUE_ACK_s;
end
QUEUE_ACK_s : begin
rd_nxt_state <= WAIT_ACK_s;
end
WAIT_ACK_s : begin
// the output pipe line is fully loaded, so wait for ack from mac
// before moving on
if (tx_ack == 1'b1)
rd_nxt_state <= FRAME_s;
else
rd_nxt_state <= WAIT_ACK_s;
end
FRAME_s : begin
// when the end of frame has been reached wait another frame in
// the fifo
if (rd_eof == 1'b1)
rd_nxt_state <= IDLE_s;
else
rd_nxt_state <= FRAME_s;
end
default : begin
rd_nxt_state <= IDLE_s;
end
endcase
end
// full duplex state machine
end // gen_fd_sm
endgenerate
//---------------------------------------------------------------------------
// Full and Half Duplex State Machine
generate if (FULL_DUPLEX_ONLY != 1) begin : gen_hd_sm
// decode the next state
// should never receive a rd_drop_frame pulse outside of the Frame state
always @(rd_state or frame_in_fifo or rd_eof_reg or tx_ack or rd_drop_frame or rd_retransmit)
begin
case (rd_state)
IDLE_s : begin
// if a retransmit request is detected go to retransmit state
if (rd_retransmit == 1'b1)
rd_nxt_state <= RETRANSMIT_s;
// if there is a frame in the fifo then queue the new frame to
// the output
else if (frame_in_fifo == 1'b1)
rd_nxt_state <= QUEUE1_s;
else
rd_nxt_state <= IDLE_s;
end
QUEUE1_s : begin
if (rd_retransmit == 1'b1)
rd_nxt_state <= RETRANSMIT_s;
else
rd_nxt_state <= QUEUE2_s;
end
QUEUE2_s : begin
if (rd_retransmit == 1'b1)
rd_nxt_state <= RETRANSMIT_s;
else
rd_nxt_state <= QUEUE3_s;
end
QUEUE3_s : begin
if (rd_retransmit == 1'b1)
rd_nxt_state <= RETRANSMIT_s;
else
rd_nxt_state <= QUEUE_ACK_s;
end
QUEUE_ACK_s : begin
if (rd_retransmit == 1'b1)
rd_nxt_state <= RETRANSMIT_s;
else
rd_nxt_state <= WAIT_ACK_s;
end
WAIT_ACK_s : begin
// the output pipeline is now fully loaded so wait for ack from
// mac before moving on.
if (rd_retransmit == 1'b1)
rd_nxt_state <= RETRANSMIT_s;
else if (tx_ack == 1'b1)
rd_nxt_state <= FRAME_s;
else
rd_nxt_state <= WAIT_ACK_s;
end
FRAME_s : begin
// if a collision only request, then must drop the rest of the
// current frame, move to drop state
if (rd_drop_frame == 1'b1)
rd_nxt_state <= DROP_s;
else if (rd_retransmit == 1'b1)
rd_nxt_state <= RETRANSMIT_s;
// continue transmitting frame until the end of the frame is
// detected, then wait for a new frame to be sent.
else if (rd_eof_reg == 1'b1)
rd_nxt_state <= IDLE_s;
else
rd_nxt_state <= FRAME_s;
end
DROP_s : begin
// wait until rest of frame has been cleared.
if (rd_eof_reg == 1'b1)
rd_nxt_state <= IDLE_s;
else
rd_nxt_state <= DROP_s;
end
RETRANSMIT_s : begin
// reload the data pipe from the start of the frame
rd_nxt_state <= QUEUE1_s;
end
default : begin
rd_nxt_state <= IDLE_s;
end
endcase
end
end // gen_hd_sm // half duplex state machine
endgenerate
//---------------------------------------------------------------------------
// decode output signals
// decode output data
always @(posedge rd_clk)
begin
if (rd_enable == 1'b1)
begin
if (rd_nxt_state == FRAME_s)
tx_data <= rd_data_pipe;
else
begin
case (rd_state)
QUEUE_ACK_s :
tx_data <= rd_data_pipe;
WAIT_ACK_s :
tx_data <= tx_data;
FRAME_s :
tx_data <= rd_data_pipe;
default :
tx_data <= 8'b0;
endcase
end
end
end
// decode output data valid
always @(posedge rd_clk)
begin
if (rd_enable == 1'b1)
begin
if (rd_nxt_state == FRAME_s)
tx_data_valid <= ~(tx_collision && ~(tx_retransmit));
else
begin
case (rd_state)
QUEUE_ACK_s :
tx_data_valid <= 1'b1;
WAIT_ACK_s :
tx_data_valid <= 1'b1;
FRAME_s :
tx_data_valid <= ~(rd_nxt_state == DROP_s);
default :
tx_data_valid <= 1'b0;
endcase
end
end
end
//---------------------------------------------------------------------------
// decode full duplex only control signals
generate if (FULL_DUPLEX_ONLY == 1) begin : gen_fd_decode
assign rd_en = (rd_state == IDLE_s) ? 1'b0 :
(rd_nxt_state == FRAME_s) ? 1'b1 :
(rd_state == WAIT_ACK_s) ? 1'b0 : 1'b1;
assign rd_addr_inc = rd_en;
assign rd_addr_reload = (rd_state == FRAME_s && rd_nxt_state == IDLE_s) ? 1'b1 : 1'b0;
// Transmit frame pulse is only 1 clock enabled pulse long.
// Transmit frame pulse must never be more frequent than 64 clocks to allow toggle to cross clock domain
assign rd_transmit_frame = (rd_state == WAIT_ACK_s && rd_nxt_state == FRAME_s) ? 1'b1 : 1'b0;
// unused for full duplex only
assign rd_start_addr_reload = 1'b0;
assign rd_start_addr_load = 1'b0;
assign rd_retransmit_frame = 1'b0;
end // gen_fd_decode // full duplex control signals
endgenerate
//---------------------------------------------------------------------------
// decode half duplex control signals
generate if (FULL_DUPLEX_ONLY != 1) begin : gen_hd_decode
assign rd_en = (rd_state == IDLE_s) ? 1'b0 :
(rd_nxt_state == DROP_s && rd_eof == 1'b1) ? 1'b0 :
(rd_nxt_state == FRAME_s) ? 1'b1 :
(rd_state == RETRANSMIT_s) ? 1'b0 :
(rd_state == WAIT_ACK_s) ? 1'b0 : 1'b1;
assign rd_addr_inc = rd_en;
assign rd_addr_reload = (rd_state == FRAME_s && rd_nxt_state == IDLE_s) ? 1'b1 :
(rd_state == DROP_s && rd_nxt_state == IDLE_s) ? 1'b1 : 1'b0;
assign rd_start_addr_reload = (rd_state == RETRANSMIT_s) ? 1'b1 : 1'b0;
assign rd_start_addr_load = (rd_state == WAIT_ACK_s && rd_nxt_state == FRAME_s) ? 1'b1 :
(rd_col_window_expire == 1'b1) ? 1'b1 : 1'b0;
// Transmit frame pulse must never be more frequent than 64 clocks to allow toggle to cross clock domain
assign rd_transmit_frame = (rd_state == WAIT_ACK_s && rd_nxt_state == FRAME_s) ? 1'b1 : 1'b0;
// Retransmit frame pulse must never be more frequent than 16 clocks to allow toggle to cross clock domain
assign rd_retransmit_frame = (rd_state == RETRANSMIT_s) ? 1'b1 : 1'b0;
end // gen_hd_decode // half duplex control signals
endgenerate
//---------------------------------------------------------------------------
// Frame Count
// We need to maintain a count of frames in the fifo, so that we know when a
// frame is available for transmission. The counter must be held on the
// write clock domain as this is the faster clock.
//---------------------------------------------------------------------------
// A frame has been written to the fifo
assign wr_store_frame = (wr_state == EOF_s && wr_nxt_state != EOF_s) ? 1'b1 : 1'b0;
// generate a toggle to indicate when a frame has been transmitted from the fifo
always @(posedge rd_clk)
begin // process
if (rd_sreset == 1'b1)
rd_tran_frame_tog <= 1'b0;
else if (rd_enable == 1'b1)
if (rd_transmit_frame == 1'b1) // assumes EOF_s is valid for one clock
// cycle only ever! check
rd_tran_frame_tog <= !rd_tran_frame_tog;
end
// move the read transmit frame signal onto the write clock domain
always @(posedge wr_clk)
begin
if (wr_sreset == 1'b1)
begin
wr_tran_frame_tog <= 1'b0;
wr_tran_frame_sync <= 1'b0;
wr_tran_frame_delay <= 1'b0;
wr_transmit_frame <= 1'b0;
end
else
begin
wr_tran_frame_tog <= rd_tran_frame_tog;
wr_tran_frame_sync <= wr_tran_frame_tog;
wr_tran_frame_delay <= wr_tran_frame_sync;
// edge detector
if ((wr_tran_frame_delay ^ wr_tran_frame_sync) == 1'b1)
wr_transmit_frame <= 1'b1;
else
wr_transmit_frame <= 1'b0;
end
end
//---------------------------------------------------------------------------
generate if (FULL_DUPLEX_ONLY == 1) begin : gen_fd_count
// count the number of frames in the fifo. the counter is incremented when a
// frame is stored and decremented when a frame is transmitted. Need to keep
// the counter on the write clock as this is the fastest clock.
always @(posedge wr_clk)
begin
if (wr_sreset == 1'b1)
wr_frames <= 9'b0;
else
if ((wr_store_frame & !wr_transmit_frame) == 1'b1)
wr_frames <= wr_frames + 1;
else if ((!wr_store_frame & wr_transmit_frame) == 1'b1)
wr_frames <= wr_frames - 1;
end
end // gen_fd_count
endgenerate
//---------------------------------------------------------------------------
generate if (FULL_DUPLEX_ONLY != 1) begin : gen_hd_count
// generate a toggle to indicate when a frame has been transmitted from the fifo
always @(posedge rd_clk)
begin // process
if (rd_sreset == 1'b1)
rd_retran_frame_tog <= 1'b0;
else if (rd_enable == 1'b1)
if (rd_retransmit_frame == 1'b1) // assumes EOF_s is valid for one clock
// cycle only ever! check
rd_retran_frame_tog <= !rd_retran_frame_tog;
end
// move the read transmit frame signal onto the write clock domain
always @(posedge wr_clk)
begin
if (wr_sreset == 1'b1)
begin
wr_retran_frame_tog <= 1'b0;
wr_retran_frame_sync <= 1'b0;
wr_retran_frame_delay <= 1'b0;
wr_retransmit_frame <= 1'b0;
end
else
begin
wr_retran_frame_tog <= rd_retran_frame_tog;
wr_retran_frame_sync <= wr_retran_frame_tog;
wr_retran_frame_delay <= wr_retran_frame_sync;
// edge detector
if ((wr_retran_frame_delay ^ wr_retran_frame_sync) == 1'b1)
wr_retransmit_frame <= 1'b1;
else
wr_retransmit_frame <= 1'b0;
end
end
// count the number of frames in the fifo. the counter is incremented when a
// frame is stored or retransmitted and decremented when a frame is transmitted. Need to keep
// the counter on the write clock as this is the fastest clock.
// Assumes transmit and retransmit cannot happen at same time
always @(posedge wr_clk)
begin
if (wr_sreset == 1'b1)
wr_frames <= 9'b0;
else
if ((wr_store_frame & wr_retransmit_frame) == 1'b1)
wr_frames <= wr_frames + 2;
else if (((wr_store_frame | wr_retransmit_frame) & !wr_transmit_frame) == 1'b1)
wr_frames <= wr_frames + 1;
else if (wr_transmit_frame == 1'b1 & !wr_store_frame)
wr_frames <= wr_frames - 1;
end
end // gen_hd_count
endgenerate
//---------------------------------------------------------------------------
// generate a frame in fifo signal for use in control logic
always @(posedge wr_clk)
begin
if (wr_sreset == 1'b1)
wr_frame_in_fifo <= 1'b0;
else
if (wr_frames != 9'b0)
wr_frame_in_fifo <= 1'b1;
else
wr_frame_in_fifo <= 1'b0;
end
// register back onto read domain for use in the read logic
always @(posedge rd_clk)
begin
if (rd_sreset == 1'b1)
begin
frame_in_fifo_sync <= 1'b0;
frame_in_fifo <= 1'b0;
end
else if (rd_enable == 1'b1)
begin
frame_in_fifo_sync <= wr_frame_in_fifo;
frame_in_fifo <= frame_in_fifo_sync;
end
end
//---------------------------------------------------------------------------
// Address counters
//---------------------------------------------------------------------------
// Address counters
// write address is incremented when write enable signal has been asserted
always @(posedge wr_clk)
begin
if (wr_sreset == 1'b1)
wr_addr <= 12'b0;
else if (wr_addr_reload == 1'b1)
wr_addr <= wr_start_addr;
else if (wr_addr_inc == 1'b1)
wr_addr <= wr_addr + 1;
end
// store the start address incase the address must be reset
always @(posedge wr_clk)
begin
if (wr_sreset == 1'b1)
wr_start_addr <= 12'b0;
else if (wr_start_addr_load == 1'b1)
wr_start_addr <= wr_addr + 1;
end
//---------------------------------------------------------------------------
generate if (FULL_DUPLEX_ONLY == 1) begin : gen_fd_addr
// read address is incremented when read enable signal has been asserted
always @(posedge rd_clk)
begin
if (rd_sreset == 1'b1)
rd_addr <= 12'b0;
else if (rd_enable == 1'b1)
if (rd_addr_reload == 1'b1)
rd_addr <= rd_dec_addr;
else if (rd_addr_inc == 1'b1)
rd_addr <= rd_addr + 1;
end
// do not need to keep a start address, but the address is needed to
// calculate fifo occupancy.
always @(posedge rd_clk)
begin
if (rd_sreset == 1'b1)
rd_start_addr <= 12'b0;
else if (rd_enable == 1'b1)
rd_start_addr <= rd_addr;
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -