From fea439b84d8568de24ef4a1fc75c7b142a30f449 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Fri, 24 Sep 2021 10:45:09 -0500 Subject: [PATCH] SDC to ABHLite interface partially done. Added SDC to adrdec and uncore. --- wally-pipelined/config/rv32ic/wally-config.vh | 3 + wally-pipelined/config/rv64ic/wally-config.vh | 3 + wally-pipelined/src/mmu/adrdecs.sv | 17 ++-- wally-pipelined/src/mmu/pmachecker.sv | 4 +- wally-pipelined/src/sdc/SDC.sv | 93 +++++++++++-------- wally-pipelined/src/sdc/sd_cmd_fsm.sv | 4 +- wally-pipelined/src/uncore/uncore.sv | 44 ++++++--- .../src/wally/wallypipelinedsoc.sv | 18 +++- 8 files changed, 120 insertions(+), 66 deletions(-) diff --git a/wally-pipelined/config/rv32ic/wally-config.vh b/wally-pipelined/config/rv32ic/wally-config.vh index dfe1c61e0..6eeebdd69 100644 --- a/wally-pipelined/config/rv32ic/wally-config.vh +++ b/wally-pipelined/config/rv32ic/wally-config.vh @@ -93,6 +93,9 @@ `define PLIC_SUPPORTED 1'b1 `define PLIC_BASE 34'h0C000000 `define PLIC_RANGE 34'h03FFFFFF +`define SDC_SUPPORTED 1'b1 +`define SDC_BASE 34'h00012100 +`define SDC_RANGE 34'h00000020 // Bus Interface width `define AHBW 32 diff --git a/wally-pipelined/config/rv64ic/wally-config.vh b/wally-pipelined/config/rv64ic/wally-config.vh index ef935ae2c..58bbaa9e2 100644 --- a/wally-pipelined/config/rv64ic/wally-config.vh +++ b/wally-pipelined/config/rv64ic/wally-config.vh @@ -97,6 +97,9 @@ `define PLIC_SUPPORTED 1'b1 `define PLIC_BASE 56'h0C000000 `define PLIC_RANGE 56'h03FFFFFF +`define SDC_SUPPORTED 1'b1 +`define SDC_BASE 56'h00012100 +`define SDC_RANGE 56'h00000020 // Test modes diff --git a/wally-pipelined/src/mmu/adrdecs.sv b/wally-pipelined/src/mmu/adrdecs.sv index 3084b0ac7..a8f88249f 100644 --- a/wally-pipelined/src/mmu/adrdecs.sv +++ b/wally-pipelined/src/mmu/adrdecs.sv @@ -30,19 +30,20 @@ module adrdecs ( input logic [`PA_BITS-1:0] PhysicalAddress, input logic AccessRW, AccessRX, AccessRWX, input logic [1:0] Size, - output logic [6:0] SelRegions + output logic [7:0] SelRegions ); // Determine which region of physical memory (if any) is being accessed // *** eventually uncomment Access signals - adrdec boottimdec(PhysicalAddress, `BOOTTIM_BASE, `BOOTTIM_RANGE, `BOOTTIM_SUPPORTED, /*1'b1*/AccessRX, Size, 4'b1111, SelRegions[5]); - adrdec timdec(PhysicalAddress, `TIM_BASE, `TIM_RANGE, `TIM_SUPPORTED, /*1'b1*/AccessRWX, Size, 4'b1111, SelRegions[4]); - adrdec clintdec(PhysicalAddress, `CLINT_BASE, `CLINT_RANGE, `CLINT_SUPPORTED, AccessRW, Size, 4'b1111, SelRegions[3]); - adrdec gpiodec(PhysicalAddress, `GPIO_BASE, `GPIO_RANGE, `GPIO_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[2]); - adrdec uartdec(PhysicalAddress, `UART_BASE, `UART_RANGE, `UART_SUPPORTED, AccessRW, Size, 4'b0001, SelRegions[1]); - adrdec plicdec(PhysicalAddress, `PLIC_BASE, `PLIC_RANGE, `PLIC_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[0]); + adrdec boottimdec(PhysicalAddress, `BOOTTIM_BASE, `BOOTTIM_RANGE, `BOOTTIM_SUPPORTED, /*1'b1*/AccessRX, Size, 4'b1111, SelRegions[6]); + adrdec timdec(PhysicalAddress, `TIM_BASE, `TIM_RANGE, `TIM_SUPPORTED, /*1'b1*/AccessRWX, Size, 4'b1111, SelRegions[5]); + adrdec clintdec(PhysicalAddress, `CLINT_BASE, `CLINT_RANGE, `CLINT_SUPPORTED, AccessRW, Size, 4'b1111, SelRegions[4]); + adrdec gpiodec(PhysicalAddress, `GPIO_BASE, `GPIO_RANGE, `GPIO_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[3]); + adrdec uartdec(PhysicalAddress, `UART_BASE, `UART_RANGE, `UART_SUPPORTED, AccessRW, Size, 4'b0001, SelRegions[2]); + adrdec plicdec(PhysicalAddress, `PLIC_BASE, `PLIC_RANGE, `PLIC_SUPPORTED, AccessRW, Size, 4'b0100, SelRegions[1]); + adrdec sdcdec(PhysicalAddress, `SDC_BASE, `SDC_RANGE, `SDC_SUPPORTED, AccessRW, Size, 4'b0011, SelRegions[0]); - assign SelRegions[6] = ~|(SelRegions[5:0]); + assign SelRegions[7] = ~|(SelRegions[6:0]); endmodule diff --git a/wally-pipelined/src/mmu/pmachecker.sv b/wally-pipelined/src/mmu/pmachecker.sv index a95252f3b..5ce62c0d4 100644 --- a/wally-pipelined/src/mmu/pmachecker.sv +++ b/wally-pipelined/src/mmu/pmachecker.sv @@ -45,7 +45,7 @@ module pmachecker ( logic PMAAccessFault; logic AccessRW, AccessRWX, AccessRX; - logic [6:0] SelRegions; + logic [7:0] SelRegions; // Determine what type of access is being made assign AccessRW = ReadAccessM | WriteAccessM; @@ -61,7 +61,7 @@ module pmachecker ( assign AtomicAllowed = SelRegions[4]; // Detect access faults - assign PMAAccessFault = SelRegions[6] & AccessRWX; + assign PMAAccessFault = SelRegions[7] & AccessRWX; assign PMAInstrAccessFaultF = ExecuteAccessF && PMAAccessFault; assign PMALoadAccessFaultM = ReadAccessM && PMAAccessFault; assign PMAStoreAccessFaultM = WriteAccessM && PMAAccessFault; diff --git a/wally-pipelined/src/sdc/SDC.sv b/wally-pipelined/src/sdc/SDC.sv index 66a266a28..7167286e8 100644 --- a/wally-pipelined/src/sdc/SDC.sv +++ b/wally-pipelined/src/sdc/SDC.sv @@ -43,16 +43,16 @@ module SDC //sd card interface // place the tristate drivers at the top. this level // will use dedicated 1 direction ports. - output logic SDCmdOut, - input logic SDCmdIn, - output logic SDCmdOE, - input logic SDDatIn, - output logic SDCLK, + output logic SDCCmdOut, + input logic SDCCmdIn, + output logic SDCCmdOE, + input logic [3:0] SDCDatIn, + output logic SDCCLK, // interrupt to PLIC output logic SDCIntM); - logic initTrans; + logic InitTrans; logic RegRead; logic RegWrite; logic [4:0] HADDRDelay; @@ -61,7 +61,7 @@ module SDC // Register outputs logic [7:0] CLKDiv; logic [2:0] Command; - logic [`XLEN-1:9] Address; + logic [63:9] Address; logic SDCDone; @@ -73,23 +73,26 @@ module SDC logic StartCLKDivUpdate; logic CLKDivUpdateEn; - logic SDCLKEN; - + logic SDCCLKEN; + logic CLKGate; + logic SDCDataValid; + logic [`XLEN-1:0] SDCReadData; + logic [`XLEN-1:0] ReadData; // registers - //| Offset | Name | Size | Purpose | - //|--------+---------+------+------------------------------------------------| - //| 0x0 | CLKDiv | 4 | Divide HCLK to produce SDCLK | - //| 0x4 | Status | 4 | Provide status to software | - //| 0x8 | Control | 4 | Send commands to SDC | - //| 0xC | Size | 4 | Size of data command (only 512 byte supported) | - //| 0x10 | address | 8 | address of operation | - //| 0x18 | data | 8 | Data Bus interface | + //| Offset | Name | Size | Purpose | + //|--------+---------+--------+------------------------------------------------| + //| 0x0 | CLKDiv | 4 | Divide HCLK to produce SDCLK | + //| 0x4 | Status | 4 | Provide status to software | + //| 0x8 | Control | 4 | Send commands to SDC | + //| 0xC | Size | 4 | Size of data command (only 512 byte supported) | + //| 0x10 | address | 8 | address of operation | + //| 0x18 | data | XLEN/8 | Data Bus interface | // Status contains - // Status[0] busy + // Status[0] busy // Status[1] done // Status[2] invalid command // Status[5:3] error code @@ -125,42 +128,50 @@ module SDC assign StartCLKDivUpdate = HADDRDelay == '0 & RegWrite; - flopenl #(8) CLKDivReg(HCLK, ~HRESETn, CLKDivUpdateEn, HWDATA[31:0], `SDCCLKDIV, CLKDiv); + flopenl #(8) CLKDivReg(HCLK, ~HRESETn, CLKDivUpdateEn, HWDATA[7:0], `SDCCLKDIV, CLKDiv); // Control reg flopenl #(3) CommandReg(HCLK, ~HRESETn, (HADDRDelay == 'h8 & RegWrite) | (SDCDone), SDCDone ? '0 : HWDATA[2:0], '0, Command); - - flopenr #(`XLEN-9) AddressReg(HCLK, ~HRESETn, (HADDRDelay == 'h10 & RegWrite), - HWDATA[`XLEN-1:9], Address); + generate + if (`XLEN == 64) begin + flopenr #(64-9) AddressReg(HCLK, ~HRESETn, (HADDRDelay == 'h10 & RegWrite), + HWDATA[`XLEN-1:9], Address); + end else begin + flopenr #(32-9) AddressLowReg(HCLK, ~HRESETn, (HADDRDelay == 'h10 & RegWrite), + HWDATA[`XLEN-1:9], Address[31:9]); + flopenr #(32) AddressHighReg(HCLK, ~HRESETn, (HADDRDelay == 'h14 & RegWrite), + HWDATA, Address[63:32]); + end + endgenerate + flopen #(`XLEN) DataReg(HCLK, (HADDRDelay == 'h18 & RegWrite) | (SDCDataValid), SDCDataValid ? SDCReadData : HWDATA, ReadData); generate if(`XLEN == 64) begin always_comb - case(HADDRDelay[4:2]) - 'h0: HREADSDC = {`XLEN-8'b0, CLKDiv}; - 'h4: HREADSDC = {`XLEN-6'b0, ErrorCode, InvalidCommand, Done, Busy}; - 'h8: HREADSDC = {`XLEN-3'b0, Command}; + case(HADDRDelay[4:0]) + 'h0: HREADSDC = {56'b0, CLKDiv}; + 'h4: HREADSDC = {58'b0, ErrorCode, InvalidCommand, Done, Busy}; + 'h8: HREADSDC = {61'b0, Command}; 'hC: HREADSDC = 'h200; - 'h10: HREADSDC = Address; + 'h10: HREADSDC = {Address, 9'b0}; 'h18: HREADSDC = ReadData; - default: HREADSDC = {32'b0, CLKDiv}; + default: HREADSDC = {56'b0, CLKDiv}; endcase end else begin always_comb - case(HADDRDelay[4:2]) - 'h0: HREADSDC = CLKDiv; - 'h4: HREADSDC = {ErrorCode, InvalidCommand, Done, Busy}; - 'h8: HREADSDC = Command; + case(HADDRDelay[4:0]) + 'h0: HREADSDC = {24'b0, CLKDiv}; + 'h4: HREADSDC = {26'b0, ErrorCode, InvalidCommand, Done, Busy}; + 'h8: HREADSDC = {29'b0, Command}; 'hC: HREADSDC = 'h200; - 'h10: HREADSDC = Address[31:0]; + 'h10: HREADSDC = {Address[31:9], 9'b0}; 'h14: HREADSDC = Address[63:32]; 'h18: HREADSDC = ReadData[31:0]; - 'h1C: HREADSDC = ReadData[63:32]; - default: HREADSDC = CLKDiv; + default: HREADSDC = {24'b0, CLKDiv}; endcase end endgenerate @@ -190,7 +201,7 @@ module SDC always_comb begin CLKDivUpdateEn = 1'b0; HREADYSDC = 1'b0; - SDCLKEN = 1'b1; + SDCCLKEN = 1'b1; case (CurrState) STATE_READY : begin @@ -208,16 +219,16 @@ module SDC end STATE_CLK_DIV1: begin NextState = STATE_CLK_DIV2; - SDCLKEN = 1'b0; + SDCCLKEN = 1'b0; end STATE_CLK_DIV2: begin NextState = STATE_CLK_DIV3; CLKDivUpdateEn = 1'b1; - SDCLKEN = 1'b0; + SDCCLKEN = 1'b0; end STATE_CLK_DIV3: begin NextState = STATE_CLK_DIV4; - SDCLKEN = 1'b0; + SDCCLKEN = 1'b0; end STATE_CLK_DIV4: begin NextState = STATE_READY; @@ -227,7 +238,7 @@ module SDC // clock generation divider - clockgater clockgater(.E(SDCLKEN), + clockgater clockgater(.E(SDCCLKEN), .SE(1'b0), .CLK(HCLK), .ECLK(CLKGate)); @@ -237,7 +248,7 @@ module SDC .i_EN(CLKDiv != 'b1), .i_CLK(CLKGate), .i_RST(~HRESETn), - .o_CLK(CLKSDC)); + .o_CLK(SDCCLK)); diff --git a/wally-pipelined/src/sdc/sd_cmd_fsm.sv b/wally-pipelined/src/sdc/sd_cmd_fsm.sv index c98448c7d..c21331920 100644 --- a/wally-pipelined/src/sdc/sd_cmd_fsm.sv +++ b/wally-pipelined/src/sdc/sd_cmd_fsm.sv @@ -204,7 +204,9 @@ module sd_cmd_fsm localparam logic [7:0] c_NCC_min = 8'd7; // counter_in localparam logic [7:0] c_NRC_min = 8'd8; // counter_in - localparam logic [18:0] c_1000ms = 18'd400000; // ACMD41 timeout + //localparam logic [18:0] c_1000ms = 18'd400000; // ACMD41 timeout + //*** BUG this value is too bit to fit into 19 bits. + localparam logic [18:0] c_1000ms = 18'd40000; // ACMD41 timeout // command instruction type (opcode(6)) localparam c_CMD = 1'b0; diff --git a/wally-pipelined/src/uncore/uncore.sv b/wally-pipelined/src/uncore/uncore.sv index 78a89b02d..bf9e46081 100644 --- a/wally-pipelined/src/uncore/uncore.sv +++ b/wally-pipelined/src/uncore/uncore.sv @@ -56,30 +56,36 @@ module uncore ( output logic [31:0] GPIOPinsOut, GPIOPinsEn, input logic UARTSin, output logic UARTSout, + output logic SDCCmdOut, + output logic SDCCmdOE, + input logic SDCCmdIn, + input logic [3:0] SDCDatIn, + output logic SDCCLK, output logic [63:0] MTIME_CLINT, MTIMECMP_CLINT ); logic [`XLEN-1:0] HWDATA; - logic [`XLEN-1:0] HREADTim, HREADCLINT, HREADPLIC, HREADGPIO, HREADUART; + logic [`XLEN-1:0] HREADTim, HREADCLINT, HREADPLIC, HREADGPIO, HREADUART, HREADSDC; - logic [6:0] HSELRegions; - logic HSELTim, HSELCLINT, HSELPLIC, HSELGPIO, PreHSELUART, HSELUART; - logic HSELTimD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD; - logic HRESPTim, HRESPCLINT, HRESPPLIC, HRESPGPIO, HRESPUART; - logic HREADYTim, HREADYCLINT, HREADYPLIC, HREADYGPIO, HREADYUART; + logic [7:0] HSELRegions; + logic HSELTim, HSELCLINT, HSELPLIC, HSELGPIO, PreHSELUART, HSELUART, HSELSDC; + logic HSELTimD, HSELCLINTD, HSELPLICD, HSELGPIOD, HSELUARTD, HSELSDCD; + logic HRESPTim, HRESPCLINT, HRESPPLIC, HRESPGPIO, HRESPUART, HRESPSDC; + logic HREADYTim, HREADYCLINT, HREADYPLIC, HREADYGPIO, HREADYUART, HRESPSDCD; logic [`XLEN-1:0] HREADBootTim; - logic HSELBootTim, HSELBootTimD, HRESPBootTim, HREADYBootTim; + logic HSELBootTim, HSELBootTimD, HRESPBootTim, HREADYBootTim, HREADYSDC; logic HSELNoneD; logic [1:0] MemRWboottim; logic UARTIntr,GPIOIntr; - + logic SDCIntM; + // Determine which region of physical memory (if any) is being accessed // Use a trimmed down portion of the PMA checker - only the address decoders // Set access types to all 1 as don't cares because the MMU has already done access checking adrdecs adrdecs({{(`PA_BITS-32){1'b0}}, HADDR}, 1'b1, 1'b1, 1'b1, HSIZE[1:0], HSELRegions); // unswizzle HSEL signals - assign {HSELBootTim, HSELTim, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC} = HSELRegions[5:0]; + assign {HSELBootTim, HSELTim, HSELCLINT, HSELGPIO, HSELUART, HSELPLIC, HSELSDC} = HSELRegions[6:0]; // subword accesses: converts HWDATAIN to HWDATA subwordwrite sww(.*); @@ -115,6 +121,17 @@ module uncore ( end else begin : uart assign UARTSout = 0; assign UARTIntr = 0; end + if (`SDC_SUPPORTED == 1) begin : sdc + SDC SDC(.HCLK, .HRESETn, .HSELSDC, .HADDR(HADDR[4:0]), .HWRITE, .HREADY, .HTRANS, + .HWDATA, .HREADSDC, .HRESPSDC, .HREADYSDC, + // sdc interface + .SDCCmdOut, .SDCCmdIn, .SDCCmdOE, .SDCDatIn, .SDCCLK, + // interrupt to PLIC + .SDCIntM + ); + end else begin : uart + assign UARTSout = 0; assign UARTIntr = 0; + end endgenerate // mux could also include external memory @@ -124,22 +141,25 @@ module uncore ( ({`XLEN{HSELPLICD}} & HREADPLIC) | ({`XLEN{HSELGPIOD}} & HREADGPIO) | ({`XLEN{HSELBootTimD}} & HREADBootTim) | - ({`XLEN{HSELUARTD}} & HREADUART); + ({`XLEN{HSELUARTD}} & HREADUART) | + ({`XLEN{HSELSDC}} & HREADSDC); assign HRESP = HSELTimD & HRESPTim | HSELCLINTD & HRESPCLINT | HSELPLICD & HRESPPLIC | HSELGPIOD & HRESPGPIO | HSELBootTimD & HRESPBootTim | - HSELUARTD & HRESPUART; + HSELUARTD & HRESPUART | + HSELSDC & HRESPSDC; assign HREADY = HSELTimD & HREADYTim | HSELCLINTD & HREADYCLINT | HSELPLICD & HREADYPLIC | HSELGPIOD & HREADYGPIO | HSELBootTimD & HREADYBootTim | HSELUARTD & HREADYUART | + HSELSDCD & HREADYSDC | HSELNoneD; // don't lock up the bus if no region is being accessed // Address Decoder Delay (figure 4-2 in spec) - flopr #(7) hseldelayreg(HCLK, ~HRESETn, HSELRegions, {HSELNoneD, HSELBootTimD, HSELTimD, HSELCLINTD, HSELGPIOD, HSELUARTD, HSELPLICD}); + flopr #(8) hseldelayreg(HCLK, ~HRESETn, HSELRegions, {HSELNoneD, HSELBootTimD, HSELTimD, HSELCLINTD, HSELGPIOD, HSELUARTD, HSELPLICD, HSELSDCD}); endmodule diff --git a/wally-pipelined/src/wally/wallypipelinedsoc.sv b/wally-pipelined/src/wally/wallypipelinedsoc.sv index c85f5d4f4..dec2bc867 100644 --- a/wally-pipelined/src/wally/wallypipelinedsoc.sv +++ b/wally-pipelined/src/wally/wallypipelinedsoc.sv @@ -51,7 +51,10 @@ module wallypipelinedsoc ( input logic [31:0] GPIOPinsIn, output logic [31:0] GPIOPinsOut, GPIOPinsEn, input logic UARTSin, - output logic UARTSout + output logic UARTSout, + output tri1 SDCCmd, + input logic [3:0] SDCDat, + output logic SDCCLK ); // to instruction memory *** remove later @@ -70,6 +73,17 @@ module wallypipelinedsoc ( logic HWRITED; logic [15:0] rd2; // bogus, delete when real multicycle fetch works logic [31:0] InstrF; + + logic SDCCmdOut; + logic SDCCmdOE; + logic SDCCmdIn; + logic [3:0] SDCDatIn; + + assign SDCCmd = SDCCmdOE ? SDCCmdOut : 1'bz; + assign SDCCmdIn = SDCCmd; + assign SDCDatIn = SDCDat; // when write supported this will be a tristate + + // instantiate processor and memories wallypipelinedhart hart(.*); @@ -77,4 +91,4 @@ module wallypipelinedsoc ( // instructions now come from uncore memory. This line can be removed at any time. // imem imem(.AdrF(PCF[`XLEN-1:1]), .*); // temporary until uncore memory is finished*** uncore uncore(.HWDATAIN(HWDATA), .*); -endmodule \ No newline at end of file +endmodule