📄 generic_transmit_fifo.v
字号:
reg CODEWORD_RECENT; wire COMPLETE_FRAME_TRANSMIT; reg NEARLY_EMPTY_SIZE; reg NEARLY_EMPTY_FRAME; wire NEARLY_EMPTY_FRAME_TX; reg NEARLY_EMPTY_SIZE_TX; reg COMPLETE_FRAME_TRANSMIT_REG; reg REALLY_EMPTY_TMP; wire FRAME_TRANSMIT; reg FRAME_TRANSMIT_REG; assign DUMMY1 = 32'h00000000; assign DUMMY2 = 4'b0000; assign DUMMY3 = 16'h0000; assign DUMMY4 = 2'b00; assign DUMMY5 = 8'b00000000; assign DUMMY6 = 1'b0; assign DUMMY7 = 4'b0; assign DUMMY8 = 2'b0; assign DUMMY9 = 1'b0; assign FRAME_COUNT_ZERO = 0; assign WR_DATA = {LANE_VALID, DATA}; // LANE_VALID is attached to the top of DATA to provide the input to the FIFO assign TX_DATA_VALID = DATA_VALID & VALID_EN; // Enable DATA_VALID assign WR_EN = WR_INC; // The write enable for the FIFO is also the increment pulse for the pointer assign STATUS_UNDERRUN = INT_UNDERRUN_REG & CONTROL; assign RD_EN_TEMP = RD_INC; // The read enable for the FIFO is also the increment pulse for the pointer assign RD_EN = RD_EN_TEMP | TX_SRESET; // The FIFO must be enabled for the sreset to work assign CONTROL = RD_DATA[16]; // Represents the value of LANE_VALID(0) at the read output assign INT_NEARLY_FULL = PRE_FULL | FULL; // Need to provide a > NEARLY_FULL signal assign STATUS_FULL = FULL; // FULL is already in CLK domain, and so can go straight out assign STATUS_NEARLY_FULL = NEARLY_FULL; // NEARLY_FULL is already in CLK domain, and so can go straight out assign STATUS_NEARLY_EMPTY = NEARLY_EMPTY; // NEARLY_EMPTY is already in CLK domain assign STATUS_EMPTY = STATUS_EMPTY_INT; // STATUS_EMPTY_INT is also in CLK domain always @(TX_UNDERRUN) begin TX_UNDERRUN_OUT <= #1000 TX_UNDERRUN; end always @(TX_DATA_INT) begin TX_DATA <= #1000 TX_DATA_INT; end always @(DATA_VALID_INT) begin DATA_VALID <= #1000 DATA_VALID_INT; end assign WR_POINTER_VECTOR = WR_POINTER; assign RD_POINTER_VECTOR = RD_POINTER; // Write increment logic // FIFO can only write a data word (indicated by LANE_VALID(0) = 1'b1) when NEARLY_FULL = 1'b0, // but can write a codeword at any time, all enabled by the bus WR_ENABLE assign WRITE_ENABLE = (~(INT_NEARLY_FULL & LANE_VALID[0])) & WR_ENABLE & ((!CODEWORD_RECENT) || LANE_VALID[0]); // Underrun logic // An underrun signal will be generated if an acknowledge is received from the transmitter // when the FIFO is EMPTY and the previous word sent was a data word (indicated by RD_DATA(128) = 1'b1), // or when a forced UNDERRUN_PULSE is generated from the codeword assign TX_UNDERRUN = ((INT_UNDERRUN_REG & CONTROL) | UNDERRUN_PULSE); // Enable logic for DATA_VALID // DATA_VALID is enabled when sending data words, but only when not in an UNDERRUN condition, // where DATA_VALID must be kept at zero until the start of the next frame assign VALID_EN = CONTROL & (~TX_UNDERRUN); // Read increment logic // FIFO can be read and incremented on a number of different occasions: // 1. The device is just coming out of being EMPTY // 2. The frame went UNDERRUN during transmission - the READ_ENABLE is then left high to cycle through // to the end of the frame as quickly as possible, where the UNDERRUN status is cancelled. // 3. A front loaded read_enable has been enabled assign READ_ENABLE = PRE_READ_ENABLE | INT_UNDERRUN | ((~STATUS_EMPTY_INT_TX) & STATUS_EMPTY_INT_TX_REG & EMPTY_VALID & (~RD_DATA_INT[16])); // The RD_DATA from the FIFO is registered to help with timing. The data will only be registered // to this registered when outputting a START signal or when HALF_BIT is high indicating that // that the data needs to be read assign OUT_ENABLE = START | HALF_BIT; // Acknowledge logic // An acknowledge is only sent to the bus when the data is being written into the FIFO assign ACK = WR_EN; // Error logic // An error signal is sent when the bus tries to write data, but for some reason the // internal logic will not let it be written into the FIFO assign ERR = WR_ENABLE & (~WR_EN); // purpose: Determine if any data has been received in frame // type : Sequential always @(posedge CLK) begin if (TX_FIFO_SRESET == 1'b1 || (WR_ENABLE == 1'b1 && LANE_VALID[0] == 1'b0)) CODEWORD_RECENT <= 1'b1; else begin if (WR_ENABLE == 1'b1) CODEWORD_RECENT <= 1'b0; end end // Create a pre_READ_ENABLE // This creates a front loaded registered signal for the READ_ENABLE // This should go high when: // An acknowledge is received from the MAC or when in STREAM mode with DATA on the READ, and // when in STREAM mode with no reading happening or an acknowledge is received, and top-half of data is selectecd, // OR FIFO is not nearly empty when the read data is the first data after a control word, // or the control word is the next one to read and the output is the top-half, // and no start has just being sent or is being sent. always @(TX_ACK or STREAM or CONTROL or RD_INC or HALF_BIT or NEARLY_EMPTY_TX or RD_DATA_INT[16] or START or START_REG) begin if (((TX_ACK == 1'b1 || (STREAM == 1'b1 && CONTROL == 1'b1)) && (((STREAM == 1'b1 && RD_INC == 1'b0) || TX_ACK == 1'b1) && HALF_BIT == 1'b0)) || (NEARLY_EMPTY_TX == 1'b0 && ((RD_DATA_INT[16] == 1'b1 && CONTROL == 1'b0) || (RD_DATA_INT[16] == 1'b0 && CONTROL == 1'b1 && HALF_BIT == 1'b1 )) && START == 1'b0 && START_REG == 1'b0)) PRE_READ_ENABLE_COMB <= 1'b1; else PRE_READ_ENABLE_COMB <= 1'b0; end always @(posedge TX_CLK) begin if (TX_SRESET == 1'b1) PRE_READ_ENABLE <= 1'b0; else PRE_READ_ENABLE <= PRE_READ_ENABLE_COMB; end // Generate the correct size and number of block rams for the FIFO_SIZE passed in assign WR_DATA_PADDED = {16'h0000, WR_DATA[15:0]}; assign WR_VLD_PADDED = {2'b00, WR_DATA[17:16]}; // Instantiate the correct size and number of block rams... // We need to use Verilog2001 features to do this. These are currently supported by XST, // and MTI support is slated for December... integer i; integer j; // Use the code below when Verilog 2001 generate statements are supported.... /* generate if (FIFO_SIZE >= 512) begin generate for (i = 0; i < 1; i = i + 1) begin RAMB16_S36_S36 RAM_SIZE111 (.DIA(WR_DATA_PADDED), .DIB(DUMMY1), .DIPA(WR_VLD_PADDED), .DIPB(DUMMY2), .ENA(PWR), .ENB(RD_EN), .WEA(WR_EN), .WEB(GND), .SSRA(GND), .SSRB(TX_SRESET), .CLKA(CLK), .CLKB(TX_CLK), .ADDRA(WR_POINTER_VECTOR), .ADDRB(RD_POINTER_VECTOR), .DOB(RD_TEMP1), .DOPB(RD_TEMP2) ); end endgenerate assign RD_DATA_INT = {RD_TEMP2[1:0], RD_TEMP1[15:0]}; end else if(FIFO_SIZE == 1024) begin generate for (i = 0; i < 1; i = i + 1) begin RAMB16_S18_S18 RAM_SIZE211 (.DIA(WR_DATA[15:0]), .DIB(DUMMY3), .DIPA(WR_DATA[17:16]), .DIPB(DUMMY4), .ENA(PWR), .ENB(RD_EN), .WEA(WR_EN), .WEB(GND), .SSRA(GND), .SSRB(TX_SRESET), .CLKA(CLK), .CLKB(TX_CLK), .ADDRA(WR_POINTER_VECTOR), .ADDRB(RD_POINTER_VECTOR), .DOB(RD_DATA_INT[15:0]), .DOPB(RD_DATA_INT[17:16]) ); end endgenerate end else if(FIFO_SIZE == 2048) begin generate for (i = 0; i < 2; i = i + 1) begin RAMB16_S9_S9 RAM_SIZE311 (.DIA(WR_DATA[(i*8)+7:(i*8)]), .DIB(DUMMY5), .DIPA(WR_DATA[i+16:i+16]), .DIPB(DUMMY6), .ENA(PWR), .ENB(RD_EN), .WEA(WR_EN), .WEB(GND), .SSRA(GND), .SSRB(TX_SRESET), .CLKA(CLK), .CLKB(TX_CLK), .ADDRA(WR_POINTER_VECTOR), .ADDRB(RD_POINTER_VECTOR), .DOB(RD_DATA_INT[(i*8)+7:(i*8)]), .DOPB(RD_DATA_INT[i+16:i+16]) ); end endgenerate end else if(FIFO_SIZE == 4096) begin generate for (i = 0; i < 4; i = i + 1) begin RAMB16_S4_S4 RAM_SIZE411 (.DIA(WR_DATA[(i*4)+3:(i*4)]), .DIB(DUMMY7), .ENA(PWR), .ENB(RD_EN), .WEA(WR_EN), .WEB(GND), .SSRA(GND), .SSRB(TX_SRESET), .CLKA(CLK), .CLKB(TX_CLK), .ADDRA(WR_POINTER_VECTOR), .ADDRB(RD_POINTER_VECTOR), .DOB(RD_DATA_INT[(i*4)+3:(i*4)]) ); end endgenerate assign WR_DATA_PAD2 = {2'b00, WR_DATA[17:16]}; RAMB16_S4_S4 RAM_SIZE41B (.DIA(WR_DATA_PAD2), .DIB(DUMMY7), .ENA(PWR), .ENB(RD_EN), .WEA(WR_EN), .WEB(GND), .SSRA(GND), .SSRB(TX_SRESET), .CLKA(CLK), .CLKB(TX_CLK), .ADDRA(WR_POINTER_VECTOR), .ADDRB(RD_POINTER_VECTOR), .DOB(RD_TEMP3) ); assign RD_DATA_INT[17:16] = RD_TEMP3[1:0]; end else if(FIFO_SIZE == 8192) begin generate for (i = 0; i < 9; i = i + 1) begin RAMB16_S2_S2 RAM_SIZE511 (.DIA(WR_DATA[(i*2)+1:(i*2)]), .DIB(DUMMY4), .ENA(PWR), .ENB(RD_EN), .WEA(WR_EN), .WEB(GND), .SSRA(GND), .SSRB(TX_SRESET), .CLKA(CLK), .CLKB(TX_CLK), .ADDRA(WR_POINTER_VECTOR), .ADDRB(RD_POINTER_VECTOR), .DOB(RD_DATA_INT[(i*2)+1:(i*2)]) ); end endgenerate end else // (FIFO_SIZE == 16384) begin generate for (i = 0; i < 18; i = i + 1) begin RAMB16_S1_S1 RAM_SIZE611 (.DIA(WR_DATA[i:i]), .DIB(DUMMY9), .ENA(PWR), .ENB(RD_EN), .WEA(WR_EN), .WEB(GND), .SSRA(GND), .SSRB(TX_SRESET), .CLKA(CLK), .CLKB(TX_CLK), .ADDRA(WR_POINTER_VECTOR), .ADDRB(RD_POINTER_VECTOR), .DOB(RD_DATA_INT[i:i]) ); end endgenerate end endgenerate */ // CHANGES REQUIRED // Use the code below when Verilog 2001 generate statements are NOT supported... // Uncomment the code for the correct FIFO_SIZE... // (FIFO_SIZE == 512) /* RAMB16_S36_S36 RAM_SIZE111 (.DIA(WR_DATA_PADDED), .DIB(DUMMY1), .DIPA(WR_VLD_PADDED), .DIPB(DUMMY2), .ENA(PWR), .ENB(RD_EN), .WEA(WR_EN), .WEB(GND), .SSRA(GND), .SSRB(TX_SRESET), .CLKA(CLK), .CLKB(TX_CLK), .ADDRA(WR_POINTER_VECTOR), .ADDRB(RD_POINTER_VECTOR), .DOB(RD_TEMP1), .DOPB(RD_TEMP2) ); assign RD_DATA_INT = {RD_TEMP2[1:0], RD_TEMP1[15:0]};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -