Removed asynchronous reset causing lint issue in peripherals

This commit is contained in:
David Harris 2024-06-18 05:49:12 -07:00
parent 2fc9edff45
commit 7509e856df
6 changed files with 110 additions and 120 deletions

View File

@ -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
*/
*/

View File

@ -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;

View File

@ -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

51
src/uncore/spi_fifo.sv Normal file
View File

@ -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

View File

@ -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;