diff --git a/src/generic/mem/ram2p1r1wbe_512x64.sv b/src/generic/mem/ram2p1r1wbe_2048x64.sv similarity index 100% rename from src/generic/mem/ram2p1r1wbe_512x64.sv rename to src/generic/mem/ram2p1r1wbe_2048x64.sv diff --git a/src/uncore/clint_apb.sv b/src/uncore/clint_apb.sv index 58f80c26e..41c9f47ef 100644 --- a/src/uncore/clint_apb.sv +++ b/src/uncore/clint_apb.sv @@ -76,7 +76,7 @@ module clint_apb import cvw::*; #(parameter cvw_t P) ( default: PRDATA <= '0; endcase end - always_ff @(posedge PCLK or negedge PRESETn) + always_ff @(posedge PCLK) if (~PRESETn) begin MSIP <= 1'b0; MTIMECMP <= 64'hFFFFFFFFFFFFFFFF; // Spec says MTIMECMP is not reset, but we reset to maximum value to prevent spurious timer interrupts @@ -92,7 +92,7 @@ module clint_apb import cvw::*; #(parameter cvw_t P) ( // eventually replace MTIME logic below with timereg // timereg tr(PCLK, PRESETn, TIMECLK, memwrite & (entry==16'hBFF8), 1'b0, PWDATA, MTIME, done); - always_ff @(posedge PCLK or negedge PRESETn) + always_ff @(posedge PCLK) if (~PRESETn) begin MTIME <= '0; end else if (memwrite & entry == 16'hBFF8) begin @@ -251,4 +251,4 @@ module graytobinary #(parameter N) ( assign b[i] = g[i] ^ b[i+1]; end endmodule -*/ \ No newline at end of file +*/ diff --git a/src/uncore/gpio_apb.sv b/src/uncore/gpio_apb.sv index 49a8db06b..7721d9986 100644 --- a/src/uncore/gpio_apb.sv +++ b/src/uncore/gpio_apb.sv @@ -82,8 +82,8 @@ module gpio_apb import cvw::*; #(parameter cvw_t P) ( else assign PRDATA = Dout; // register access - always_ff @(posedge PCLK, negedge PRESETn) - if (~PRESETn) begin // asynch reset + always_ff @(posedge PCLK) + if (~PRESETn) begin input_en <= '0; output_en <= '0; output_val <= '0; diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index b54480de3..635e4ef10 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -61,6 +61,10 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( localparam SPI_IE = 8'h70; localparam SPI_IP = 8'h74; + // receive shift register states + typedef enum logic [1:0] {ReceiveShiftFullState, ReceiveShiftNotFullState, ReceiveShiftDelayState} rsrstatetype; + + // SPI control registers. Refer to SiFive FU540-C000 manual logic [11:0] SckDiv; logic [1:0] SckMode; @@ -88,8 +92,11 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( logic ReceiveFIFOReadIncrement; logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty; logic [7:0] TransmitFIFOReadData; - logic [2:0] TransmitWriteWatermarkLevel, ReceiveReadWatermarkLevel; + /* verilator lint_off UNDRIVEN */ + logic [2:0] TransmitWriteWatermarkLevel, ReceiveReadWatermarkLevel; // unused generic FIFO outputs + /* verilator lint_off UNDRIVEN */ logic [7:0] ReceiveShiftRegEndian; // Reverses ReceiveShiftReg if Format[2] set (little endian transmission) + rsrstatetype ReceiveState, ReceiveNextState; // Transmission signals logic sck; @@ -150,7 +157,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( else assign PRDATA = Dout; // Register access - always_ff@(posedge PCLK, negedge PRESETn) + always_ff@(posedge PCLK) if (~PRESETn) begin SckDiv <= 12'd3; SckMode <= 2'b0; @@ -215,7 +222,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // Active at 2x SCLK frequency to account for implicit half cycle delays and actions on both clock edges depending on phase assign SCLKenable = (DivCounter == SckDiv); assign SCLKenableEarly = ((DivCounter + 12'b1) == SckDiv); - always_ff @(posedge PCLK, negedge PRESETn) + always_ff @(posedge PCLK) if (~PRESETn) DivCounter <= '0; else if (SCLKenable) DivCounter <= 12'b0; else DivCounter <= DivCounter + 12'b1; @@ -229,33 +236,56 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( assign ImplicitDelay2 = SckMode[0] ? 9'b1 : 9'b0; // Calculate when tx/rx shift registers are full/empty - TransmitShiftFSM TransmitShiftFSM(PCLK, PRESETn, TransmitFIFOReadEmpty, ReceivePenultimateFrame, Active0, TransmitShiftEmpty); - ReceiveShiftFSM ReceiveShiftFSM(PCLK, PRESETn, SCLKenable, ReceivePenultimateFrame, SampleEdge, SckMode[0], ReceiveShiftFull); + + // Transmit Shift FSM + always_ff @(posedge PCLK) + if (~PRESETn) TransmitShiftEmpty <= 1'b1; + else if (TransmitShiftEmpty) begin + if (TransmitFIFOReadEmpty | (~TransmitFIFOReadEmpty & (ReceivePenultimateFrame & Active0))) TransmitShiftEmpty <= 1'b1; + else if (~TransmitFIFOReadEmpty) TransmitShiftEmpty <= 1'b0; + end else begin + if (ReceivePenultimateFrame & Active0) TransmitShiftEmpty <= 1'b1; + else TransmitShiftEmpty <= 1'b0; + end + + // Receive Shift FSM + always_ff @(posedge PCLK) + if (~PRESETn) ReceiveState <= ReceiveShiftNotFullState; + else if (SCLKenable) begin + case (ReceiveState) + ReceiveShiftFullState: ReceiveState <= ReceiveShiftNotFullState; + ReceiveShiftNotFullState: if (ReceivePenultimateFrame & (SampleEdge)) ReceiveState <= ReceiveShiftDelayState; + else ReceiveState <= ReceiveShiftNotFullState; + ReceiveShiftDelayState: ReceiveState <= ReceiveShiftFullState; + endcase + end + + assign ReceiveShiftFull = SckMode[0] ? (ReceiveState == ReceiveShiftFullState) : (ReceiveState == ReceiveShiftDelayState); // Calculate tx/rx fifo write and recieve increment signals - always_ff @(posedge PCLK, negedge PRESETn) + always_ff @(posedge PCLK) if (~PRESETn) TransmitFIFOWriteIncrement <= 1'b0; else TransmitFIFOWriteIncrement <= (Memwrite & (Entry == 8'h48) & ~TransmitFIFOWriteFull & TransmitInactive); - always_ff @(posedge PCLK, negedge PRESETn) + always_ff @(posedge PCLK) if (~PRESETn) ReceiveFIFOReadIncrement <= 1'b0; else ReceiveFIFOReadIncrement <= ((Entry == 8'h4C) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement); // Tx/Rx FIFOs - SynchFIFO #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn, TransmitFIFOWriteIncrement, TransmitShiftEmpty, TransmitData[7:0], TransmitWriteWatermarkLevel, TransmitWatermark[2:0], + spi_fifo #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn, TransmitFIFOWriteIncrement, TransmitShiftEmpty, TransmitData[7:0], TransmitWriteWatermarkLevel, TransmitWatermark[2:0], TransmitFIFOReadData[7:0], TransmitFIFOWriteFull, TransmitFIFOReadEmpty, TransmitWriteMark, TransmitReadMark); - SynchFIFO #(3,8) rxFIFO(PCLK, SCLKenable, 1'b1, PRESETn, ReceiveShiftFullDelay, ReceiveFIFOReadIncrement, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel, + spi_fifo #(3,8) rxFIFO(PCLK, SCLKenable, 1'b1, PRESETn, ReceiveShiftFullDelay, ReceiveFIFOReadIncrement, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel, ReceiveData[7:0], ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty, RecieveWriteMark, RecieveReadMark); - always_ff @(posedge PCLK, negedge PRESETn) + always_ff @(posedge PCLK) if (~PRESETn) TransmitFIFOReadEmptyDelay <= 1'b1; else if (SCLKenable) TransmitFIFOReadEmptyDelay <= TransmitFIFOReadEmpty; - always_ff @(posedge PCLK, negedge PRESETn) + always_ff @(posedge PCLK) if (~PRESETn) ReceiveShiftFullDelay <= 1'b0; else if (SCLKenable) ReceiveShiftFullDelay <= ReceiveShiftFull; - always_ff @(posedge PCLK, negedge PRESETn) + always_ff @(posedge PCLK) if (~PRESETn) ReceiveShiftFullDelayPCLK <= 1'b0; else if (SCLKenableEarly) ReceiveShiftFullDelayPCLK <= ReceiveShiftFull; @@ -265,7 +295,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( typedef enum logic [2:0] {CS_INACTIVE, DELAY_0, ACTIVE_0, ACTIVE_1, DELAY_1,INTER_CS, INTER_XFR} statetype; statetype state; - always_ff @(posedge PCLK, negedge PRESETn) + always_ff @(posedge PCLK) if (~PRESETn) begin state <= CS_INACTIVE; FrameCount <= 4'b0; @@ -347,7 +377,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // Transmit shift register assign TransmitDataEndian = Format[0] ? {TransmitFIFOReadData[0], TransmitFIFOReadData[1], TransmitFIFOReadData[2], TransmitFIFOReadData[3], TransmitFIFOReadData[4], TransmitFIFOReadData[5], TransmitFIFOReadData[6], TransmitFIFOReadData[7]} : TransmitFIFOReadData[7:0]; - always_ff @(posedge PCLK, negedge PRESETn) + always_ff @(posedge PCLK) if(~PRESETn) TransmitShiftReg <= 8'b0; else if (TransmitShiftRegLoad) TransmitShiftReg <= TransmitDataEndian; else if (ShiftEdge & Active) TransmitShiftReg <= {TransmitShiftReg[6:0], 1'b0}; @@ -359,7 +389,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( assign ShiftIn = P.SPI_LOOPBACK_TEST ? SPIOut : SPIIn; // Receive shift register - always_ff @(posedge PCLK, negedge PRESETn) + always_ff @(posedge PCLK) if(~PRESETn) ReceiveShiftReg <= 8'b0; else if (SampleEdge & SCLKenable) begin if (~Active) ReceiveShiftReg <= 8'b0; @@ -385,94 +415,3 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( assign SPICS = ChipSelectMode[0] ? ChipSelectDef : ChipSelectAuto; endmodule - -module SynchFIFO #(parameter M=3, N=8)( // 2^M entries of N bits each - input logic PCLK, wen, ren, PRESETn, - input logic winc, rinc, - input logic [N-1:0] wdata, - input logic [M-1:0] wwatermarklevel, rwatermarklevel, - output logic [N-1:0] rdata, - output logic wfull, rempty, - output logic wwatermark, rwatermark); - - /* Pointer FIFO using design elements from "Simulation and Synthesis Techniques - for Asynchronous FIFO Design" by Clifford E. Cummings. Namely, M bit read and write pointers - are an extra bit larger than address size to determine full/empty conditions. - Watermark comparisons use 2's complement subtraction between the M-1 bit pointers, - which are also used to address memory - */ - - logic [N-1:0] mem[2**M]; - logic [M:0] rptr, wptr; - logic [M:0] rptrnext, wptrnext; - logic [M-1:0] raddr; - logic [M-1:0] waddr; - - assign rdata = mem[raddr]; - always_ff @(posedge PCLK) - if (winc & ~wfull) mem[waddr] <= wdata; - - // write and read are enabled - always_ff @(posedge PCLK, negedge PRESETn) - if (~PRESETn) begin - rptr <= '0; - wptr <= '0; - wfull <= 1'b0; - rempty <= 1'b1; - end else begin - if (wen) begin - wfull <= ({~wptrnext[M], wptrnext[M-1:0]} == rptr); - wptr <= wptrnext; - end - if (ren) begin - rptr <= rptrnext; - rempty <= (wptr == rptrnext); - end - end - - assign raddr = rptr[M-1:0]; - assign rptrnext = rptr + {{(M){1'b0}}, (rinc & ~rempty)}; - assign rwatermark = ((waddr - raddr) < rwatermarklevel) & ~wfull; - assign waddr = wptr[M-1:0]; - assign wwatermark = ((waddr - raddr) > wwatermarklevel) | wfull; - assign wptrnext = wptr + {{(M){1'b0}}, (winc & ~wfull)}; -endmodule - -module TransmitShiftFSM( - input logic PCLK, PRESETn, - input logic TransmitFIFOReadEmpty, ReceivePenultimateFrame, Active0, - output logic TransmitShiftEmpty); - - always_ff @(posedge PCLK, negedge PRESETn) - if (~PRESETn) TransmitShiftEmpty <= 1'b1; - else if (TransmitShiftEmpty) begin - if (TransmitFIFOReadEmpty | (~TransmitFIFOReadEmpty & (ReceivePenultimateFrame & Active0))) TransmitShiftEmpty <= 1'b1; - else if (~TransmitFIFOReadEmpty) TransmitShiftEmpty <= 1'b0; - end else begin - if (ReceivePenultimateFrame & Active0) TransmitShiftEmpty <= 1'b1; - else TransmitShiftEmpty <= 1'b0; - end - -endmodule - -module ReceiveShiftFSM( - input logic PCLK, PRESETn, SCLKenable, - input logic ReceivePenultimateFrame, SampleEdge, SckMode, - output logic ReceiveShiftFull -); - typedef enum logic [1:0] {ReceiveShiftFullState, ReceiveShiftNotFullState, ReceiveShiftDelayState} statetype; - statetype ReceiveState, ReceiveNextState; - always_ff @(posedge PCLK, negedge PRESETn) - if (~PRESETn) ReceiveState <= ReceiveShiftNotFullState; - else if (SCLKenable) begin - case (ReceiveState) - ReceiveShiftFullState: ReceiveState <= ReceiveShiftNotFullState; - ReceiveShiftNotFullState: if (ReceivePenultimateFrame & (SampleEdge)) ReceiveState <= ReceiveShiftDelayState; - else ReceiveState <= ReceiveShiftNotFullState; - ReceiveShiftDelayState: ReceiveState <= ReceiveShiftFullState; - endcase - end - - assign ReceiveShiftFull = SckMode ? (ReceiveState == ReceiveShiftFullState) : (ReceiveState == ReceiveShiftDelayState); -endmodule - diff --git a/src/uncore/spi_fifo.sv b/src/uncore/spi_fifo.sv new file mode 100644 index 000000000..40c3ca4ff --- /dev/null +++ b/src/uncore/spi_fifo.sv @@ -0,0 +1,51 @@ +module spi_fifo #(parameter M=3, N=8)( // 2^M entries of N bits each + input logic PCLK, wen, ren, PRESETn, + input logic winc, rinc, + input logic [N-1:0] wdata, + input logic [M-1:0] wwatermarklevel, rwatermarklevel, + output logic [N-1:0] rdata, + output logic wfull, rempty, + output logic wwatermark, rwatermark); + + /* Pointer FIFO using design elements from "Simulation and Synthesis Techniques + for Asynchronous FIFO Design" by Clifford E. Cummings. Namely, M bit read and write pointers + are an extra bit larger than address size to determine full/empty conditions. + Watermark comparisons use 2's complement subtraction between the M-1 bit pointers, + which are also used to address memory + */ + + logic [N-1:0] mem[2**M]; + logic [M:0] rptr, wptr; + logic [M:0] rptrnext, wptrnext; + logic [M-1:0] raddr; + logic [M-1:0] waddr; + + assign rdata = mem[raddr]; + always_ff @(posedge PCLK) + if (winc & ~wfull) mem[waddr] <= wdata; + + // write and read are enabled + always_ff @(posedge PCLK) + if (~PRESETn) begin + rptr <= '0; + wptr <= '0; + wfull <= 1'b0; + rempty <= 1'b1; + end else begin + if (wen) begin + wfull <= ({~wptrnext[M], wptrnext[M-1:0]} == rptr); + wptr <= wptrnext; + end + if (ren) begin + rptr <= rptrnext; + rempty <= (wptr == rptrnext); + end + end + + assign raddr = rptr[M-1:0]; + assign rptrnext = rptr + {{(M){1'b0}}, (rinc & ~rempty)}; + assign rwatermark = ((waddr - raddr) < rwatermarklevel) & ~wfull; + assign waddr = wptr[M-1:0]; + assign wwatermark = ((waddr - raddr) > wwatermarklevel) | wfull; + assign wptrnext = wptr + {{(M){1'b0}}, (winc & ~wfull)}; +endmodule diff --git a/src/uncore/uartPC16550D.sv b/src/uncore/uartPC16550D.sv index 13f02fedb..c4c1dc27f 100644 --- a/src/uncore/uartPC16550D.sv +++ b/src/uncore/uartPC16550D.sv @@ -145,7 +145,7 @@ module uartPC16550D #(parameter UART_PRESCALE) ( // Register interface (Table 1, note some are read only and some write only) /////////////////////////////////////////// - always_ff @(posedge PCLK, negedge PRESETn) + always_ff @(posedge PCLK) if (~PRESETn) begin // Table 3 Reset Configuration IER <= 4'b0; FCR <= 8'b0; @@ -222,7 +222,7 @@ module uartPC16550D #(parameter UART_PRESCALE) ( // the data, so the baud rate is 320x10^6 / (65 x 2^5 x 16) = 9615 Hz, which is // close enough to 9600 baud to stay synchronized over the duration of one character. /////////////////////////////////////////// - always_ff @(posedge PCLK, negedge PRESETn) + always_ff @(posedge PCLK) if (~PRESETn) begin baudcount <= 1; baudpulse <= 1'b0; @@ -248,7 +248,7 @@ module uartPC16550D #(parameter UART_PRESCALE) ( // receive timing and control /////////////////////////////////////////// - always_ff @(posedge PCLK, negedge PRESETn) + always_ff @(posedge PCLK) if (~PRESETn) begin rxoversampledcnt <= '0; rxstate <= UART_IDLE; @@ -281,7 +281,7 @@ module uartPC16550D #(parameter UART_PRESCALE) ( // receive shift register, buffer register, FIFO /////////////////////////////////////////// - always_ff @(posedge PCLK, negedge PRESETn) + always_ff @(posedge PCLK) if (~PRESETn) rxshiftreg <= 10'b0000000001; // initialize so that there is a valid stop bit else if (rxcentered) rxshiftreg <= {rxshiftreg[8:0], SINsync}; // capture bit assign rxparitybit = rxshiftreg[1]; // parity, if it exists, in bit 1 when all done @@ -363,7 +363,7 @@ module uartPC16550D #(parameter UART_PRESCALE) ( assign rxfifohaserr = |(RXerrbit & rxfullbit); // receive buffer register and ready bit - always_ff @(posedge PCLK, negedge PRESETn) // track rxrdy for DMA mode (FCR3 = FCR0 = 1) + always_ff @(posedge PCLK) // track rxrdy for DMA mode (FCR3 = FCR0 = 1) if (~PRESETn) rxfifodmaready <= 1'b0; else if (rxfifotriggered | rxfifotimeout) rxfifodmaready <= 1'b1; else if (rxfifoempty) rxfifodmaready <= 1'b0; @@ -383,7 +383,7 @@ module uartPC16550D #(parameter UART_PRESCALE) ( // transmit timing and control /////////////////////////////////////////// - always_ff @(posedge PCLK, negedge PRESETn) + always_ff @(posedge PCLK) if (~PRESETn) begin txoversampledcnt <= '0; txstate <= UART_IDLE; @@ -431,7 +431,7 @@ module uartPC16550D #(parameter UART_PRESCALE) ( end // registers & FIFO - always_ff @(posedge PCLK, negedge PRESETn) + always_ff @(posedge PCLK) if (~PRESETn) begin txfifohead <= '0; txfifotail <= '0; txhrfull <= 1'b0; txsrfull <= 1'b0; TXHR <= '0; txsr <= 12'hfff; end else if (~MEMWb & (A == 3'b010) & Din[2]) begin @@ -467,7 +467,7 @@ module uartPC16550D #(parameter UART_PRESCALE) ( end end - always_ff @(posedge PCLK, negedge PRESETn) begin + always_ff @(posedge PCLK) begin // special condition to check if the fifo is empty or full. Because the head // pointer indicates where the next write goes and not the location of the // current head, the head and tail pointer being equal imply two different @@ -492,7 +492,7 @@ module uartPC16550D #(parameter UART_PRESCALE) ( assign txfifofull = (txfifohead == txfifotail) & HeadPointerLastMove; // transmit buffer ready bit - always_ff @(posedge PCLK, negedge PRESETn) // track txrdy for DMA mode (FCR3 = FCR0 = 1) + always_ff @(posedge PCLK) // track txrdy for DMA mode (FCR3 = FCR0 = 1) if (~PRESETn) txfifodmaready <= 1'b0; else if (txfifoempty) txfifodmaready <= 1'b1; else if (txfifofull) txfifodmaready <= 1'b0;