From 9ed7a1f494cdd5da8174b550323995b5e5539371 Mon Sep 17 00:00:00 2001 From: Ross Thompson Date: Thu, 23 Sep 2021 17:45:45 -0500 Subject: [PATCH] Partial implementation of SDC AHBLite interface. --- wally-pipelined/src/sdc/SDC.sv | 151 +++++++++++++++++++++++++++++++-- 1 file changed, 144 insertions(+), 7 deletions(-) diff --git a/wally-pipelined/src/sdc/SDC.sv b/wally-pipelined/src/sdc/SDC.sv index 6912c0ab7..773f63042 100644 --- a/wally-pipelined/src/sdc/SDC.sv +++ b/wally-pipelined/src/sdc/SDC.sv @@ -55,9 +55,27 @@ module SDC logic initTrans; logic RegRead; logic RegWrite; + logic [4:0] HADDRDelay; - // *** reduce size later + + // Register outputs logic [31:0] CLKDiv; + logic [2:0] Command; + logic [`XLEN-1:9] Address; + + + logic SDCDone; + + logic [2:0] ErrorCode; + logic InvalidCommand; + logic Done; + logic Busy; + + logic StartCLKDivUpdate; + logic CLKDivUpdateEn; + logic SDCLKEN; + + // registers @@ -68,7 +86,24 @@ module SDC //| 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 | + //| 0x18 | data | 8 | Data Bus interface | + + // Status contains + // Status[0] busy + // Status[1] done + // Status[2] invalid command + // Status[5:3] error code + + // control contains 3 bit command + // control[2:0] + // 000 nop op + // xx1 initialize + // 010 Write no implemented + // 100 Read + // 110 Atomic read/write not implemented + + // size is fixed to 512. Read only + // Currently using a mailbox style interface. Data is passed through the Data register (0x10) // The card will support 3 operations @@ -81,12 +116,114 @@ module SDC // currently does not support writes - assign InitTrans = HREADY & HSELTSDC & (HTRANS != 2'b00); - assign RegWrite = InitTrans & HWRITE; - assign RegRead = InitTrans & ~HWRITE; + assign InitTrans = HREADY & HSELSDC & (HTRANS != 2'b00); + assign RegRead = InitTrans & ~HWRITE; + // AHBLite Spec has write data 1 cycle after write command + flopr #(1) RegWriteReg(HCLK, ~HRESETn, InitTrans & HWRITE, RegWrite); + + flopr #(5) HADDRReg(HCLK, ~HRESETn, HADDR, HADDRDelay); + + assign StartCLKDivUpdate = HADDRDelay == '0 & RegWrite; + + flopenl #(32) CLKDivReg(HCLK, ~HRESETn, CLKDivUpdateEn, HWDATA[31:0], `SDCCLKDIV, CLKDiv); - // *** need to delay - flopenl #(32) CLKDivReg(HCLK, ~HRESETn, , HADDR == '0 & RegWrite, HWRITE, `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); + + 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 = {32'b0, CLKDiv}; + 'h4: HREADSDC = {`XLEN-6'b0, ErrorCode, InvalidCommand, Done, Busy}; + 'h8: HREADSDC = {`XLEN-3'b0, Command}; + 'hC: HREADSDC = 'h200; + 'h10: HREADSDC = Address; + 'h18: HREADSDC = ReadData; + default: HREADSDC = {32'b0, CLKDiv}; + endcase + end else begin + always_comb + case(HADDRDelay[4:2]) + 'h0: HREADSDC = CLKDiv; + 'h4: HREADSDC = {ErrorCode, InvalidCommand, Done, Busy}; + 'h8: HREADSDC = Command; + 'hC: HREADSDC = 'h200; + 'h10: HREADSDC = Address[31:0]; + 'h14: HREADSDC = Address[63:32]; + 'h18: HREADSDC = ReadData[31:0]; + 'h1C: HREADSDC = ReadData[63:32]; + default: HREADSDC = CLKDiv; + endcase + end + endgenerate + + typedef enum {STATE_READY, + + // clock update states + STATE_CLK_DIV1, + STATE_CLK_DIV2, + STATE_CLK_DIV3, + STATE_CLK_DIV4, + + // restart SDC + STATE_RESTART, + + // SDC operation + STATE_PROCESS_CMD + } statetype; + + + statetype CurrState, NextState; + + always_ff @(posedge HCLK, posedge ~HRESETn) + if (~HRESETn) CurrState <= #1 STATE_READY; + else CurrState <= #1 NextState; + + always_comb begin + CLKDivUpdateEn = 1'b0; + HREADYSDC = 1'b0; + SDCLKEN = 1'b1; + case (CurrState) + + STATE_READY : begin + if (StartCLKDivUpdate)begin + NextState = STATE_CLK_DIV1; + HREADYSDC = 1'b0; +/* -----\/----- EXCLUDED -----\/----- + end else if () begin + -----/\----- EXCLUDED -----/\----- */ + + end else begin + NextState = STATE_READY; + HREADYSDC = 1'b1; + end + end + STATE_CLK_DIV1: begin + NextState = STATE_CLK_DIV2; + SDCLKEN = 1'b0; + end + STATE_CLK_DIV2: begin + NextState = STATE_CLK_DIV3; + CLKDivUpdateEn = 1'b1; + SDCLKEN = 1'b0; + end + STATE_CLK_DIV3: begin + NextState = STATE_CLK_DIV4; + SDCLKEN = 1'b0; + end + STATE_CLK_DIV4: begin + NextState = STATE_READY; + end + endcase + end endmodule