mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
SDC to ABHLite interface partially done.
Added SDC to adrdec and uncore.
This commit is contained in:
parent
a182263b1c
commit
4256ef82b1
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user