mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Update SPI peripheral to accept writes to FIFO always. Worked on this together with Naiche and Rose.
This commit is contained in:
parent
9fae5dfc0a
commit
43b17b5058
@ -91,28 +91,28 @@ int disk_read(BYTE * buf, LBA_t sector, UINT count) {
|
||||
while((r = spi_dummy()) != SD_DATA_TOKEN);
|
||||
|
||||
crc = 0;
|
||||
n = 512;
|
||||
do {
|
||||
uint8_t x = spi_dummy();
|
||||
*p++ = x;
|
||||
crc = crc16(crc, x);
|
||||
} while (--n > 0);
|
||||
|
||||
/* n = 512/8; */
|
||||
/* n = 512; */
|
||||
/* do { */
|
||||
/* // Send 8 dummy bytes (fifo should be empty) */
|
||||
/* for (j = 0; j < 8; j++) { */
|
||||
/* spi_sendbyte(0xff); */
|
||||
/* } */
|
||||
/* uint8_t x = spi_dummy(); */
|
||||
/* *p++ = x; */
|
||||
/* crc = crc16(crc, x); */
|
||||
/* } while (--n > 0); */
|
||||
|
||||
/* // Reset counter. Process bytes AS THEY COME IN. */
|
||||
/* for (j = 0; j < 8; j++) { */
|
||||
/* while (!(read_reg(SPI_IP) & 2)) {} */
|
||||
/* uint8_t x = spi_readbyte(); */
|
||||
/* *p++ = x; */
|
||||
/* crc = crc16(crc, x); */
|
||||
/* } */
|
||||
/* } while(--n > 0); */
|
||||
n = 512/8;
|
||||
do {
|
||||
// Send 8 dummy bytes (fifo should be empty)
|
||||
for (j = 0; j < 8; j++) {
|
||||
spi_sendbyte(0xff);
|
||||
}
|
||||
|
||||
// Reset counter. Process bytes AS THEY COME IN.
|
||||
for (j = 0; j < 8; j++) {
|
||||
while (!(read_reg(SPI_IP) & 2)) {}
|
||||
uint8_t x = spi_readbyte();
|
||||
*p++ = x;
|
||||
crc = crc16(crc, x);
|
||||
}
|
||||
} while(--n > 0);
|
||||
|
||||
// Read CRC16 and check
|
||||
crc_exp = ((uint16_t)spi_dummy() << 8);
|
||||
|
@ -148,8 +148,7 @@ 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
|
||||
// JACOB: This shouldn't behave this way
|
||||
assign PREADY = TransmitInactive; // Tie PREADY to transmission for hardware interlock
|
||||
assign PREADY = Entry == SPI_TXDATA | Entry == SPI_RXDATA | TransmitInactive; // Tie PREADY to transmission for hardware interlock
|
||||
|
||||
// Account for subword read/write circuitry
|
||||
// -- Note SPI registers are 32 bits no matter what; access them with LW SW.
|
||||
@ -187,12 +186,16 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
||||
SPI_CSMODE: ChipSelectMode <= Din[1:0];
|
||||
SPI_DELAY0: Delay0 <= {Din[23:16], Din[7:0]};
|
||||
SPI_DELAY1: Delay1 <= {Din[23:16], Din[7:0]};
|
||||
SPI_FMT: Format <= {Din[19:16], Din[2]};
|
||||
SPI_TXDATA: if (~TransmitFIFOWriteFull) TransmitData[7:0] <= Din[7:0];
|
||||
SPI_FMT: Format <= {Din[19:16], Din[2]};
|
||||
SPI_TXMARK: TransmitWatermark <= Din[2:0];
|
||||
SPI_RXMARK: ReceiveWatermark <= Din[2:0];
|
||||
SPI_IE: InterruptEnable <= Din[1:0];
|
||||
endcase
|
||||
|
||||
if (Memwrite)
|
||||
case(Entry)
|
||||
SPI_TXDATA: if (~TransmitFIFOWriteFull) TransmitData[7:0] <= Din[7:0];
|
||||
endcase
|
||||
/* verilator lint_off CASEINCOMPLETE */
|
||||
|
||||
// According to FU540 spec: Once interrupt is pending, it will remain set until number
|
||||
@ -268,11 +271,12 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
always_ff @(posedge PCLK)
|
||||
if (~PRESETn) TransmitFIFOWriteIncrement <= 1'b0;
|
||||
else TransmitFIFOWriteIncrement <= (Memwrite & (Entry == 8'h48) & ~TransmitFIFOWriteFull & TransmitInactive);
|
||||
// else TransmitFIFOWriteIncrement <= (Memwrite & (Entry == 8'h48) & ~TransmitFIFOWriteFull & TransmitInactive);
|
||||
else TransmitFIFOWriteIncrement <= (Memwrite & (Entry == SPI_TXDATA) & ~TransmitFIFOWriteFull);
|
||||
|
||||
always_ff @(posedge PCLK)
|
||||
if (~PRESETn) ReceiveFIFOReadIncrement <= 1'b0;
|
||||
else ReceiveFIFOReadIncrement <= ((Entry == 8'h4C) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement);
|
||||
else ReceiveFIFOReadIncrement <= ((Entry == SPI_RXDATA) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement);
|
||||
|
||||
// Tx/Rx FIFOs
|
||||
spi_fifo #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn, TransmitFIFOWriteIncrement, TransmitShiftEmpty, TransmitData[7:0], TransmitWriteWatermarkLevel, TransmitWatermark[2:0],
|
||||
@ -300,7 +304,8 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
||||
always_ff @(posedge PCLK)
|
||||
if (~PRESETn) begin
|
||||
state <= CS_INACTIVE;
|
||||
FrameCount <= 4'b0;
|
||||
FrameCount <= 4'b0;
|
||||
SPICLK <= SckMode[1];
|
||||
end else if (SCLKenable) begin
|
||||
/* verilator lint_off CASEINCOMPLETE */
|
||||
case (state)
|
||||
@ -311,21 +316,32 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
||||
InterCSCount <= 9'b10;
|
||||
InterXFRCount <= 9'b1;
|
||||
if ((~TransmitFIFOReadEmpty | ~TransmitShiftEmpty) & ((|(Delay0[7:0])) | ~SckMode[0])) state <= DELAY_0;
|
||||
else if ((~TransmitFIFOReadEmpty | ~TransmitShiftEmpty)) state <= ACTIVE_0;
|
||||
else if ((~TransmitFIFOReadEmpty | ~TransmitShiftEmpty)) begin
|
||||
state <= ACTIVE_0;
|
||||
SPICLK <= ~SckMode[1];
|
||||
end
|
||||
end
|
||||
DELAY_0: begin
|
||||
CS_SCKCount <= CS_SCKCount + 9'b1;
|
||||
if (CS_SCKCount >= (({Delay0[7:0], 1'b0}) + ImplicitDelay1)) state <= ACTIVE_0;
|
||||
if (CS_SCKCount >= (({Delay0[7:0], 1'b0}) + ImplicitDelay1)) begin
|
||||
state <= ACTIVE_0;
|
||||
SPICLK <= ~SckMode[1];
|
||||
end
|
||||
end
|
||||
ACTIVE_0: begin
|
||||
FrameCount <= FrameCount + 4'b1;
|
||||
SPICLK <= SckMode[1];
|
||||
state <= ACTIVE_1;
|
||||
end
|
||||
ACTIVE_1: begin
|
||||
InterXFRCount <= 9'b1;
|
||||
if (FrameCount < Format[4:1]) state <= ACTIVE_0;
|
||||
if (FrameCount < Format[4:1]) begin
|
||||
state <= ACTIVE_0;
|
||||
SPICLK <= ~SckMode[1];
|
||||
end
|
||||
else if ((ChipSelectMode[1:0] == 2'b10) & ~|(Delay1[15:8]) & (~TransmitFIFOReadEmpty)) begin
|
||||
state <= ACTIVE_0;
|
||||
SPICLK <= ~SckMode[1];
|
||||
CS_SCKCount <= 9'b1;
|
||||
SCK_CSCount <= 9'b10;
|
||||
FrameCount <= 4'b0;
|
||||
@ -349,8 +365,10 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
||||
FrameCount <= 4'b0;
|
||||
InterCSCount <= 9'b10;
|
||||
InterXFRCount <= InterXFRCount + 9'b1;
|
||||
if ((InterXFRCount >= ({Delay1[15:8], 1'b0})) & ~TransmitFIFOReadEmptyDelay) state <= ACTIVE_0;
|
||||
else if (~|ChipSelectMode[1:0]) state <= CS_INACTIVE;
|
||||
if ((InterXFRCount >= ({Delay1[15:8], 1'b0})) & ~TransmitFIFOReadEmptyDelay) begin
|
||||
state <= ACTIVE_0;
|
||||
SPICLK <= ~SckMode[1];
|
||||
end else if (~|ChipSelectMode[1:0]) state <= CS_INACTIVE;
|
||||
end
|
||||
endcase
|
||||
/* verilator lint_off CASEINCOMPLETE */
|
||||
@ -360,11 +378,11 @@ module spi_apb import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
assign DelayMode = SckMode[0] ? (state == DELAY_1) : (state == ACTIVE_1 & ReceiveShiftFull);
|
||||
assign ChipSelectInternal = (state == CS_INACTIVE | state == INTER_CS | DelayMode & ~|(Delay0[15:8])) ? ChipSelectDef : ~ChipSelectDef;
|
||||
assign SPICLK = (state == ACTIVE_0) ? ~SckMode[1] : SckMode[1];
|
||||
// assign preSPICLK = (state == ACTIVE_0) ? ~SckMode[1] : SckMode[1];
|
||||
assign Active = (state == ACTIVE_0 | state == ACTIVE_1);
|
||||
assign SampleEdge = SckMode[0] ? (state == ACTIVE_1) : (state == ACTIVE_0);
|
||||
assign ZeroDelayHoldMode = ((ChipSelectMode == 2'b10) & (~|(Delay1[7:4])));
|
||||
assign TransmitInactive = ((state == INTER_CS) | (state == CS_INACTIVE) | (state == INTER_XFR) | (ReceiveShiftFullDelayPCLK & ZeroDelayHoldMode));
|
||||
assign TransmitInactive = ((state == INTER_CS) | (state == CS_INACTIVE) | (state == INTER_XFR) | (ReceiveShiftFullDelayPCLK & ZeroDelayHoldMode) | ((state == ACTIVE_1) & ((ChipSelectMode[1:0] == 2'b10) & ~|(Delay1[15:8]) & (~TransmitFIFOReadEmpty) & (FrameCount == 4'd8))));
|
||||
assign Active0 = (state == ACTIVE_0);
|
||||
|
||||
// Signal tracks which edge of sck to shift data
|
||||
|
Loading…
Reference in New Issue
Block a user