📄 generic_transmit_fifo.v
字号:
else FRAME_COUNT <= FRAME_COUNT_COMB; end // Due to the fact that the frame is written in TX_FIFO_CLK and we are counting frames in TX_CLK // we need to reclock the writing process. We increment the FRAME_COUNT when the first word // of a new frame is written and when the codeword is written. These two events can not occur at // the same time. However, due to timing unknowns in the reclocking process, their reclocked // versions may appear on the same TX_CLK edge. Therefore, the FRAME_COUNT must be incremented // twice under this sceanrio. It is not possible to get two codewords or two start of frames // concurrently. // Create the additional count if necessary always @(FRAME_WRITE or FRAME_WRITE_REG or CODE_WRITE or CODE_WRITE_REG) begin if (FRAME_WRITE == 1'b1 && FRAME_WRITE_REG == 1'b0 && CODE_WRITE == 1'b1 && CODE_WRITE_REG == 1'b1) FRAME_WRITE_ADD_COMB <= 1'b1; else FRAME_WRITE_ADD_COMB <= 1'b0; end always @(posedge TX_CLK) begin if (TX_SRESET == 1'b1) FRAME_WRITE_ADD <= 1'b0; else FRAME_WRITE_ADD <= FRAME_WRITE_ADD_COMB; end // Determine if a frame write has occurred always @(posedge TX_CLK) begin if (TX_SRESET == 1'b1) begin FRAME_WRITE <= 1'b0; FRAME_WRITE_REG <= 1'b0; CODE_WRITE <= 1'b0; CODE_WRITE_REG <= 1'b0; end else begin FRAME_WRITE_REG <= FRAME_WRITE; FRAME_WRITE <= FRAME_WRITE_FIFO; CODE_WRITE_REG <= CODE_WRITE; CODE_WRITE <= CODE_WRITE_FIFO; end end // Register the actual start of writing of a codeword in TX_FIFO_CLK always @(WR_DATA[16] or WR_INC) begin if (WR_DATA[16] == 1'b0 && WR_INC == 1'b1) CODE_WRITE_FIFO_COMB <= 1'b1; else CODE_WRITE_FIFO_COMB <= 1'b0; end always @(posedge CLK) begin if (TX_FIFO_SRESET == 1'b1) CODE_WRITE_FIFO <= 1'b0; else CODE_WRITE_FIFO <= CODE_WRITE_FIFO_COMB; end // Register the actual start of writing of a frame in TX_FIFO_CLK always @(FRAME_WRITE_FIFO_HOLD or WR_INC) begin if (FRAME_WRITE_FIFO_HOLD == 1'b1 && WR_INC == 1'b1) FRAME_WRITE_FIFO_COMB <= 1'b1; else FRAME_WRITE_FIFO_COMB <= 1'b0; end always @(posedge CLK) begin if (TX_FIFO_SRESET == 1'b1) FRAME_WRITE_FIFO <= 1'b0; else FRAME_WRITE_FIFO <= FRAME_WRITE_FIFO_COMB; end // Hold the writing of a codeword to enable the indentifaction of a new frame write always @(WR_DATA[16] or WR_INC or FRAME_WRITE_FIFO_HOLD) begin if (WR_DATA[16] == 1'b0 && WR_INC == 1'b1) FRAME_WRITE_FIFO_HOLD_COMB <= 1'b1; else if (WR_INC == 1'b1) FRAME_WRITE_FIFO_HOLD_COMB <= 1'b0; else FRAME_WRITE_FIFO_HOLD_COMB <= FRAME_WRITE_FIFO_HOLD; end always @(posedge CLK) begin if (TX_FIFO_SRESET == 1'b1) FRAME_WRITE_FIFO_HOLD <= 1'b1; // initialise to 1'b1 so that the first new frame is recognised else FRAME_WRITE_FIFO_HOLD <= FRAME_WRITE_FIFO_HOLD_COMB; end assign FRAME_READ = START | ((~RD_DATA_INT[16]) & CONTROL & OUT_ENABLE); // Create the start pulse when a control word is sitting on the output of the FIFO and // the NEARLY_EMPTY signal is low indicating a new transmission can begin always @(REALLY_EMPTY or NEARLY_EMPTY_TX or RD_DATA_INT[16] or CONTROL or HALF_BIT or START or START_REG) begin if (REALLY_EMPTY == 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) START_COMB <= 1'b1; else START_COMB <= 1'b0; end always @(posedge TX_CLK) begin if (TX_SRESET == 1'b1) START <= 1'b0; else START <= START_COMB; end // Capture a frame transmission commencement because of a complete frame stored in FIFO assign COMPLETE_FRAME_TRANSMIT = (START_COMB & (~NEARLY_EMPTY_FRAME_TX)) | (COMPLETE_FRAME_TRANSMIT_REG & (~((~RD_DATA_INT[16]) & CONTROL & OUT_ENABLE))); always @(posedge TX_CLK) begin if (TX_SRESET == 1'b1) COMPLETE_FRAME_TRANSMIT_REG <= 1'b0; else COMPLETE_FRAME_TRANSMIT_REG <= COMPLETE_FRAME_TRANSMIT; end // Capture a frame transmission commencement assign FRAME_TRANSMIT = START_COMB | (FRAME_TRANSMIT_REG & (~((~RD_DATA_INT[16]) & CONTROL & OUT_ENABLE))); always @(posedge TX_CLK) begin if (TX_SRESET == 1'b1) FRAME_TRANSMIT_REG <= 1'b0; else FRAME_TRANSMIT_REG <= FRAME_TRANSMIT; end // register start and hold until the device goes into STREAM mode always @(START or STREAM or START_REG) begin if (START == 1'b1) START_REG_COMB <= 1'b1; else if (STREAM == 1'b1) START_REG_COMB <= 1'b0; else START_REG_COMB <= START_REG; end always @(posedge TX_CLK) begin if (TX_SRESET == 1'b1) START_REG <= 1'b0; else START_REG <= START_REG_COMB; end // When an acknowledge is received from the transmitter, the module must stream the data // to the transmitter, stopping only when the end of the frame is reached always @(TX_ACK or CONTROL or STREAM) begin if (TX_ACK == 1'b1) STREAM_COMB <= 1'b1; else if (CONTROL == 1'b0) STREAM_COMB <= 1'b0; else STREAM_COMB <= STREAM; end always @(posedge TX_CLK) begin if (TX_SRESET == 1'b1) STREAM <= 1'b0; else STREAM <= STREAM_COMB; end assign MULT_SEL = HALF_BIT; // Multiplex the read data from the FIFO to create the half word data for transmission always @(MULT_SEL or RD_DATA) begin case (MULT_SEL) 1'b0 : begin TX_DATA_INT <= RD_DATA[7:0]; DATA_VALID_INT <= RD_DATA[16]; end default : begin TX_DATA_INT <= RD_DATA[15:8]; DATA_VALID_INT <= RD_DATA[17]; end endcase end // Write pointer generation always @(posedge CLK) begin if (TX_FIFO_SRESET == 1'b1) WR_POINTER <= 0; else if(WR_INC == 1'b1) #100 WR_POINTER <= WR_POINTER + 1; end // Read pointer generation always @(posedge TX_CLK) begin if (TX_SRESET == 1'b1) RD_POINTER <= 0; else if(RD_INC == 1'b1) #100 RD_POINTER <= RD_POINTER + 1; end // Overload control // Overload status is set if the bus tries to write a data word into the FIFO when it is // PRE_FULL (1 before FULL). The status is reset when a codeword is written always @(WR_ENABLE or LANE_VALID[0] or PRE_FULL or STATUS_OVERLOAD_INT) begin if (WR_ENABLE == 1'b1) begin if (LANE_VALID[0] == 1'b0) STATUS_OVERLOAD_COMB <= 1'b0; else if (PRE_FULL == 1'b1) STATUS_OVERLOAD_COMB <= 1'b1; else STATUS_OVERLOAD_COMB <= STATUS_OVERLOAD_INT; end else STATUS_OVERLOAD_COMB <= STATUS_OVERLOAD_INT; end always @(posedge CLK) begin if (TX_FIFO_SRESET == 1'b1) STATUS_OVERLOAD_INT <= 1'b0; else STATUS_OVERLOAD_INT <= STATUS_OVERLOAD_COMB; end assign STATUS_OVERLOAD = STATUS_OVERLOAD_INT; // Underrun control // The UNDERRUN status signal is set when the transmitter acknowledges a data frame and the // FIFO is empty and the FIFO is transmitting a frame to the MAC. It is reset by the // transmission of a codeword. always @(CONTROL or TX_ACK or STREAM or REALLY_EMPTY or INT_UNDERRUN) begin if (CONTROL == 1'b0) INT_UNDERRUN_COMB <= 1'b0; else if ((TX_ACK == 1'b1 || STREAM == 1'b1) && REALLY_EMPTY == 1'b1) INT_UNDERRUN_COMB <= 1'b1; else INT_UNDERRUN_COMB <= INT_UNDERRUN; end always @(posedge TX_CLK) begin if (TX_SRESET == 1'b1) INT_UNDERRUN <= 1'b0; else INT_UNDERRUN <= INT_UNDERRUN_COMB; end // Underrun pulse generation // The host can force the transmitter to invalidate the current frame transmission, by sending // a codeword with the most significant bit of DATA set to 1'b1. When this is read from the // other side of the FIFO, a one pulse wide UNDERRUN signal is generated. always @(RD_DATA[15] or CONTROL) begin if (RD_DATA[15] == 1'b1 && CONTROL == 1'b0) UNDERRUN_SEL_COMB <= 1'b1; else UNDERRUN_SEL_COMB <= 1'b0; end always @(posedge TX_CLK) begin if (TX_SRESET == 1'b1) UNDERRUN_SEL <= 1'b0; else UNDERRUN_SEL <= UNDERRUN_SEL_COMB; end always @(UNDERRUN_SEL or RD_DATA or CONTROL) begin case (UNDERRUN_SEL) 1'b0 : UNDERRUN_PULSE <= RD_DATA[15] && (~CONTROL); default : UNDERRUN_PULSE <= 1'b0; endcase end // Half bit generation to ensure data is multiplexed correctly for each half word, // and that it resets to 0 for each increment of the read address always @(HALF_BIT or STREAM or CONTROL or RD_INC or TX_ACK) begin if (HALF_BIT == 1'b1) HALF_BIT_COMB <= 1'b0; else if ((STREAM == 1'b1 && CONTROL == 1'b1 && RD_INC == 1'b0) || TX_ACK == 1'b1) HALF_BIT_COMB <= 1'b1; else HALF_BIT_COMB <= HALF_BIT; end always @(posedge TX_CLK) begin if (TX_SRESET == 1'b1) HALF_BIT <= 1'b0; else HALF_BIT <= HALF_BIT_COMB; end /*---------------------------------------------------------------- ---- Allow flags determine whether FIFO control logic can ---- operate. If read_enable is driven high, and the FIFO is ---- not Empty, then Reads are allowed. Similarly, if the ---- write_enable signal is high, and the FIFO is not Full, ---- then Writes are allowed. ---- ----------------------------------------------------------------*/ assign RD_INC = (READ_ENABLE & ~REALLY_EMPTY); assign WR_INC = (WRITE_ENABLE & ~FULL); assign FULL_ALLOW = (FULL | WRITE_ENABLE); assign EMPTY_ALLOW = (REALLY_EMPTY | READ_ENABLE); assign NEARLY_FULL_ALLOW = (PRE_FULL | WRITE_ENABLE); /*--------------------------------------------------------------- ---- Empty flag is set on reset (initial), or when gray ---- code counters are equal, or when there is one word in ---- the FIFO, and a Read operation is ab
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -