📄 eth_avalon_txdma.v
字号:
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_avalon_txdma.v ////
//// ////
//// This file is a patch used in conjunction with the ////
//// Ethernet IP core project. ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Jakob Jones (jrjonsie@gmail.com) ////
//// ////
//// All additional information is available in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
module eth_avalon_txdma #(parameter FIFO_DEPTH=128) (
//Commaon signals
input clk,
input reset,
//Descriptor ram interface
input [6:0] max_tx_bd, //Highest index RX Descriptor
input [31:0] bd_desc, //Descriptor Control data input
input [31:0] bd_ptr, //Descriptor pointer input
input bd_wait, //Descriptor RAM is busy
output bd_write, //write control data to BD RAM
output bd_read, //read control and pointer data from BD RAM
output reg [6:0] bd_index, //Which descriptor to read
output [31:0] bd_writedata, //Control data to be written to descriptor
//Memory port interface
input av_waitrequest, //Memory port is busy
input [31:0] av_readdata, //Memory port readdata
input av_readdatavalid, //Memory port readdata valid signal
output reg av_read, //Memory port read
output reg [31:0] av_address, //Memory port address
//Streaming interface
input TxEn, //Enable transmit
input txclk, //Transmit clock
output [7:0] tx_data, //output data
output tx_dv, //qualifies dataout, startofpacket, and endofpacket
output tx_sop, //start of data packet
output tx_eop, //end of data packet
input tx_ack, //Acknowledge TX data
input [8:0] tx_stat, //Status bits
input tx_stat_valid, //Status is valid
output tx_stat_ack,
input tx_retry,
output PerPacketPad, //Per packet pad
output PerPacketCrc, //Per packet crc
output TxUnderRun, //An underrun occured
//Interrupt outputs
output reg TxB_IRQ,
output reg TxE_IRQ
);
//Some useful constant functions
`include "eth_avalon_functions.v"
localparam MINFD = max(FIFO_DEPTH,128); //Minimum 128 byte FIFO depth
localparam RFD = nextPow2(MINFD)>>2; //FIFO depth next power of 2 (and divide by 4)
//FF_FULL_THRESHOLD is the number of words in the FIFO before we set the
//almost FULL flag. In other words. We pause reading data from memory if
//the FIFO reaches this level. If we are overrunning the FIFO, this
//number needs to be reduced.
localparam FF_FULL_THRESHOLD = RFD - 16;
//Bit descriptions for TX descriptor
localparam BIT_LEN_H = 31, //Upper bit of length field
BIT_LEN_L = 16, //Lower bit of length field
//Control bits
BIT_READY = 15, //Ready control bit (1=READY Controller can write to it)
BIT_IRQ = 14, //Generate an interrupt at end of TX
BIT_WRAP = 13, //Wrap to first RX descriptor after this one
BIT_PAD = 12, //Add Padding to small frames
BIT_CRC = 11, //Add CRC
BIT_RSVD_H = 10, //Upper bit of reserved field
BIT_RSVD_L = 9, //Lower bit of reserved field
//Status bits
BIT_UR = 8, //Buffer Underrun
BIT_RTRY_H = 7, //Upper bit of retry count
BIT_RTRY_L = 4, //Lower bit of retry count
BIT_RL = 3, //Retransmission Limit
BIT_LC = 2, //Late Collision
BIT_DF = 1, //Defer Indication
BIT_CS = 0; //Carrier Sense Lost
//State bits
localparam ST_IDLE = 0,
ST_BD_RD = 1, //Read Descriptor
ST_DMA1 = 2, //Transfer first word
ST_DMA2 = 3, //Wait for data to be written to FIFO
ST_STAT = 4, //Wait for status from MAC
ST_BD_WR = 5; //Write status back to MAC
//TX State machine bits
localparam TX_IDLE = 0,
TX_SEND = 1,
TX_WAIT = 2;
wire pre_av_read;
wire [31:0] pre_av_address;
reg [5:0] state;
wire [15:0] bd_len; //Frame length from descriptor
reg [31:0] ptr;
reg [31:0] desc;
wire [1:0] valid_cnt;
reg [1:0] first_valid_cnt;
reg [1:0] last_valid_cnt;
reg [13:0] tg_cnt; //target count (number of words to read from memory)
reg [13:0] rd_cnt; //read count (number of words read from memory)
reg [13:0] wr_cnt; //write count (number of words written to FIFO)
wire [15:0] next_tg_cnt; //intentionally 2 bits larger
wire [13:0] next_rd_cnt;
wire [13:0] next_wr_cnt;
wire last_read; //Last read from memory
reg last_read_r;
wire first_write; //First write to FIFO
wire last_write; //Last write to FIFO
reg [31:0] rdata; //registered av_readdata
reg valid_rdata; //registered av_readdatavalid
wire stat_ready; //Status ready from TX
reg [BIT_UR:BIT_CS] stat;
wire stat_error; //Status indicates error
wire dff_clear;
wire [clogb2(RFD-1):0] dff_wrused;
wire dff_almost_full;
wire dff_full;
wire dff_write;
wire [35:0] dff_din;
wire dff_read;
wire dff_empty;
wire [35:0] dff_dout;
reg [2:0] tx_state;
reg tx_stat_valid_r;
wire last_byte;
wire [7:0] tx_ff_data [0:3];
wire [1:0] byte_cnt;
reg [1:0] byte_index;
//Avalon bus
assign pre_av_address = {ptr[31:2],2'b00};
assign pre_av_read = state[ST_DMA1 ] & ~dff_almost_full;
assign valid_tx_rd = pre_av_read & ~av_waitrequest;
//Descriptor bus
assign bd_read = state[ST_BD_RD];
assign bd_write = state[ST_BD_WR];
//Descriptor writeback data
assign bd_writedata[BIT_LEN_H:BIT_LEN_L] = desc[BIT_LEN_H:BIT_LEN_L]; //No modification to length
assign bd_writedata[BIT_READY] = 1'b0; // Clear ready flag
assign bd_writedata[BIT_IRQ] = desc[BIT_IRQ]; //leave IRQ
assign bd_writedata[BIT_WRAP] = desc[BIT_WRAP]; //leave WRAP
assign bd_writedata[BIT_PAD] = desc[BIT_PAD]; //leave PAD
assign bd_writedata[BIT_CRC] = desc[BIT_CRC]; //leave CRC
assign bd_writedata[BIT_RSVD_H:BIT_RSVD_L] = desc[BIT_RSVD_H:BIT_RSVD_L]; //leave reserved field
assign bd_writedata[BIT_UR:BIT_CS] = stat[BIT_UR:BIT_CS]; //set status flags
assign bd_len = bd_desc[BIT_LEN_H:BIT_LEN_L];
//Add a pipeline stage for Avalon reads
always @(posedge clk or posedge reset)
if(reset) av_read <= 1'b0;
else if(~av_waitrequest) av_read <= pre_av_read;
always @(posedge clk)
if(~av_waitrequest) av_address <= pre_av_address;
always @(posedge clk or posedge reset)
if(reset) state <= 6'd1;
else begin state <= 6'd0;
//This really is a parallel case
case(1'b1) // synopsys parallel_case
state[ST_IDLE ]: // do nothing
if(TxEn & ~stat_ready) state[ST_BD_RD] <= 1'b1;
else state[ST_IDLE] <= 1'b1;
state[ST_BD_RD]: // read descriptor
if(~bd_wait & bd_desc[BIT_READY]) state[ST_DMA1 ] <= 1'b1;
else state[ST_BD_RD] <= 1'b1;
state[ST_DMA1 ]: // issue all reads
if(valid_tx_rd & last_read)
state[ST_DMA2 ] <= 1'b1;
else state[ST_DMA1 ] <= 1'b1;
state[ST_DMA2 ]: // wait here for stat
if(last_write & valid_rdata) state[ST_STAT ] <= 1'b1;
else state[ST_DMA2 ] <= 1'b1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -