xref: /XiangShan/src/main/scala/device/AXI4DummySD.scala (revision dc597826530cb6803c2396d6ab0e5eb176b732e0)
1/***************************************************************************************
2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3* Copyright (c) 2020-2021 Peng Cheng Laboratory
4*
5* XiangShan is licensed under Mulan PSL v2.
6* You can use this software according to the terms and conditions of the Mulan PSL v2.
7* You may obtain a copy of Mulan PSL v2 at:
8*          http://license.coscl.org.cn/MulanPSL2
9*
10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*
14* See the Mulan PSL v2 for more details.
15***************************************************************************************/
16
17package device
18
19import chipsalliance.rocketchip.config.Parameters
20import chisel3._
21import chisel3.util._
22import Chisel.BlackBox
23import freechips.rocketchip.diplomacy.AddressSet
24import utils._
25
26trait HasSDConst {
27  def MemorySize = 4L * 1024 * 1024 * 1024 // 4GB
28  def READ_BL_LEN = 15
29
30  def BlockLen = (1 << READ_BL_LEN)
31
32  def NrBlock = MemorySize / BlockLen
33
34  def C_SIZE_MULT = 7 // only 3 bits
35  def MULT = (1 << (C_SIZE_MULT + 2))
36
37  def C_SIZE = NrBlock / MULT - 1
38}
39
40class SDHelper extends BlackBox with HasBlackBoxInline {
41  val io = IO(new Bundle {
42    val clk = Input(Clock())
43    val ren = Input(Bool())
44    val data = Output(UInt(32.W))
45    val setAddr = Input(Bool())
46    val addr = Input(UInt(32.W))
47  })
48
49  setInline("SDHelper.v",
50    s"""
51       |import "DPI-C" function void sd_setaddr(input int addr);
52       |import "DPI-C" function void sd_read(output int data);
53       |
54       |module SDHelper (
55       |  input clk,
56       |  input setAddr,
57       |  input [31:0] addr,
58       |  input ren,
59       |  output reg [31:0] data
60       |);
61       |
62       |  always @(negedge clk) begin
63       |    if (ren) sd_read(data);
64       |  end
65       |  always@(posedge clk) begin
66       |    if (setAddr) sd_setaddr(addr);
67       |  end
68       |
69       |endmodule
70     """.stripMargin)
71}
72
73class AXI4DummySD
74(
75  address: Seq[AddressSet]
76)(implicit p: Parameters)
77  extends AXI4SlaveModule(address, executable = false) with HasSDConst
78{
79  override lazy val module = new AXI4SlaveModuleImp[Null](this) {
80    val range = List.range(0, 21)
81    val sdcmd :: sdarg :: sdtout :: sdcdiv :: sdrsp0 :: sdrsp1 :: sdrsp2 :: sdrsp3 :: sdhsts :: __pad0 :: __pad1 :: __pad2 :: sdvdd :: sdedm :: sdhcfg :: sdhbct :: sddata :: __pad10 :: __pad11 :: __pad12 :: sdhblc :: Nil = range
82
83    val regs = List.fill(range.size)(RegInit(0.U(32.W)))
84    val edmConst = (8 << 4).U // number of data in fifo
85
86    val MMC_SEND_OP_COND = 1
87    val MMC_ALL_SEND_CID = 2
88    val MMC_SEND_CSD = 9
89    val MMC_SEND_STATUS = 13
90    val MMC_READ_MULTIPLE_BLOCK = 18
91
92    val setAddr = WireInit(false.B)
93
94    def cmdWfn(wdata: UInt) = {
95      val cmd = wdata(5, 0)
96      switch(cmd) {
97        is(MMC_SEND_OP_COND.U) {
98          regs(sdrsp0) := "h80ff8000".U
99        }
100        is(MMC_ALL_SEND_CID.U) {
101          regs(sdrsp0) := "h00000001".U
102          regs(sdrsp1) := "h00000000".U
103          regs(sdrsp2) := "h00000000".U
104          regs(sdrsp3) := "h15000000".U
105        }
106        is(MMC_SEND_CSD.U) {
107          regs(sdrsp0) := "h92404001".U
108          regs(sdrsp1) := "h124b97e3".U | (C_SIZE.U(1, 0) << 30)
109          regs(sdrsp2) := "h0f508000".U | C_SIZE.U(11, 2) | (READ_BL_LEN.U << 16)
110          regs(sdrsp3) := "h8c26012a".U
111        }
112        is(MMC_SEND_STATUS.U) {
113          regs(sdrsp0) := 0.U
114          regs(sdrsp1) := 0.U
115          regs(sdrsp2) := 0.U
116          regs(sdrsp3) := 0.U
117        }
118        is(MMC_READ_MULTIPLE_BLOCK.U) {
119          setAddr := true.B
120        }
121      }
122      wdata
123    }
124
125    val sdHelper = Module(new SDHelper)
126    sdHelper.io.clk := clock
127    sdHelper.io.ren := (getOffset(raddr) === 0x40.U && in.ar.fire())
128    sdHelper.io.setAddr := setAddr
129    sdHelper.io.addr := regs(sdarg)
130
131    def sdRead = sdHelper.io.data
132
133    val mapping = Map(
134      RegMap(0x00, regs(sdcmd), cmdWfn),
135      RegMap(0x04, regs(sdarg)),
136      RegMap(0x10, regs(sdrsp0), RegMap.Unwritable),
137      RegMap(0x14, regs(sdrsp1), RegMap.Unwritable),
138      RegMap(0x18, regs(sdrsp2), RegMap.Unwritable),
139      RegMap(0x1c, regs(sdrsp3), RegMap.Unwritable),
140      RegMap(0x20, regs(sdhsts)),
141      RegMap(0x34, edmConst, RegMap.Unwritable),
142      RegMap(0x38, regs(sdhcfg)),
143      RegMap(0x38, regs(sdhbct)),
144      RegMap(0x40, sdRead, RegMap.Unwritable),
145      RegMap(0x50, regs(sdhblc))
146    )
147
148    def getOffset(addr: UInt) = addr(12, 0)
149
150    val strb = Mux(waddr(2), in.w.bits.strb(7, 4), in.w.bits.strb(3, 0))
151    val rdata = Wire(UInt(64.W))
152    RegMap.generate(mapping, getOffset(raddr), rdata,
153      getOffset(waddr), in.w.fire(), in.w.bits.data, MaskExpand(strb))
154
155    in.r.bits.data := Fill(2, rdata(31, 0))
156  }
157}
158