SDC to ABHLite interface partially done.

Added SDC to adrdec and uncore.
This commit is contained in:
Ross Thompson 2021-09-24 10:45:09 -05:00
parent a182263b1c
commit 4256ef82b1
8 changed files with 120 additions and 66 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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));

View File

@ -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;

View File

@ -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

View File

@ -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
endmodule