📄 generic_receive_fifo.v
字号:
else begin if (RX_DATA_VALID == 1'b1) GOOD_BAD_FRAME_RECENT <= 1'b0; end end// purpose: Create Write Enables for FIFO. A single 16-bit word write is perfomed over 2 8-bit word writes.// This is controlled by two separate write enables, an upper and a lower.// type : sequential assign WR_LOWER_COMB = (RX_DATA_VALID_REG1 & (~RX_DATA_VALID_REG2)) | // first 8-bit word of frame. (RX_DATA_VALID_REG1 & (~WR_LOWER)) | // alternate words in frame. TRIGGER_CODEWORD_REG; // Code word to complete frame. assign WR_UPPER_COMB = (RX_DATA_VALID_REG1 & RX_DATA_VALID_REG2 & WR_LOWER) | // alternate words in frame. (RX_DATA_VALID_REG1 & (~RX_DATA_VALID)) | // complete last word of frame. TRIGGER_CODEWORD_REG; // Code word to complete frame. always @(posedge RX_CLK) begin if(RX_SRESET == 1'b1) begin WR_LOWER <= 1'b0; WR_UPPER <= 1'b0; end else begin WR_LOWER <= WR_LOWER_COMB; WR_UPPER <= WR_UPPER_COMB; end end // purpose: Only allow writes if FIFO is not full // type : combinatorial assign WR_UPPER_ALLOW = WR_UPPER & ~FULL; assign WR_LOWER_ALLOW = WR_LOWER & ~FULL; // purpose: Create Write Address Pointer for FIFO. This is incremented after every two 8-bit word writes.// In this implementation, all frames (Good and Bad) are written into the Rx FIFO. always @(posedge RX_CLK) begin if(RX_SRESET == 1'b1) WR_ADDR <= 0; else if (WR_UPPER_ALLOW == 1'b1) WR_ADDR <= WR_ADDR + 1; end // purpose: Format the data valid signals to be written to the FIFO. These are formatted from 1-bits // to 2-bits. Please note that, for normal frame data, the data valid signals represent // valid bytes on the data bus (data valid bit zero represents the data byte containing bits // 7 downto 0; data valid bit 1 represents the data byte containing bits 15 downto 8). // For code words, data valids are set to the unique code 0x2 which will never be obtained // for normal frame data.// type : sequential always @(posedge RX_CLK) begin if(RX_SRESET == 1'b1) DATA_VALID_2BIT <= 0; else if (TRIGGER_CODEWORD_REG == 1'b1) DATA_VALID_2BIT[1:1] <= 1'b1; // produce code word else if (RX_DATA_VALID == 1'b0 && WR_UPPER == 1'b1) DATA_VALID_2BIT[1:1] <= 1'b0; // complete end of frame else DATA_VALID_2BIT[1] <= RX_DATA_VALID_REG1; // normal frame data if (TRIGGER_CODEWORD_REG == 1'b1) DATA_VALID_2BIT[0:0] <= 1'b0; // produce code word else DATA_VALID_2BIT[0] <= RX_DATA_VALID_REG1; // normal frame data end // purpose: Format the data words to be written to the FIFO. These are formatted from 8-bits to 16-bits. // A Code Word is appended at the end of a frame. This Code Word is identified by the unique // data valid code of 0x2. // type : sequential always @(posedge RX_CLK) begin if(RX_SRESET == 1'b1) RX_DATA_16BIT <= 0; else if (TRIGGER_CODEWORD_REG == 1'b1) // create code word begin RX_DATA_16BIT[15] <= GOOD_FRAME_HELD; RX_DATA_16BIT[14] <= BAD_FRAME_HELD; RX_DATA_16BIT[13] <= FULL_HELD; RX_DATA_16BIT[12:0] <= 0; end else // frame data begin RX_DATA_16BIT[15:8] <= RX_DATA_REG; RX_DATA_16BIT[7:0] <= RX_DATA_REG; end end /*------------------------------------------------------------------------------------- THE FOLLOWING CODE CREATES THE FIFO READ LOGIC FOR THE GENERIC INTERFACE -------------------------------------------------------------------------------------*/// purpose: Only allow reads if FIFO is not empty // type : combinatorial assign RD_ALLOW = RD_ENABLE & ~REALLY_EMPTY; // purpose: Create Binary Read Address Pointer for FIFO. // type : sequential always @(posedge FIFO_CLK) begin if(RX_FIFO_SRESET == 1'b1) RD_ADDR <= 0; else if (RD_ALLOW == 1'b1) RD_ADDR <= RD_ADDR + 1; end // purpose: Create Read Acknowledge (or Error) Signal to Client Interface. // type : sequential always @(posedge FIFO_CLK) begin if(RX_FIFO_SRESET == 1'b1) begin RD_ACK_INT <= 1'b0; RD_ERR <= 1'b0; end else begin RD_ACK_INT <= RD_ALLOW; RD_ERR <= RD_ENABLE & (~RD_ALLOW); end end /*------------------------------------------------------------------------------------- THE FOLLOWING CODE INSTANTIATES VIRTEX II BLOCK RAM PRIMITIVES TO CREATE FIFO -------------------------------------------------------------------------------------*/// purpose: Build Receive Path FIFO out of Block RAM's// type : component RX_BLOCKRAM #(FIFO_SIZE) CREATE_FIFO ( .SSRB(RX_FIFO_SRESET), .DIA(RX_DATA_16BIT), // data words are written to the data inputs. .DIPA(DATA_VALID_2BIT), // data valids are written to the extra parity inputs. .ADDRA(WR_ADDR), .ENA_UPPER(WR_UPPER_ALLOW), .ENA_LOWER(WR_LOWER_ALLOW), .CLKA(RX_CLK), .ADDRB(RD_ADDR), .ENB(RD_ALLOW), .CLKB(FIFO_CLK), .DOB(DATA_OUT), // data words are read from the data inputs. .DOPB(DATA_VALID_OUT_INT) // data valids are read from the extra parity inputs. );/*------------------------------------------------------------------------------------- THE FOLLOWING CODE CONVERTS THE BINARY WRITE POINTER INTO PIPELINED GRAY CODES.---- This enables accurate clock boundary crossing of the write pointer. ---- Please refer to Xilinx Application Note 131 for an explanation of this logic. -------------------------------------------------------------------------------------*/// purpose: Convert Binary Write Pointer to Gray Code. // type : combinatorial always @(WR_ADDR) begin WR_GRAY[log2_FIFO_SIZE-1] <= WR_ADDR[log2_FIFO_SIZE-1]; for (i = log2_FIFO_SIZE-2; i >= 0; i = i - 1) WR_GRAY[i] <= WR_ADDR[i+1] ^ WR_ADDR[i]; end // purpose: Register Gray Code Write Pointer. // type : sequential always @(posedge RX_CLK) begin if(RX_SRESET == 1'b1) begin WR_NEXTGRAY[log2_FIFO_SIZE-1] <= 1'b1; WR_NEXTGRAY[log2_FIFO_SIZE-2:0] <= 0; WR_TRUEGRAY <= 0; end else begin WR_TRUEGRAY <= WR_GRAY; if (WR_UPPER_ALLOW == 1'b1) WR_NEXTGRAY <= WR_GRAY; end end // purpose: 2nd Pipeline Registered Version of Write Pointer Gray Code. // type : sequential always @(posedge RX_CLK) begin if(RX_SRESET == 1'b1) begin WR_ADDRGRAY[log2_FIFO_SIZE-1] <= 1'b1; WR_ADDRGRAY[log2_FIFO_SIZE-2:1] <= 0; WR_ADDRGRAY[0] <= 1'b1; end else if (WR_UPPER_ALLOW == 1'b1) WR_ADDRGRAY <= WR_NEXTGRAY; end // purpose: 3rd Pipeline Registered Version of Write Pointer Gray Code. // type : sequential always @(posedge RX_CLK) begin if(RX_SRESET == 1'b1) begin WR_LASTGRAY[log2_FIFO_SIZE-1] <= 1'b1; WR_LASTGRAY[log2_FIFO_SIZE-2:2] <= 0; WR_LASTGRAY[1] <= 1'b1; WR_LASTGRAY[0] <= 1'b1; end else if (WR_UPPER_ALLOW == 1'b1) WR_LASTGRAY <= WR_ADDRGRAY; end /*------------------------------------------------------------------------------------- THE FOLLOWING CODE CONVERTS THE BINARY READ POINTER INTO PIPELINED GRAY CODES ---- This enables accurate clock boundary crossing of the read pointer. ---- Please refer to Xilinx Application Note 131 for an explanation of this logic. -------------------------------------------------------------------------------------*/// purpose: Convert binary read pointer to Gray Code. // type : sequential always @(posedge FIFO_CLK) begin if(RX_FIFO_SRESET == 1'b1) begin RD_NEXTGRAY[log2_FIFO_SIZE-1] <= 1'b1; RD_NEXTGRAY[log2_FIFO_SIZE-2:0] <= 0; end else if (RD_ALLOW == 1'b1) begin RD_NEXTGRAY[log2_FIFO_SIZE-1] <= RD_ADDR[log2_FIFO_SIZE-1]; for (i = log2_FIFO_SIZE-2; i >= 0; i = i - 1) RD_NEXTGRAY[i] <= RD_ADDR[i+1] ^ RD_ADDR[i]; end end // purpose: 2nd Pipeline Registered Version of Read Pointer Gray Code. // type : sequential always @(posedge FIFO_CLK)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -