📄 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. ////
//// ////
//////////////////////////////////////////////////////////////////////
// History:
// 07/03/08 - Repaired bug with determining number of valid
// bytes corresponding to last data read from
// memory. Code was examining length field from
// descriptor input rather than registered
// descriptor data.
//
// 08/12/08 - Added logic to prevent FIFO overflows when
// Avalon BUS has large latency.
//
module eth_avalon_txdma #(parameter FIFO_DEPTH=128) (
//Commaon signals
input clk, // System clock
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)
localparam FIFO_MARGIN = 5; // Cushion between FIFO depth and our perceived depth
localparam FIFO_THRESHOLD = RFD - FIFO_MARGIN;
//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, // Waiting for data to transmit
TX_SEND = 1, // Sending transmit data
TX_WAIT = 2; // Waiting for status from MAC
wire pre_av_read; // pre-registered avalon read signal
wire [31:0] pre_av_address; // pre_registered avalon address
wire valid_tx_rd; // Avalon bus acknowledged read
reg [5:0] state; // State machine bits
wire [15:0] bd_len; // Frame length from descriptor
reg [31:0] ptr; // Memory read pointer
reg [31:0] desc; // Registered bd_desc
wire [15:0] desc_len; // Frame length from stored descriptor
wire [1:0] valid_cnt; // Number of valid bytes in current data word
reg [1:0] first_valid_cnt;// Number of valid bytes in first data word
reg [1:0] last_valid_cnt; // Number of valid bytes in last data word
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)
reg [13:0] rd_pending; // Number of reads pending (used to gate reads for FIFO protection)
reg pipe_hold; // Hold the pipeline until some of the reads have come back
wire [15:0] next_tg_cnt; // intentionally 2 bits larger
wire [13:0] next_rd_cnt; // next value of rd_cnt
wire [13:0] next_wr_cnt; // next value of wr_cnt
wire last_read; // Last read from memory
reg last_read_r; // Registered last_read
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; // Data FIFO clear
wire [clogb2(RFD-1)-1:0] dff_wrused; // Amount of space used in data FIFO
reg [clogb2(RFD-1):0] dff_used_la;// Future value of dff_wrused when all reads are finished
wire dff_full; // Data FIFO full
wire dff_write; // Data FIFO write
wire [35:0] dff_din; // Data FIFO data input
wire dff_read; // Data FIFO read
wire dff_empty; // Data FIFO empty
wire [35:0] dff_dout; // Data FIFO data output
reg [2:0] tx_state; // Transmit state machine bits
reg tx_stat_valid_r;// Registered tx_stat_valid
wire tx_start; // Start signal to transmit state machine
wire last_byte; // Indicates last valid byte of current data word
wire [7:0] tx_ff_data [0:3];// Transmit bytes from data FIFO
wire [1:0] byte_cnt; // Indicates how many bytes are valid from data FIFO
reg [1:0] byte_index; // Indexes tx_ff_data for byte transmission
//Avalon bus
assign pre_av_address = {ptr[31:2],2'b00};
assign pre_av_read = state[ST_DMA1 ] & ~pipe_hold;
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];
assign desc_len = 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -