mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Removed asynchronous reset causing lint issue in peripherals
This commit is contained in:
parent
2fc9edff45
commit
7509e856df
@ -76,7 +76,7 @@ module clint_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
default: PRDATA <= '0;
|
default: PRDATA <= '0;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
always_ff @(posedge PCLK or negedge PRESETn)
|
always_ff @(posedge PCLK)
|
||||||
if (~PRESETn) begin
|
if (~PRESETn) begin
|
||||||
MSIP <= 1'b0;
|
MSIP <= 1'b0;
|
||||||
MTIMECMP <= 64'hFFFFFFFFFFFFFFFF; // Spec says MTIMECMP is not reset, but we reset to maximum value to prevent spurious timer interrupts
|
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
|
// eventually replace MTIME logic below with timereg
|
||||||
// timereg tr(PCLK, PRESETn, TIMECLK, memwrite & (entry==16'hBFF8), 1'b0, PWDATA, MTIME, done);
|
// 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
|
if (~PRESETn) begin
|
||||||
MTIME <= '0;
|
MTIME <= '0;
|
||||||
end else if (memwrite & entry == 16'hBFF8) begin
|
end else if (memwrite & entry == 16'hBFF8) begin
|
||||||
@ -251,4 +251,4 @@ module graytobinary #(parameter N) (
|
|||||||
assign b[i] = g[i] ^ b[i+1];
|
assign b[i] = g[i] ^ b[i+1];
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
*/
|
*/
|
||||||
|
@ -82,8 +82,8 @@ module gpio_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
else assign PRDATA = Dout;
|
else assign PRDATA = Dout;
|
||||||
|
|
||||||
// register access
|
// register access
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK)
|
||||||
if (~PRESETn) begin // asynch reset
|
if (~PRESETn) begin
|
||||||
input_en <= '0;
|
input_en <= '0;
|
||||||
output_en <= '0;
|
output_en <= '0;
|
||||||
output_val <= '0;
|
output_val <= '0;
|
||||||
|
@ -61,6 +61,10 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
localparam SPI_IE = 8'h70;
|
localparam SPI_IE = 8'h70;
|
||||||
localparam SPI_IP = 8'h74;
|
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
|
// SPI control registers. Refer to SiFive FU540-C000 manual
|
||||||
logic [11:0] SckDiv;
|
logic [11:0] SckDiv;
|
||||||
logic [1:0] SckMode;
|
logic [1:0] SckMode;
|
||||||
@ -88,8 +92,11 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
logic ReceiveFIFOReadIncrement;
|
logic ReceiveFIFOReadIncrement;
|
||||||
logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty;
|
logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty;
|
||||||
logic [7:0] TransmitFIFOReadData;
|
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)
|
logic [7:0] ReceiveShiftRegEndian; // Reverses ReceiveShiftReg if Format[2] set (little endian transmission)
|
||||||
|
rsrstatetype ReceiveState, ReceiveNextState;
|
||||||
|
|
||||||
// Transmission signals
|
// Transmission signals
|
||||||
logic sck;
|
logic sck;
|
||||||
@ -150,7 +157,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
else assign PRDATA = Dout;
|
else assign PRDATA = Dout;
|
||||||
|
|
||||||
// Register access
|
// Register access
|
||||||
always_ff@(posedge PCLK, negedge PRESETn)
|
always_ff@(posedge PCLK)
|
||||||
if (~PRESETn) begin
|
if (~PRESETn) begin
|
||||||
SckDiv <= 12'd3;
|
SckDiv <= 12'd3;
|
||||||
SckMode <= 2'b0;
|
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
|
// 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 SCLKenable = (DivCounter == SckDiv);
|
||||||
assign SCLKenableEarly = ((DivCounter + 12'b1) == SckDiv);
|
assign SCLKenableEarly = ((DivCounter + 12'b1) == SckDiv);
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK)
|
||||||
if (~PRESETn) DivCounter <= '0;
|
if (~PRESETn) DivCounter <= '0;
|
||||||
else if (SCLKenable) DivCounter <= 12'b0;
|
else if (SCLKenable) DivCounter <= 12'b0;
|
||||||
else DivCounter <= DivCounter + 12'b1;
|
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;
|
assign ImplicitDelay2 = SckMode[0] ? 9'b1 : 9'b0;
|
||||||
|
|
||||||
// Calculate when tx/rx shift registers are full/empty
|
// 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
|
// Calculate tx/rx fifo write and recieve increment signals
|
||||||
|
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK)
|
||||||
if (~PRESETn) TransmitFIFOWriteIncrement <= 1'b0;
|
if (~PRESETn) TransmitFIFOWriteIncrement <= 1'b0;
|
||||||
else TransmitFIFOWriteIncrement <= (Memwrite & (Entry == 8'h48) & ~TransmitFIFOWriteFull & TransmitInactive);
|
else TransmitFIFOWriteIncrement <= (Memwrite & (Entry == 8'h48) & ~TransmitFIFOWriteFull & TransmitInactive);
|
||||||
|
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK)
|
||||||
if (~PRESETn) ReceiveFIFOReadIncrement <= 1'b0;
|
if (~PRESETn) ReceiveFIFOReadIncrement <= 1'b0;
|
||||||
else ReceiveFIFOReadIncrement <= ((Entry == 8'h4C) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement);
|
else ReceiveFIFOReadIncrement <= ((Entry == 8'h4C) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement);
|
||||||
|
|
||||||
// Tx/Rx FIFOs
|
// 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);
|
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);
|
ReceiveData[7:0], ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty, RecieveWriteMark, RecieveReadMark);
|
||||||
|
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK)
|
||||||
if (~PRESETn) TransmitFIFOReadEmptyDelay <= 1'b1;
|
if (~PRESETn) TransmitFIFOReadEmptyDelay <= 1'b1;
|
||||||
else if (SCLKenable) TransmitFIFOReadEmptyDelay <= TransmitFIFOReadEmpty;
|
else if (SCLKenable) TransmitFIFOReadEmptyDelay <= TransmitFIFOReadEmpty;
|
||||||
|
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK)
|
||||||
if (~PRESETn) ReceiveShiftFullDelay <= 1'b0;
|
if (~PRESETn) ReceiveShiftFullDelay <= 1'b0;
|
||||||
else if (SCLKenable) ReceiveShiftFullDelay <= ReceiveShiftFull;
|
else if (SCLKenable) ReceiveShiftFullDelay <= ReceiveShiftFull;
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK)
|
||||||
if (~PRESETn) ReceiveShiftFullDelayPCLK <= 1'b0;
|
if (~PRESETn) ReceiveShiftFullDelayPCLK <= 1'b0;
|
||||||
else if (SCLKenableEarly) ReceiveShiftFullDelayPCLK <= ReceiveShiftFull;
|
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;
|
typedef enum logic [2:0] {CS_INACTIVE, DELAY_0, ACTIVE_0, ACTIVE_1, DELAY_1,INTER_CS, INTER_XFR} statetype;
|
||||||
statetype state;
|
statetype state;
|
||||||
|
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK)
|
||||||
if (~PRESETn) begin
|
if (~PRESETn) begin
|
||||||
state <= CS_INACTIVE;
|
state <= CS_INACTIVE;
|
||||||
FrameCount <= 4'b0;
|
FrameCount <= 4'b0;
|
||||||
@ -347,7 +377,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
// Transmit shift register
|
// 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];
|
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;
|
if(~PRESETn) TransmitShiftReg <= 8'b0;
|
||||||
else if (TransmitShiftRegLoad) TransmitShiftReg <= TransmitDataEndian;
|
else if (TransmitShiftRegLoad) TransmitShiftReg <= TransmitDataEndian;
|
||||||
else if (ShiftEdge & Active) TransmitShiftReg <= {TransmitShiftReg[6:0], 1'b0};
|
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;
|
assign ShiftIn = P.SPI_LOOPBACK_TEST ? SPIOut : SPIIn;
|
||||||
|
|
||||||
// Receive shift register
|
// Receive shift register
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK)
|
||||||
if(~PRESETn) ReceiveShiftReg <= 8'b0;
|
if(~PRESETn) ReceiveShiftReg <= 8'b0;
|
||||||
else if (SampleEdge & SCLKenable) begin
|
else if (SampleEdge & SCLKenable) begin
|
||||||
if (~Active) ReceiveShiftReg <= 8'b0;
|
if (~Active) ReceiveShiftReg <= 8'b0;
|
||||||
@ -385,94 +415,3 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
assign SPICS = ChipSelectMode[0] ? ChipSelectDef : ChipSelectAuto;
|
assign SPICS = ChipSelectMode[0] ? ChipSelectDef : ChipSelectAuto;
|
||||||
endmodule
|
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
51
src/uncore/spi_fifo.sv
Normal 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
|
@ -145,7 +145,7 @@ module uartPC16550D #(parameter UART_PRESCALE) (
|
|||||||
// Register interface (Table 1, note some are read only and some write only)
|
// 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
|
if (~PRESETn) begin // Table 3 Reset Configuration
|
||||||
IER <= 4'b0;
|
IER <= 4'b0;
|
||||||
FCR <= 8'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
|
// 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.
|
// 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
|
if (~PRESETn) begin
|
||||||
baudcount <= 1;
|
baudcount <= 1;
|
||||||
baudpulse <= 1'b0;
|
baudpulse <= 1'b0;
|
||||||
@ -248,7 +248,7 @@ module uartPC16550D #(parameter UART_PRESCALE) (
|
|||||||
// receive timing and control
|
// receive timing and control
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK)
|
||||||
if (~PRESETn) begin
|
if (~PRESETn) begin
|
||||||
rxoversampledcnt <= '0;
|
rxoversampledcnt <= '0;
|
||||||
rxstate <= UART_IDLE;
|
rxstate <= UART_IDLE;
|
||||||
@ -281,7 +281,7 @@ module uartPC16550D #(parameter UART_PRESCALE) (
|
|||||||
// receive shift register, buffer register, FIFO
|
// 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
|
if (~PRESETn) rxshiftreg <= 10'b0000000001; // initialize so that there is a valid stop bit
|
||||||
else if (rxcentered) rxshiftreg <= {rxshiftreg[8:0], SINsync}; // capture 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
|
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);
|
assign rxfifohaserr = |(RXerrbit & rxfullbit);
|
||||||
|
|
||||||
// receive buffer register and ready bit
|
// 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;
|
if (~PRESETn) rxfifodmaready <= 1'b0;
|
||||||
else if (rxfifotriggered | rxfifotimeout) rxfifodmaready <= 1'b1;
|
else if (rxfifotriggered | rxfifotimeout) rxfifodmaready <= 1'b1;
|
||||||
else if (rxfifoempty) rxfifodmaready <= 1'b0;
|
else if (rxfifoempty) rxfifodmaready <= 1'b0;
|
||||||
@ -383,7 +383,7 @@ module uartPC16550D #(parameter UART_PRESCALE) (
|
|||||||
// transmit timing and control
|
// transmit timing and control
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK)
|
||||||
if (~PRESETn) begin
|
if (~PRESETn) begin
|
||||||
txoversampledcnt <= '0;
|
txoversampledcnt <= '0;
|
||||||
txstate <= UART_IDLE;
|
txstate <= UART_IDLE;
|
||||||
@ -431,7 +431,7 @@ module uartPC16550D #(parameter UART_PRESCALE) (
|
|||||||
end
|
end
|
||||||
|
|
||||||
// registers & FIFO
|
// registers & FIFO
|
||||||
always_ff @(posedge PCLK, negedge PRESETn)
|
always_ff @(posedge PCLK)
|
||||||
if (~PRESETn) begin
|
if (~PRESETn) begin
|
||||||
txfifohead <= '0; txfifotail <= '0; txhrfull <= 1'b0; txsrfull <= 1'b0; TXHR <= '0; txsr <= 12'hfff;
|
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
|
end else if (~MEMWb & (A == 3'b010) & Din[2]) begin
|
||||||
@ -467,7 +467,7 @@ module uartPC16550D #(parameter UART_PRESCALE) (
|
|||||||
end
|
end
|
||||||
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
|
// 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
|
// 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
|
// 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;
|
assign txfifofull = (txfifohead == txfifotail) & HeadPointerLastMove;
|
||||||
|
|
||||||
// transmit buffer ready bit
|
// 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;
|
if (~PRESETn) txfifodmaready <= 1'b0;
|
||||||
else if (txfifoempty) txfifodmaready <= 1'b1;
|
else if (txfifoempty) txfifodmaready <= 1'b1;
|
||||||
else if (txfifofull) txfifodmaready <= 1'b0;
|
else if (txfifofull) txfifodmaready <= 1'b0;
|
||||||
|
Loading…
Reference in New Issue
Block a user