mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
More SPI optimizations.
This commit is contained in:
parent
745e53adf7
commit
120b21d7d5
@ -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
|
||||||
@ -230,23 +230,17 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
SPICLK);
|
SPICLK);
|
||||||
|
|
||||||
// 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
|
||||||
always_ff @(posedge PCLK) begin
|
always_ff @(posedge PCLK) begin
|
||||||
@ -258,15 +252,11 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
|||||||
TransmitRegLoaded <= 1'b0;
|
TransmitRegLoaded <= 1'b0;
|
||||||
end
|
end
|
||||||
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];
|
||||||
|
|
||||||
|
@ -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
|
||||||
@ -242,17 +241,6 @@ module spi_controller (
|
|||||||
// Logic for continuing to transmit through Delay states after end of frame
|
// Logic for continuing to transmit through Delay states after end of frame
|
||||||
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
|
||||||
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user