📄 eth_avalon_txdma.v
字号:
state[ST_STAT ]: begin // wait for status
if(stat_ready) begin
if(tx_retry) state[ST_IDLE ] <= 1'b1;
else state[ST_BD_WR] <= 1'b1;
end else state[ST_STAT ] <= 1'b1;
end
state[ST_BD_WR]: // write descriptor
if(~bd_wait) state[ST_IDLE ] <= 1'b1;
else state[ST_BD_WR] <= 1'b1;
endcase
end
assign next_tg_cnt = bd_len + ({1'b0,ptr[1:0]} + 3'd3);
assign next_rd_cnt = rd_cnt + 14'd1;
assign next_wr_cnt = wr_cnt + 14'd1;
assign last_read = (next_rd_cnt >= tg_cnt) | stat_ready;
assign first_write = !wr_cnt;
assign last_write = last_read_r & (next_wr_cnt >= rd_cnt);
assign valid_cnt = first_write ? first_valid_cnt:
last_write ? last_valid_cnt:
2'd3;
//Register last read signal
always @(posedge clk) begin
valid_rdata <= av_readdatavalid;
rdata <= av_readdata;
if(valid_rdata) wr_cnt <= next_wr_cnt;
//This really is a parallel case
case(1'b1) // synopsys parallel_case
state[ST_IDLE]: begin
last_read_r <= 1'b0; //clear last read flag
rd_cnt <= 14'd0; //clear read count
wr_cnt <= 14'd0; //clear write count
TxB_IRQ <= 1'b0; //clear irq
TxE_IRQ <= 1'b0; //clear error irq
if(~TxEn) bd_index <= 7'd0; //clear the BD indexer
end //state[ST_IDLE ]
state[ST_BD_RD]: begin
if(~bd_wait & bd_desc[BIT_READY]) begin
tg_cnt <= next_tg_cnt[15:2]; //load target count
{ptr,desc} <= {bd_ptr,bd_desc}; //load pointer and descriptor
end
end //state[ST_BD_RD]
state[ST_DMA1 ]: begin
first_valid_cnt <= (3'd3 - {1'b0,ptr[1:0]});
last_valid_cnt <= (bd_len[2:0] + {1'b0,ptr[1:0]}) - 3'd1;
if(valid_tx_rd) begin
ptr[31:2] <= ptr[31:2] + 30'd1; //increment read address
last_read_r <= last_read; //set last read flag
rd_cnt <= next_rd_cnt; //increment read count
end
end //state[ST_DMA1 ]
state[ST_BD_WR]:
if(~bd_wait) begin
TxB_IRQ <= desc[BIT_IRQ] & ~stat_error;
TxE_IRQ <= desc[BIT_IRQ] & stat_error;
if(desc[BIT_WRAP] | (bd_index == max_tx_bd))
bd_index <= 7'd0;
else bd_index <= bd_index + 7'd1;
end
endcase
end
//***************************************************************************
//*************************** Data FIFO *************************************
assign dff_clear = reset | state[ST_IDLE];
assign dff_write = valid_rdata & ~stat_ready;
assign dff_din[35] = first_write;
assign dff_din[34] = last_write;
assign dff_din[33:32] = valid_cnt;
assign dff_din[31:0] = first_write? (rdata >> {ptr[1:0],3'd0}): rdata;
assign dff_almost_full = dff_wrused >= FF_FULL_THRESHOLD;
//We'll read from the FIFO everytime there is a word ready or if something
//happened to put us into the WAIT state. We do this to flush the FIFO so
//any pending incoming reads from the avalon bus will make it into the FIFO
assign dff_read = tx_state[TX_WAIT] | (tx_state[TX_SEND] & last_byte & tx_ack);
eth_avalon_dma_fifo #( .DEPTH(RFD),
.WIDTH(36)) data_fifo(
.aclr (dff_clear ),
.wrclk (clk ),
.data (dff_din ),
.wrreq (dff_write ),
.wrfull (dff_full ),
.wrusedw (dff_wrused ),
.rdclk (txclk ),
.rdreq (dff_read&~dff_empty ),
.rdempty (dff_empty ),
.rdusedw ( ),
.q (dff_dout )
);
//Send stat_ready signal from TX to Avalon
eth_dc_reg stat_ready_dc_reg(
.d (tx_state[TX_WAIT] & tx_stat_valid_r),
.inclk (txclk ),
.outclk (clk ),
.reset (reset ),
.q (stat_ready )
);
//Send stat_ack signal from Avalon to TX
eth_dc_reg stat_ack_dc_reg(
.d (state[ST_IDLE] ),
.inclk (clk ),
.outclk (txclk ),
.reset (reset ),
.q (tx_stat_ack )
);
//Send tx_start signal from Avalon to TX
//We start sending the data when there is either
//words in the FIFO or when the DMA transfer
//has finished.
eth_dc_reg tx_start_dc_reg(
.d ((dff_wrused >= 8)/*dff_almost_full*/ | state[ST_DMA2] ),
.inclk (clk ),
.outclk (txclk ),
.reset (reset ),
.q (tx_start )
);
//************************* End Data FIFO ***********************************
//***************************************************************************
//***************************************************************************
//************************* Streaming Interface *****************************
assign stat_error = |{stat[BIT_UR],stat[BIT_RL:BIT_CS]};
assign tx_ff_data[0] = dff_dout[7:0];
assign tx_ff_data[1] = dff_dout[15:8];
assign tx_ff_data[2] = dff_dout[23:16];
assign tx_ff_data[3] = dff_dout[31:24];
assign byte_cnt = dff_dout[33:32];
assign last_byte = (byte_index == byte_cnt);
assign tx_data = tx_ff_data[byte_index];
assign tx_dv = tx_state[TX_SEND];
assign tx_sop = tx_state[TX_SEND] & !byte_index & dff_dout[35];
assign tx_eop = tx_state[TX_SEND] & last_byte & dff_dout[34];
assign PerPacketPad = desc[BIT_PAD];
assign PerPacketCrc = desc[BIT_CRC];
assign TxUnderRun = tx_state[TX_SEND] & tx_ack & dff_empty;
always @(posedge txclk or posedge reset)
if(reset) tx_state <= 3'd1;
else begin
/*default case-->*/ tx_state <= 3'd0;
case(1'b1) // synopsys parallel_case
tx_state[TX_IDLE]:// Wait for start
if(tx_start) tx_state[TX_SEND] <= 1'b1;
else tx_state[TX_IDLE] <= 1'b1;
tx_state[TX_SEND]:// Send all data
if((last_byte & dff_dout[34] & tx_ack) | tx_stat_valid)
tx_state[TX_WAIT] <= 1'b1;
else tx_state[TX_SEND] <= 1'b1;
tx_state[TX_WAIT]:// Wait for status
if(tx_stat_ack) tx_state[TX_IDLE] <= 1'b1;
else tx_state[TX_WAIT] <= 1'b1;
endcase
end
always @(posedge txclk)
if(tx_stat_valid) stat <= tx_stat;
always @(posedge txclk)
if(tx_state[TX_IDLE]) tx_stat_valid_r <= 1'b0;
else if(tx_stat_valid) tx_stat_valid_r <= 1'b1;
always @(posedge txclk)
case(1'b1)
tx_state[TX_IDLE]: begin
byte_index <= 2'd0;
end
tx_state[TX_SEND]: begin
if(tx_ack) begin
if(last_byte) byte_index <= 2'd0;
else byte_index <= byte_index + 2'd1;
end
end
endcase
//*********************** End Streaming Interface ***************************
//***************************************************************************
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -