From e3d8162279a0cae37eaddd0683f267ac3cf95fb4 Mon Sep 17 00:00:00 2001 From: naichewa Date: Wed, 1 Nov 2023 10:14:15 -0700 Subject: [PATCH] harris code review 3 --- config/fpga/config.vh | 6 + src/uncore/spi_apb.sv | 476 ++++++--------------------------- src/uncore/uncore.sv | 6 +- src/wally/wallypipelinedsoc.sv | 8 +- testbench/testbench.sv | 3 +- testbench/wallywrapper.sv | 4 +- 6 files changed, 95 insertions(+), 408 deletions(-) diff --git a/config/fpga/config.vh b/config/fpga/config.vh index 9e2b4cbb9..d390453f4 100644 --- a/config/fpga/config.vh +++ b/config/fpga/config.vh @@ -135,10 +135,15 @@ localparam SDC_SUPPORTED = 1'b1; localparam logic [63:0] SDC_BASE = 64'h00013000; localparam logic [63:0] SDC_RANGE = 64'h0000007F; +localparam SPI_SUPPORTED = 1'b1; +localparam logic [63:0] SPI_BASE = 64'h10040000; +localparam logic [63:0] SPI_RANGE = 64'h00000FFF; + // Test modes // Tie GPIO outputs back to inputs localparam GPIO_LOOPBACK_TEST = 0; +localparam SPI_LOOPBACK_TEST = 0; // Hardware configuration localparam UART_PRESCALE = 32'd0; @@ -149,6 +154,7 @@ localparam PLIC_NUM_SRC = 32'd53; localparam PLIC_NUM_SRC_LT_32 = (PLIC_NUM_SRC < 32); localparam PLIC_GPIO_ID = 32'd3; localparam PLIC_UART_ID = 32'd10; +localparam PLIC_SPI_ID = 32'd6; localparam PLIC_SDC_ID = 32'd20; localparam BPRED_SUPPORTED = 1; diff --git a/src/uncore/spi_apb.sv b/src/uncore/spi_apb.sv index d86974500..a177e6502 100644 --- a/src/uncore/spi_apb.sv +++ b/src/uncore/spi_apb.sv @@ -27,9 +27,15 @@ // Current limitations: Flash read sequencer mode not implemented, dual and quad modes untestable with current test plan. // Hardware interlock change to busy signal +// Get rid of dual/ quad mode // write tests for fifo full and empty watermark edge cases -// HoldModeDeassert verilater lint, relook in general +// HoldModeDeassert make sure still works // Comment on FIFOs: watermark calculations +// Comment all interface and internal signals on the lines they are declared +// Get tabs correct so things line up +// Relook at frame compare/ Delay count logic w/o multibit +// look at ReadIncrement/WriteIncrement delay necessity +// test case for two's complement rollover on fifo watermark calculation + watermark calc redesign /* high level explanation of architecture SPI module is written to the specifications described in FU540-C000-v1.0. At the top level, it is consists of synchronous 8 byte transmit and recieve FIFOs connected to shift registers. The FIFOs are connected to WALLY by an apb bus control register interface, which includes various control registers for modifying the SPI transmission along with registers for writing @@ -38,20 +44,19 @@ along with a 4 bit Chip Select signal, a clock signal, and an interrupt signal t */ module spi_apb import cvw::*; #(parameter cvw_t P) ( - input logic PCLK, PRESETn, - input logic PSEL, - input logic [7:0] PADDR, - input logic [P.XLEN-1:0] PWDATA, + input logic PCLK, PRESETn, + input logic PSEL, + input logic [7:0] PADDR, + input logic [P.XLEN-1:0] PWDATA, input logic [P.XLEN/8-1:0] PSTRB, - input logic PWRITE, - input logic PENABLE, - output logic PREADY, - output logic [P.XLEN-1:0] PRDATA, - output logic [3:0] SPIOut, - input logic [3:0] SPIIn, + input logic PWRITE, + input logic PENABLE, + output logic PREADY, + output logic [P.XLEN-1:0] PRDATA, + output logic SPIOut, + input logic SPIIn, output logic [3:0] SPICS, output logic SPIIntr - ); //SPI registers @@ -62,7 +67,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( logic [3:0] ChipSelectDef; logic [1:0] ChipSelectMode; logic [15:0] Delay0, Delay1; - logic [7:0] Format; + logic [4:0] Format; logic [8:0] ReceiveData; logic [8:0] ReceiveDataPlaceholder; logic [2:0] TransmitWatermark, ReceiveWatermark; @@ -77,8 +82,9 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( //FIFO FSM signals logic TransmitWriteMark, TransmitReadMark, RecieveWriteMark, RecieveReadMark; logic TransmitFIFOWriteFull, TransmitFIFOReadEmpty; - logic TransmitFIFOWriteIncrement, TransmitFIFOReadIncrement; - logic ReceiveFIFOWriteIncrement, ReceiveFIFOReadIncrement; + logic TransmitFIFOReadIncrement; + logic TransmitFIFOWriteIncrement; + logic ReceiveFIFOReadIncrement; logic ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty; logic [7:0] TransmitFIFOReadData, ReceiveFIFOWriteData; @@ -89,7 +95,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( //transmission signals logic sck; - logic [12:0] DivCounter; + logic [11:0] DivCounter; logic SCLKenable; logic [8:0] Delay0Count; logic [8:0] Delay1Count; @@ -104,7 +110,6 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( logic [4:0] FrameCompare; logic FrameCompareBoolean; - logic [4:0] FrameCountShifted; logic [4:0] ReceivePenultimateFrame; logic [4:0] ReceivePenultimateFrameCount; logic ReceivePenultimateFrameBoolean; @@ -135,38 +140,31 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( logic ReceiveShiftFullDelay; logic SCLKenableDelay; - logic [3:0] shiftin; + logic shiftin; logic [7:0] ReceiveShiftRegInvert; logic ZeroDelayHoldMode; logic TransmitInactive; logic SCLKenableEarly; logic ReceiveShiftFullDelayPCLK; - logic [2:0] LeftShiftAmount; + logic [3:0] LeftShiftAmount; logic [7:0] ASR; // AlignedReceiveShiftReg logic DelayMode; + logic [3:0] PWChipSelect; - - // apb + // 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 = 1'b1; // tie high if hardware interlock solution doesn't involve bus - assign PREADY = TransmitInactive; // tie PREADY to transmission for hardware interlock - - - + assign PREADY = 1'b1; // tie high if hardware interlock solution doesn't involve bus + //assign PREADY = TransmitInactive; // tie PREADY to transmission for hardware interlock // account for subword read/write circuitry - // -- Note GPIO registers are 32 bits no matter what; access them with LW SW. - // (At least that's what I think when FE310 spec says "only naturally aligned 32-bit accesses are supported") - if (P.XLEN == 64) begin - assign Din = Entry[2] ? PWDATA[63:32] : PWDATA[31:0]; - assign PRDATA = Entry[2] ? {Dout,32'b0} : {32'b0,Dout}; - end else begin // 32-bit - assign Din = PWDATA[31:0]; - assign PRDATA = Dout; - end + // -- Note SPI registers are 32 bits no matter what; access them with LW SW. + + assign Din = PWDATA[31:0]; + if (P.XLEN == 64) assign PRDATA = {Dout, Dout}; + else assign PRDATA = Dout; - // register access + // register access *** clean this up always_ff@(posedge PCLK, negedge PRESETn) if (~PRESETn) begin SckDiv <= #1 12'd3; @@ -176,9 +174,8 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( ChipSelectMode <= #1 0; Delay0 <= #1 {8'b1,8'b1}; Delay1 <= #1 {8'b0,8'b1}; - Format <= #1 {8'b10000000}; + Format <= #1 {5'b10000}; TransmitData <= #1 9'b0; - //ReceiveData <= #1 9'b100000000; TransmitWatermark <= #1 3'b0; ReceiveWatermark <= #1 3'b0; InterruptEnable <= #1 2'b0; @@ -187,8 +184,6 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( //According to FU540 spec: Once interrupt is pending, it will remain set until number //of entries in tx/rx fifo is strictly more/less than tx/rxmark - //From spec. "Hardware interlocks ensure that the current transfer completes before mode transitions and control register updates take effect" - // Interpreting 'current transfer' as one frame /* verilator lint_off CASEINCOMPLETE */ if (Memwrite) case(Entry) //flop to sample inputs @@ -199,7 +194,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( 8'h18: ChipSelectMode <= Din[1:0]; 8'h28: Delay0 <= {Din[23:16], Din[7:0]}; 8'h2C: Delay1 <= {Din[23:16], Din[7:0]}; - 8'h40: Format <= {Din[19:16], Din[3:0]}; + 8'h40: Format <= {Din[19:16], Din[2]}; 8'h48: if (~TransmitFIFOWriteFull) TransmitData[7:0] <= Din[7:0]; 8'h50: TransmitWatermark <= Din[2:0]; 8'h54: ReceiveWatermark <= Din[2:0]; @@ -217,7 +212,7 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( 8'h18: Dout <= #1 {30'b0, ChipSelectMode}; 8'h28: Dout <= {8'b0, Delay0[15:8], 8'b0, Delay0[7:0]}; 8'h2C: Dout <= {8'b0, Delay1[15:8], 8'b0, Delay1[7:0]}; - 8'h40: Dout <= {12'b0, Format[7:4], 12'b0, Format[3:0]}; + 8'h40: Dout <= {12'b0, Format[4:1], 13'b0, Format[0], 2'b0}; 8'h48: Dout <= #1 {23'b0, TransmitFIFOWriteFull, 8'b0}; 8'h4C: Dout <= #1 {23'b0, ReceiveFIFOReadEmpty, ReceiveData[7:0]}; 8'h50: Dout <= #1 {29'b0, TransmitWatermark}; @@ -227,67 +222,21 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( default: Dout <= #1 32'b0; endcase end - - - + // SPI enable generation, where SCLK = PCLK/(2*(SckDiv + 1)) // generates a high signal at the rising and falling edge of SCLK by counting from 0 to SckDiv - assign SCLKenable = (DivCounter == {1'b0,SckDiv}); - assign SCLKenableEarly = ((DivCounter + 13'b1) == {1'b0, SckDiv}); + assign SCLKenable = (DivCounter == SckDiv); + assign SCLKenableEarly = ((DivCounter + 12'b1) == SckDiv); always_ff @(posedge PCLK, negedge PRESETn) if (~PRESETn) DivCounter <= #1 0; else if (SCLKenable) DivCounter <= 0; - else DivCounter <= DivCounter + 13'b1; - - - always_ff @(posedge PCLK, negedge PRESETn) - if (~PRESETn) SCLKenableDelay <= 0; - else SCLKenableDelay <= SCLKenable; + else DivCounter <= DivCounter + 12'b1; //Boolean logic that tracks frame progression - //multiplies frame count by 2 or 4 if in dual or quad mode - always_comb - case(Format[1:0]) - 2'b00: FrameCountShifted = FrameCount; - 2'b01: FrameCountShifted = {FrameCount[3:0], 1'b0}; - 2'b10: FrameCountShifted = {FrameCount[2:0], 2'b0}; - default: FrameCountShifted = FrameCount; - endcase - - //Calculates penultimate frame - //Frame compare doubles number of frames in dual or quad mode to account for half-duplex communication - //FrameCompareProtocol further adjusts comparison according to dual or quad mode - - always_comb - case(Format[1:0]) - 2'b00: begin - ReceivePenultimateFrame = 5'b00001; - FrameCompareProtocol = FrameCompare; - end - 2'b01: begin - ReceivePenultimateFrame = 5'b00010; - //add 1 to count if # of bits is odd so doubled # will be correct - // for ex. 5 bits needs 3 frames, 5*2 = 10 which will be reached in 5 frames not 3*2. - FrameCompareProtocol = Format[4] ? FrameCompare + 5'b1 : FrameCompare; - end - 2'b10: begin - ReceivePenultimateFrame = 5'b00100; - //if frame len =< 4, need 2 frames (one to send 1-4 bits, one to recieve) - //else, 4 < frame len =<8 8, which by same logic needs 4 frames - if (Format[7:4] > 4'b0100) FrameCompareProtocol = 5'b10000; - else FrameCompareProtocol = 5'b01000; - end - default: begin - ReceivePenultimateFrame = 5'b00001; - FrameCompareProtocol = FrameCompare; - end - - endcase - - - assign FrameCompareBoolean = (FrameCountShifted < FrameCompareProtocol); - assign ReceivePenultimateFrameCount = FrameCountShifted + ReceivePenultimateFrame; - assign ReceivePenultimateFrameBoolean = (ReceivePenultimateFrameCount >= FrameCompareProtocol); + assign FrameCompare = {1'b0,Format[4:1]}; + assign FrameCompareBoolean = (FrameCount < FrameCompare); + assign ReceivePenultimateFrameCount = FrameCount + 5'b00001; + assign ReceivePenultimateFrameBoolean = (ReceivePenultimateFrameCount >= FrameCompare); // Computing delays // When sckmode.pha = 0, an extra half-period delay is implicit in the cs-sck delay, and vice-versa for sck-cs @@ -296,11 +245,6 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( assign InterCSCompare = (InterCSCount >= ({Delay1[7:0],1'b0})); assign InterXFRCompare = (InterXFRCount >= ({Delay1[15:8], 1'b0})); - - // double number of frames in dual or quad mode because we must wait for peripheral to send back - assign FrameCompare = (Format[0] | Format[1]) ? ({Format[7:4], 1'b0}) : {1'b0,Format[7:4]}; - - // Transmit and Receive FIFOs //calculate when tx/rx shift registers are full/empty TransmitShiftFSM TransmitShiftFSM_1 (PCLK, PRESETn, TransmitFIFOReadEmpty, ReceivePenultimateFrameBoolean, Active0, TransmitShiftEmpty); ReceiveShiftFSM ReceiveShiftFSM_1 (PCLK, PRESETn, SCLKenable, ReceivePenultimateFrameBoolean, SampleEdge, SckMode[0], ReceiveShiftFull); @@ -312,16 +256,13 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( if (~PRESETn) TransmitFIFOWriteIncrementDelay <= 0; else TransmitFIFOWriteIncrementDelay <= TransmitFIFOWriteIncrement; - assign TransmitFIFOReadIncrement = TransmitShiftEmpty; - assign ReceiveFIFOWriteIncrement = ReceiveShiftFullDelay; - always_ff @(posedge PCLK, negedge PRESETn) if (~PRESETn) ReceiveFIFOReadIncrement <= 0; - else if (~ReceiveFIFOReadIncrement) ReceiveFIFOReadIncrement <= ((Entry == 8'h4C) & ~ReceiveFIFOReadEmpty & PSEL); - else ReceiveFIFOReadIncrement <= 0; - - TransmitSynchFIFO #(3,8) txFIFO(PCLK, SCLKenable, PRESETn, TransmitFIFOWriteIncrementDelay, TransmitFIFOReadIncrement, TransmitData[7:0], TransmitWriteWatermarkLevel, TransmitWatermark[2:0], TransmitFIFOReadData[7:0], TransmitFIFOWriteFull, TransmitFIFOReadEmpty, TransmitWriteMark, TransmitReadMark); - ReceiveSynchFIFO #(3,8) rxFIFO(PCLK, SCLKenable, PRESETn, ReceiveFIFOWriteIncrement, ReceiveFIFOReadIncrement, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel, ReceiveData[7:0], ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty, RecieveWriteMark, RecieveReadMark); + else ReceiveFIFOReadIncrement <= ((Entry == 8'h4C) & ~ReceiveFIFOReadEmpty & PSEL & ~ReceiveFIFOReadIncrement); + + //tx/rx FIFOs + SynchFIFO #(3,8) txFIFO(PCLK, 1'b1, SCLKenable, PRESETn, TransmitFIFOWriteIncrementDelay, TransmitShiftEmpty, TransmitData[7:0], TransmitWriteWatermarkLevel, TransmitWatermark[2:0], TransmitFIFOReadData[7:0], TransmitFIFOWriteFull, TransmitFIFOReadEmpty, TransmitWriteMark, TransmitReadMark); + SynchFIFO #(3,8) rxFIFO(PCLK, SCLKenable, 1'b1, PRESETn, ReceiveShiftFullDelay, ReceiveFIFOReadIncrement, ReceiveShiftRegEndian, ReceiveWatermark[2:0], ReceiveReadWatermarkLevel, ReceiveData[7:0], ReceiveFIFOWriteFull, ReceiveFIFOReadEmpty, RecieveWriteMark, RecieveReadMark); always_ff @(posedge PCLK, negedge PRESETn) if (~PRESETn) TransmitFIFOReadEmptyDelay <= 1; @@ -415,16 +356,12 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( // Ensures that when ChipSelectMode = hold, CS pin is deasserted only when a different value is written to csmode or csid or a write to csdeg changes the state // of the selected pin + assign PWChipSelect = PWDATA[3:0]; always_ff @(posedge PCLK, negedge PRESETn) if (~PRESETn) HoldModeDeassert <= 0; - else if (Inactive) HoldModeDeassert <= 0; - /* verilator lint_off WIDTH */ - else if (((ChipSelectMode[1:0] == 2'b10) & (Entry == (8'h18 | 8'h10) | ((Entry == 8'h14) & ((PWDATA[ChipSelectID]) != ChipSelectDef[ChipSelectID])))) & Memwrite) HoldModeDeassert <= 1; - /* verilator lint_on WIDTH */ + else if (~Inactive & ((ChipSelectMode[1:0] == 2'b10) & (Entry == (8'h18 | 8'h10) | ((Entry == 8'h14) & (PWChipSelect[ChipSelectID] != ChipSelectDef[ChipSelectID])))) & Memwrite) HoldModeDeassert <= 1; - - - // Signal tracks which edge of sck to shift data + // Signal tracks which edge of sck to shift data always_comb case(SckMode[1:0]) 2'b00: sckPhaseSelect = ~sck & SCLKenable; @@ -435,36 +372,14 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( endcase //Transmit shift register - assign TransmitDataEndian = Format[2] ? {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) - if(~PRESETn) begin - TransmitShiftReg <= 8'b0; - end - else if (TransmitShiftRegLoad) TransmitShiftReg <= TransmitDataEndian; - else if (sckPhaseSelect) begin - //if ((ChipSelectMode[1:0] == 2'b10) & ~|(Delay1[15:8]) & (~TransmitFIFOReadEmpty) & TransmitShiftEmpty) TransmitShiftReg <= TransmitFIFOReadData; - if (Active) begin - case (Format[1:0]) - 2'b00: TransmitShiftReg <= {TransmitShiftReg[6:0], 1'b0}; - 2'b01: TransmitShiftReg <= {TransmitShiftReg[5:0], 2'b0}; - 2'b10: TransmitShiftReg <= {TransmitShiftReg[3:0], 4'b0}; - default: TransmitShiftReg <= {TransmitShiftReg[6:0], 1'b0}; - endcase - end - end - always_comb - - //Output pin control based on single, dual, or quad mode - if (Active | Delay0Compare | ~TransmitShiftEmpty) begin - case(Format[1:0]) - 2'b00: SPIOut = {3'b0,TransmitShiftReg[7]}; - 2'b01: SPIOut = {2'b0,TransmitShiftReg[6], TransmitShiftReg[7]}; - // assuming SPIOut[0] is first bit transmitted etc - 2'b10: SPIOut = {TransmitShiftReg[3], TransmitShiftReg[2], TransmitShiftReg[1], TransmitShiftReg[0]}; - default: SPIOut = {3'b0, TransmitShiftReg[7]}; - endcase - end else SPIOut = 4'b0; + if(~PRESETn) TransmitShiftReg <= 8'b0; + else if (TransmitShiftRegLoad) TransmitShiftReg <= TransmitDataEndian; + else if (sckPhaseSelect & Active) TransmitShiftReg <= {TransmitShiftReg[6:0], 1'b0}; + assign SPIOut = TransmitShiftReg[7]; + //If in loopback mode, receive shift register is connected directly to module's output pins. Else, connected to SPIIn //There are no setup/hold time issues because transmit shift register and receive shift register always shift/sample on opposite edges assign shiftin = P.SPI_LOOPBACK_TEST ? SPIOut : SPIIn; @@ -474,25 +389,19 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( if(~PRESETn) ReceiveShiftReg <= 8'b0; else if (SampleEdge & SCLKenable) begin if (~Active) ReceiveShiftReg <= 8'b0; - else if (~Format[3]) begin - case(Format[1:0]) - 2'b00: ReceiveShiftReg <= { ReceiveShiftReg[6:0], shiftin[0]}; - 2'b01: ReceiveShiftReg <= { ReceiveShiftReg[5:0], shiftin[0],shiftin[1]}; - 2'b10: ReceiveShiftReg <= { ReceiveShiftReg[3:0], shiftin[0], shiftin[1], shiftin[2], shiftin[3]}; - default: ReceiveShiftReg <= { ReceiveShiftReg[6:0], shiftin[0]}; - endcase - end + else ReceiveShiftReg <= {ReceiveShiftReg[6:0], shiftin}; end // Aligns received data and reverses if little-endian - assign LeftShiftAmount = 8 - Format[7:4]; - assign ASR = ReceiveShiftReg << LeftShiftAmount; - assign ReceiveShiftRegEndian = Format[2] ? {ASR[0], ASR[1], ASR[2], ASR[3], ASR[4], ASR[5], ASR[6], ASR[7]} : ASR[7:0]; + assign LeftShiftAmount = 4'h8 - Format[4:1]; + assign ASR = ReceiveShiftReg << LeftShiftAmount[2:0]; + assign ReceiveShiftRegEndian = Format[0] ? {ASR[0], ASR[1], ASR[2], ASR[3], ASR[4], ASR[5], ASR[6], ASR[7]} : ASR[7:0]; // Interrupt logic: raise interrupt if any enabled interrupts are pending assign SPIIntr = |(InterruptPending & InterruptEnable); // Chip select logic + always_comb case(ChipSelectID[1:0]) 2'b00: ChipSelectAuto = {ChipSelectDef[3], ChipSelectDef[2], ChipSelectDef[1], ChipSelectInternal[0]}; @@ -500,12 +409,12 @@ module spi_apb import cvw::*; #(parameter cvw_t P) ( 2'b10: ChipSelectAuto = {ChipSelectDef[3],ChipSelectInternal[2], ChipSelectDef[1], ChipSelectDef[0]}; 2'b11: ChipSelectAuto = {ChipSelectInternal[3],ChipSelectDef[2], ChipSelectDef[1], ChipSelectDef[0]}; endcase + assign SPICS = ChipSelectMode[0] ? ChipSelectDef : ChipSelectAuto; - - endmodule -module TransmitSynchFIFO #(parameter M =3 , N= 8)( - input logic PCLK, sclken, PRESETn, + +module SynchFIFO #(parameter M =3 , N= 8)( + input logic PCLK, wen, ren, PRESETn, input logic winc,rinc, input logic [N-1:0] wdata, input logic [M-1:0] wwatermarklevel, rwatermarklevel, @@ -514,7 +423,7 @@ module TransmitSynchFIFO #(parameter M =3 , N= 8)( output logic wwatermark, rwatermark); logic [N-1:0] mem[2**M]; - logic [M:0] rptr, wptr; + logic [M:0] rwpr, wptr; logic [M:0] rptrnext, wptrnext; logic rempty_val; logic wfull_val; @@ -525,7 +434,7 @@ module TransmitSynchFIFO #(parameter M =3 , N= 8)( always_ff @(posedge PCLK) if (winc & ~wfull) mem[waddr] <= wdata; - // read flops are only enabled on sclk edges b/c transmit fifo is read on sclk + // write and read are enabled always_ff @(posedge PCLK, negedge PRESETn) if (~PRESETn) begin rptr <= 0; @@ -534,9 +443,11 @@ module TransmitSynchFIFO #(parameter M =3 , N= 8)( rempty <= 1'b1; end else begin - wfull <= wfull_val; - wptr <= wptrnext; - if (sclken) begin + if (wen) begin + wfull <= wfull_val; + wptr <= wptrnext; + end + if (ren) begin rptr <= rptrnext; rempty <= rempty_val; end @@ -545,245 +456,12 @@ module TransmitSynchFIFO #(parameter M =3 , N= 8)( assign raddr = rptr[M-1:0]; assign rptrnext = rptr + {3'b0, (rinc & ~rempty)}; assign rempty_val = (wptr == rptrnext); - assign rwatermark = ((rptr[M-1:0] - wptr[M-1:0]) < rwatermarklevel); + assign rwatermark = ((raddr - waddr) < rwatermarklevel); assign waddr = wptr[M-1:0]; - assign wwatermark = ((wptr[M-1:0] - rptr[M-1:0]) > wwatermarklevel); + assign wwatermark = ((waddr - raddr) > wwatermarklevel); assign wptrnext = wptr + {3'b0, (winc & ~wfull)}; assign wfull_val = ({~wptrnext[M], wptrnext[M-1:0]} == rptr); - - - - - - -endmodule - - -module ReceiveSynchFIFO #(parameter M =3 , N= 8)( - input logic PCLK, sclken, 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); - - logic [N-1:0] mem[2**M]; - logic [M:0] rptr, wptr; - logic [M:0] rptrnext, wptrnext; - logic rempty_val; - logic wfull_val; - logic [M-1:0] raddr; - logic [M-1:0] waddr; - - assign rdata = mem[raddr]; - always_ff @(posedge PCLK) - if(winc & ~wfull & PCLK) mem[waddr] <= wdata; - - //write flops are enabled only on sclk edges b/c receive fifo is written then - always_ff @(posedge PCLK, negedge PRESETn) - if (~PRESETn) begin - rptr <= 0; - wptr <= 0; - wfull <= 0; - rempty <= 0; - end else begin - rptr <= rptrnext; - rempty <= rempty_val; - if (sclken) begin - wptr <= wptrnext; - wfull <= wfull_val; - end - end - - assign rwatermark = ((rptr[M-1:0] - wptr[M-1:0]) < rwatermarklevel); - assign raddr = rptr[M-1:0]; - assign rptrnext = rptr + {3'b0, (rinc & ~rempty)}; - assign rempty_val = (wptr == rptrnext); - - assign waddr = wptr[M-1:0]; - assign wwatermark = ((wptr[M-1:0] - rptr[M-1:0]) > wwatermarklevel); - assign wptrnext = wptr + {3'b0, (winc & ~wfull)}; - assign wfull_val = ({~wptrnext[M], wptrnext[M-1:0]} == rptr); - - - -endmodule - -module TransmitFIFO #(parameter M = 3, N = 8)( - input logic wclk, rclk, 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); - - logic [N-1:0] mem[2**M]; - logic [M:0] wq1_rptr, wq2_rptr, rptr; - logic [M:0] rq1_wptr, rq2_wptr, wptr; - logic [M:0] rbin, rgraynext, rbinnext; - logic [M:0] wbin, wgraynext, wbinnext; - logic rempty_val; - logic wfull_val; - logic [M:0] wq2_rptr_bin, rq2_wptr_bin; - logic [M-1:0] raddr; - logic [M-1:0] waddr; - - assign rdata = mem[raddr]; - always_ff @(posedge wclk) - if(winc & ~wfull) mem[waddr] <= wdata; - - - always_ff @(posedge wclk, negedge PRESETn) - if (~PRESETn) begin - wq2_rptr <= 0; - wq1_rptr <= 0; - end - else begin - wq2_rptr <= wq1_rptr; - wq1_rptr <= rptr; - end - - always_ff @(posedge wclk, negedge PRESETn) - if (~PRESETn) begin - rq2_wptr <= 0; - rq1_wptr <= 0; - end - else if (rclk) begin - - rq2_wptr <= rq1_wptr; - rq1_wptr <= wptr; - end - - always_ff @(posedge wclk, negedge PRESETn) - if(~PRESETn) begin - rbin <= 0; - rptr <= 0; - end - else if (rclk) begin - rbin <= rbinnext; - rptr <= rgraynext; - end - assign rq2_wptr_bin = {rq2_wptr[3], (rq2_wptr[3]^rq2_wptr[2]),(rq2_wptr[3]^rq2_wptr[2]^rq2_wptr[1]), (rq2_wptr[3]^rq2_wptr[2]^rq2_wptr[1]^rq2_wptr[0]) }; - assign rwatermark = ((rbin[M-1:0] - rq2_wptr_bin[M-1:0]) < rwatermarklevel); - assign raddr = rbin[M-1:0]; - assign rbinnext = rbin + {3'b0, (rinc & ~rempty)}; - assign rgraynext = (rbinnext >> 1) ^ rbinnext; - assign rempty_val = (rgraynext == rq2_wptr); - - always_ff @(posedge wclk, negedge PRESETn) - if (~PRESETn) rempty <= 1'b1; - else if (rclk) rempty <= rempty_val; - - always_ff @(posedge wclk, negedge PRESETn) - if (~PRESETn) begin - wbin <= 0; - wptr <= 0; - end else begin - wbin <= wbinnext; - wptr <= wgraynext; - end - assign waddr = wbin[M-1:0]; - assign wq2_rptr_bin = {wq2_rptr[3], (wq2_rptr[3]^wq2_rptr[2]),(wq2_rptr[3]^wq2_rptr[2]^wq2_rptr[1]), (wq2_rptr[3]^wq2_rptr[2]^wq2_rptr[1]^wq2_rptr[0]) }; - assign wwatermark = ((wbin[M-1:0] - wq2_rptr_bin[M-1:0]) > wwatermarklevel); - assign wbinnext = wbin + {3'b0, (winc & ~wfull)}; - assign wgraynext = (wbinnext >> 1) ^ wbinnext; - - assign wfull_val = (wgraynext == {(~wq2_rptr[M:M-1]),wq2_rptr[M-2:0]}); - - always_ff @(posedge wclk, negedge PRESETn) - if (~PRESETn) wfull <= 1'b0; - else wfull <= wfull_val; - -endmodule - -module ReceiveFIFO #(parameter M = 3, N = 8)( - input logic wclk, rclk, 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); - - logic [N-1:0] mem[2**M]; - logic [M:0] wq1_rptr, wq2_rptr, rptr; - logic [M:0] rq1_wptr, rq2_wptr, wptr; - logic [M:0] rbin, rgraynext, rbinnext; - logic [M:0] wbin, wgraynext, wbinnext; - logic rempty_val; - logic wfull_val; - logic [M:0] wq2_rptr_bin, rq2_wptr_bin; - logic [M-1:0] raddr; - logic [M-1:0] waddr; - - assign rdata = mem[raddr]; - always_ff @(posedge rclk) - if(winc & ~wfull & wclk) mem[waddr] <= wdata; - - - always_ff @(posedge rclk, negedge PRESETn) - if (~PRESETn) begin - wq2_rptr <= 0; - wq1_rptr <= 0; - end - else if (wclk) begin - wq2_rptr <= wq1_rptr; - wq1_rptr <= rptr; - end - - always_ff @(posedge rclk, negedge PRESETn) - if (~PRESETn) begin - rq2_wptr <= 0; - rq1_wptr <= 0; - end - else begin - rq2_wptr <= rq1_wptr; - rq1_wptr <= wptr; - end - - always_ff @(posedge rclk, negedge PRESETn) - if(~PRESETn) begin - rbin <= 0; - rptr <= 0; - end - else begin - rbin <= rbinnext; - rptr <= rgraynext; - end - assign rq2_wptr_bin = {rq2_wptr[3], (rq2_wptr[3]^rq2_wptr[2]),(rq2_wptr[3]^rq2_wptr[2]^rq2_wptr[1]), (rq2_wptr[3]^rq2_wptr[2]^rq2_wptr[1]^rq2_wptr[0]) }; - assign rwatermark = ((rbin[M-1:0] - rq2_wptr_bin[M-1:0]) < rwatermarklevel); - assign raddr = rbin[M-1:0]; - assign rbinnext = rbin + {3'b0, (rinc & ~rempty)}; - assign rgraynext = (rbinnext >> 1) ^ rbinnext; - assign rempty_val = (rgraynext == rq2_wptr); - - always_ff @(posedge rclk, negedge PRESETn) - if (~PRESETn) rempty <= 1'b1; - else rempty <= rempty_val; - - always_ff @(posedge rclk, negedge PRESETn) - if (~PRESETn) begin - wbin <= 0; - wptr <= 0; - end else if (wclk) begin - wbin <= wbinnext; - wptr <= wgraynext; - end - assign waddr = wbin[M-1:0]; - assign wq2_rptr_bin = {wq2_rptr[3], (wq2_rptr[3]^wq2_rptr[2]),(wq2_rptr[3]^wq2_rptr[2]^wq2_rptr[1]), (wq2_rptr[3]^wq2_rptr[2]^wq2_rptr[1]^wq2_rptr[0]) }; - assign wwatermark = ((wbin[M-1:0] - wq2_rptr_bin[M-1:0]) > wwatermarklevel); - assign wbinnext = wbin + {3'b0, (winc & ~wfull)}; - assign wgraynext = (wbinnext >> 1) ^ wbinnext; - - assign wfull_val = (wgraynext == {(~wq2_rptr[M:M-1]),wq2_rptr[M-2:0]}); - - always_ff @(posedge rclk, negedge PRESETn) - if (~PRESETn) wfull <= 1'b0; - else if (wclk) wfull <= wfull_val; - endmodule module TransmitShiftFSM( diff --git a/src/uncore/uncore.sv b/src/uncore/uncore.sv index 3f9aae238..916dc53ef 100644 --- a/src/uncore/uncore.sv +++ b/src/uncore/uncore.sv @@ -55,9 +55,9 @@ module uncore import cvw::*; #(parameter cvw_t P)( input logic UARTSin, // UART serial input output logic UARTSout, // UART serial output input logic SDCIntr, - input logic [3:0] SPIIn, - output logic [3:0] SPIOut, - output logic [3:0] SPICS + input logic SPIIn, + output logic SPIOut, + output logic [3:0] SPICS ); logic [P.XLEN-1:0] HREADRam, HREADSDC; diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index 336bb7a6a..ab0071fff 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -54,14 +54,14 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( output logic [31:0] GPIOEN, // output enables for GPIO input logic UARTSin, // UART serial data input output logic UARTSout, // UART serial data output - input logic SDCIntr, - input logic [3:0] SPIIn, // SPI pins in - output logic [3:0] SPIOut, // SPI pins out + input logic SDCIntr, + input logic SPIIn, // SPI pins in + output logic SPIOut, // SPI pins out output logic [3:0] SPICS // SPI chip select pins ); // Uncore signals - logic [P.AHBW-1:0] HRDATA; // from AHB mux in uncore + logic [P.AHBW-1:0] HRDATA; // from AHB mux in uncore logic HRESP; // response from AHB logic MTimerInt, MSwInt;// timer and software interrupts from CLINT logic [63:0] MTIME_CLINT; // from CLINT to CSRs diff --git a/testbench/testbench.sv b/testbench/testbench.sv index a417e4075..56a8db268 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -64,7 +64,8 @@ module testbench; logic [31:0] GPIOIN, GPIOOUT, GPIOEN; logic UARTSin, UARTSout; - logic [3:0] SPIIn, SPIOut, SPICS; + logic SPIIn, SPIOut; + logic [3:0] SPICS; logic SDCIntr; logic HREADY; diff --git a/testbench/wallywrapper.sv b/testbench/wallywrapper.sv index 465aaec90..64b63c54a 100644 --- a/testbench/wallywrapper.sv +++ b/testbench/wallywrapper.sv @@ -51,6 +51,8 @@ module wallywrapper; logic [31:0] GPIOIN, GPIOOUT, GPIOEN; logic UARTSin, UARTSout; + logic SPIIn, SPIOut; + logic [3:0] SPICS; logic SDCIntr; logic HREADY; @@ -70,6 +72,6 @@ module wallywrapper; wallypipelinedsoc #(P) dut(.clk, .reset_ext, .reset, .HRDATAEXT,.HREADYEXT, .HRESPEXT,.HSELEXT, .HSELEXTSDC, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, - .UARTSin, .UARTSout, .SDCIntr); + .UARTSin, .UARTSout, .SPIIn, .SPIOut, .SPICS, .SDCIntr); endmodule