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

View File

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