More SPI optimizations.

This commit is contained in:
Jacob Pease 2024-11-04 15:38:12 -06:00
parent 745e53adf7
commit 120b21d7d5
2 changed files with 43 additions and 66 deletions

View File

@ -48,7 +48,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
output logic SPICLK
);
// register map
// register map
localparam SPI_SCKDIV = 8'h00;
localparam SPI_SCKMODE = 8'h04;
localparam SPI_CSID = 8'h10;
@ -89,7 +89,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
logic InactiveState;
logic [3:0] FrameLength;
//
// Starting Transmission and restarting SCLKenable
logic ResetSCLKenable;
logic TransmitStart;
logic TransmitStartD;
@ -98,15 +98,16 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
typedef enum logic [1:0] {READY, START, WAIT} txState;
txState CurrState, NextState;
// FIFO FSM signals
// Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1]
logic TransmitWriteMark, TransmitReadMark, ReceiveWriteMark, ReceiveReadMark;
// FIFO Watermark signals - TransmitReadMark = ip[0], ReceiveWriteMark = ip[1]
logic TransmitWriteMark, TransmitReadMark, ReceiveWriteMark, ReceiveReadMark;
// Transmit FIFO Signals
logic TransmitFIFOFull, TransmitFIFOEmpty;
logic TransmitFIFOWriteInc;
logic TransmitFIFOReadInc; // Increments Tx FIFO read ptr 1 cycle after Tx FIFO is read
logic [7:0] TransmitReadData;
//
// ReceiveFIFO Signals
logic ReceiveFIFOWriteInc;
logic ReceiveFIFOReadInc;
logic ReceiveFIFOFull, ReceiveFIFOEmpty;
@ -137,7 +138,6 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
// APB access
assign Entry = {PADDR[7:2],2'b00}; // 32-bit word-aligned accesses
assign Memwrite = PWRITE & PENABLE & PSEL; // Only write in access phase
// assign PREADY = Entry == SPI_TXDATA | Entry == SPI_RXDATA | Entry == SPI_IP;
assign PREADY = 1'b1;
// Account for subword read/write circuitry
@ -164,7 +164,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
InterruptEnable <= 2'b0;
InterruptPending <= 2'b0;
end else begin // writes
/* verilator lint_off CASEINCOMPLETE */
/* verilator lint_off CASEINCOMPLETE */
if (Memwrite)
case(Entry) // flop to sample inputs
SPI_SCKDIV: SckDiv <= Din[11:0];
@ -217,7 +217,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
spi_controller controller(PCLK, PRESETn,
// Transmit Signals
TransmitStart, TransmitStartD, ResetSCLKenable,
TransmitStart, TransmitRegLoaded, ResetSCLKenable,
// Register Inputs
SckDiv, SckMode, ChipSelectMode, Delay0, Delay1, FrameLength,
// txFIFO stuff
@ -230,23 +230,17 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
SPICLK);
// Transmit FIFO ---------------------------------------------------
// txFIFO write increment logic
always_ff @(posedge PCLK)
if (~PRESETn) begin
TransmitFIFOWriteInc <= 1'b0;
end else begin
TransmitFIFOWriteInc <= (Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOFull);
end
flopr #(1) txwincreg(PCLK, ~PRESETn,
(Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOFull),
TransmitFIFOWriteInc);
// txFIFO read increment logic
always_ff @(posedge PCLK)
if (~PRESETn) begin
TransmitFIFOReadInc <= 1'b0;
end else if (SCLKenable) begin
TransmitFIFOReadInc <= TransmitStartD | (EndOfFrame & ~TransmitFIFOEmpty) ;
end
flopenr #(1) txrincreg(PCLK, ~PRESETn, SCLKenable,
TransmitStartD | (EndOfFrame & ~TransmitFIFOEmpty),
TransmitFIFOReadInc);
// Check whether TransmitReg has been loaded.
// We use this signal to prevent returning to the Ready state for TransmitStart
always_ff @(posedge PCLK) begin
@ -258,15 +252,11 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
TransmitRegLoaded <= 1'b0;
end
end
// Setup TransmitStart state machine
always_ff @(posedge PCLK) begin
if (~PRESETn) begin
CurrState <= READY;
end else begin
CurrState <= NextState;
end
end
always_ff @(posedge PCLK)
if (~PRESETn) CurrState <= READY;
else CurrState <= NextState;
// State machine for starting transmissions
always_comb begin
@ -280,12 +270,14 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
endcase
end
// Delayed TransmitStart signal for incrementing tx read point.
assign TransmitStart = (CurrState == START);
always_ff @(posedge PCLK)
if (~PRESETn) TransmitStartD <= 1'b0;
else if (TransmitStart) TransmitStartD <= 1'b1;
else if (SCLKenable) TransmitStartD <= 1'b0;
// Transmit FIFO
spi_fifo #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn,
TransmitFIFOWriteInc, TransmitFIFOReadInc,
TransmitData[7:0],
@ -296,20 +288,17 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
TransmitWriteMark, TransmitReadMark);
// Receive FIFO ----------------------------------------------------
always_ff @(posedge PCLK)
if (~PRESETn) begin
ReceiveFIFOReadInc <= 1'b0;
end else begin
ReceiveFIFOReadInc <= ((Entry == SPI_RXDATA) & ~ReceiveFIFOEmpty & PSEL & ~ReceiveFIFOReadInc);
end
always_ff @(posedge PCLK)
if (~PRESETn) begin
ReceiveFIFOWriteInc <= 1'b0;
end else if (SCLKenable) begin
ReceiveFIFOWriteInc <= EndOfFrame;
end
// Receive FIFO Read Increment register
flopr #(1) rxfiforincreg(PCLK, ~PRESETn,
((Entry == SPI_RXDATA) & ~ReceiveFIFOEmpty & PSEL & ~ReceiveFIFOReadInc),
ReceiveFIFOReadInc);
// Receive FIFO Write Increment register
flopenr #(1) rxfifowincreg(PCLK, ~PRESETn, SCLKenable,
EndOfFrame, ReceiveFIFOWriteInc);
// Receive FIFO
spi_fifo #(3,8) rxFIFO(PCLK, SCLKenable, 1'b1, PRESETn,
ReceiveFIFOWriteInc, ReceiveFIFOReadInc,
ReceiveShiftRegEndian, ReceiveWatermark[2:0],
@ -319,6 +308,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
ReceiveFIFOEmpty,
ReceiveWriteMark, ReceiveReadMark);
// Shift Registers --------------------------------------------------
// Transmit shift register
assign TransmitLoad = TransmitStart | (EndOfFrame & ~TransmitFIFOEmpty);
assign TransmitDataEndian = Format[0] ? {<<{TransmitReadData[7:0]}} : TransmitReadData[7:0];
@ -340,12 +330,11 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
if(~PRESETn) begin
ReceiveShiftReg <= 8'b0;
end else if (SampleEdge) begin
if (~Transmitting) ReceiveShiftReg <= 8'b0;
else ReceiveShiftReg <= {ReceiveShiftReg[6:0], ShiftIn};
ReceiveShiftReg <= {ReceiveShiftReg[6:0], ShiftIn};
end
// Aligns received data and reverses if little-endian
assign LeftShiftAmount = 4'h8 - Format[4:1];
assign LeftShiftAmount = 4'h8 - FrameLength;
assign ASR = ReceiveShiftReg << LeftShiftAmount[2:0];
assign ReceiveShiftRegEndian = Format[0] ? {<<{ASR[7:0]}} : ASR[7:0];

View File

@ -33,7 +33,7 @@ module spi_controller (
// Start Transmission
input logic TransmitStart,
input logic TransmitStartD,
input logic TransmitRegLoaded,
input logic ResetSCLKenable,
// Registers
@ -84,7 +84,7 @@ module spi_controller (
// Transmit Stuff
logic ContinueTransmit;
logic EndTransmission;
logic ContinueTransmitD; // TODO: Could be replaced by TransmitRegLoaded?
// logic TransmitRegLoaded; // TODO: Could be replaced by TransmitRegLoaded?
logic NextEndDelay;
logic CurrentEndDelay;
@ -151,8 +151,7 @@ module spi_controller (
BitNum <= 4'h0;
DelayCounter <= 0;
end else begin
// TODO: Consolidate into one delay counter since none of the
// delays happen at the same time?
// SCK logic for delay times
if (TransmitStart) begin
SCK <= 0;
end else if (SCLKenable) begin
@ -242,17 +241,6 @@ module spi_controller (
// Logic for continuing to transmit through Delay states after end of frame
assign NextEndDelay = NextState == SCKCS | NextState == INTERCS | NextState == INTERXFR;
assign CurrentEndDelay = CurrState == SCKCS | CurrState == INTERCS | CurrState == INTERXFR;
//
always_ff @(posedge PCLK) begin
if (~PRESETn) begin
ContinueTransmitD <= 1'b0;
end else if (NextEndDelay & ~CurrentEndDelay) begin
ContinueTransmitD <= ContinueTransmit;
end else if (EndOfSCKCS & SCLKenable) begin
ContinueTransmitD <= 1'b0;
end
end
always_ff @(posedge PCLK) begin
if (~PRESETn) begin
@ -264,7 +252,7 @@ module spi_controller (
always_comb begin
case (CurrState)
INACTIVE: if (TransmitStartD) begin
INACTIVE: if (TransmitRegLoaded) begin
if (~HasCSSCK) NextState = TRANSMIT;
else NextState = CSSCK;
end else begin
@ -294,7 +282,7 @@ module spi_controller (
end
SCKCS: begin // SCKCS case --------------------------------------
if (EndOfSCKCS) begin
if (~ContinueTransmitD) begin
if (~TransmitRegLoaded) begin
// if (CSMode == AUTOMODE) NextState = INACTIVE;
if (CSMode == HOLDMODE) NextState = HOLD;
else NextState = INACTIVE;
@ -309,7 +297,7 @@ module spi_controller (
HOLD: begin // HOLD mode case -----------------------------------
if (CSMode == AUTOMODE) begin
NextState = INACTIVE;
end else if (TransmitStartD) begin // If FIFO is written to, start again.
end else if (TransmitRegLoaded) begin // If FIFO is written to, start again.
NextState = TRANSMIT;
end else NextState = HOLD;
end