在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
芯片精品文章合集(500篇!) 创芯人才网--重磅上线啦!
查看: 801|回复: 10

[求助] 急!!!请问有大佬了解怎么通过汇编指令集推测硬件功能吗?

[复制链接]
发表于 2024-8-20 14:54:58 | 显示全部楼层 |阅读模式
99资产
目前有指令集的文本,根据技术手册能理解每条汇编指令,但不知道如何推测硬件功能,翻译了汇编指令,也尝试画流程图理解,但效果较小,汇编指令中会常出现对某个通用寄存器的某一位赋值,但我并不了解该通用寄存器的作用,或是根据通用寄存器某一位的值进行跳转,请问有大佬指点一下方向吗?

发表于 2024-8-20 15:09:10 | 显示全部楼层
通用寄存器一般只是存储中间结果
还有另外一个方向:用专门的破解软件把汇编转成c语言代码
发表于 2024-8-20 17:06:54 | 显示全部楼层
访问的是通用寄存器还是特殊寄存器,通用寄存器就是暂存的,特殊功能寄存器得看手册了,抛开手册,单看汇编代码,那几乎是不可能理解含义的
发表于 2024-8-20 19:04:26 | 显示全部楼层
本帖最后由 轩辕志瑜 于 2024-8-20 19:58 编辑

找些开源cpu的rtl代码和讲解cpu芯片开发的视频看看。

https://github.com/darklife/darkriscv 这个项目举个例子:

config.vh(参数配置定义文件)




  1. /*
  2. * Copyright (c) 2018, Marcelo Samsoniuk
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright notice, this
  9. *   list of conditions and the following disclaimer.
  10. *
  11. * * Redistributions in binary form must reproduce the above copyright notice,
  12. *   this list of conditions and the following disclaimer in the documentation
  13. *   and/or other materials provided with the distribution.
  14. *
  15. * * Neither the name of the copyright holder nor the names of its
  16. *   contributors may be used to endorse or promote products derived from
  17. *   this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  20. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  23. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  25. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  26. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  27. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */

  30. //`timescale 1ns / 1ps

  31. // to port to a new board, use TESTMODE to test:
  32. // - the reset button is working
  33. // - the LED is blinking at 1Hz
  34. // - the UART is looped
  35. //`define __TESTMODE__

  36. ////////////////////////////////////////////////////////////////////////////////
  37. // darkriscv configuration
  38. ////////////////////////////////////////////////////////////////////////////////

  39. // pipeline stages:
  40. //
  41. // 2-stage version: core and memory in different clock edges result in less
  42. // clock performance, but less losses when the program counter changes
  43. // (pipeline flush = 1 clock).  Works like a 4-stage pipeline and remember
  44. // the 68040 clock scheme, with instruction per clock = 1.  alternatively,
  45. // it is possible work w/ 1 wait-state and 1 clock edge, but with a penalty
  46. // in performance (instruction per clock = 0.5).
  47. //
  48. // 3-stage version: core and memory in the same clock edge require one extra
  49. // stage in the pipeline, but keep a good performance most of time
  50. // (instruction per clock = 1).  of course, read operations require 1
  51. // wait-state, which means sometimes the read performance is reduced.
  52. `define __3STAGE__

  53. // RV32I vs RV32E:
  54. //
  55. // The difference between the RV32I and RV32E regarding the logic space is
  56. // minimal in typical applications with modern 5 or 6 input LUT based FPGAs,
  57. // but the RV32E is better with old 4 input LUT based FPGAs.
  58. `define __RV32E__

  59. // muti-threading support:
  60. //
  61. // Decreases clock performance by 20% (80MHz), but enables two or more
  62. // contexts (threads) in the core. The threads work in symmetrical way,
  63. // which means that they will start with the same exactly core parameters
  64. // (same initial PC, same initial SP, etc). The boot.s code is designed
  65. // to handle this difference and set each thread to different
  66. // applications.
  67. // Notes:
  68. // a) threading is currently supported only in the 3-stage pipeline version.
  69. // b) the old experimental "interrupt mode" was removed, which means that
  70. //    the multi-thread mode does not make anything "visible" other than
  71. //    increment the gpio register.
  72. // c) the threading in the non-interrupt mode switches when the program flow
  73. //    changes, i.e. every jal instruction. When the core is idle, it is
  74. //    probably in a jal loop.
  75. // The number of threads must be 2**n (i.e. THREADS = 3 means 8 threads)
  76. //`define __THREADS__ 3

  77. // mac instruction:
  78. //
  79. // The mac instruction is similar to other register to register
  80. // instructions, but with a different opcode 7'h1111111.  the format is mac
  81. // rd,r1,r2, but is not currently possible encode in asm, by this way it is
  82. // available in licb as int mac(int rd, short r1, short r2).  Although it
  83. // can be used to accelerate the mul/div operations, the mac operation is
  84. // designed for DSP applications.  with some effort (low level machine
  85. // code), it is possible peak 100MMAC/s @100MHz.
  86. //`define __MAC16X16__

  87. // interrupt support
  88. //
  89. // The interrupt support in the core uses the machine registers mtvec and
  90. // mepc, which means support the control special register instruction csrrw,
  91. // in a way that is possible read/write the mtvec and mepc.
  92. // the interrupt itself works like the thread switch, with the difference
  93. // that:
  94. // a) the PC will be saved in the mepc register
  95. // b)the PC will receive the mtvec value
  96. // c) single interrupt, which means that the mtvec offset is always zero
  97. // The interrupt support cannot be used with threading (because makes no
  98. // much sense?)... also, it requires the 3 stage pipeline (again, makes no
  99. // much sense use it with the 2-stage pipeline).
  100. //`define __INTERRUPT__

  101. // ebreak support
  102. //
  103. // ebreak enable live debug w/ gdb, with break points, single-step, etc...
  104. // it basically consists in a single instruction that replace the normal
  105. // instruction, so an exception will be triggered, which is like an interrupt,
  106. // but with no real interrupt source.
  107. //`define __EBREAK__

  108. // CSR support
  109. //
  110. // enable this to use CSR registers...  INTERRUPT and EBREAK use this in
  111. // order to read some special exception registers.  Also, THREADS use this in
  112. // order to identify the core number.  
  113. //`define __CSR__

  114. // instruction trace:
  115. //
  116. // prints the PC, the respective instruction and some useful information,
  117. // skipping halt and flush, in order to track the instruction execution
  118. // sequence.  traces are very useful to debug, since is possible dump the
  119. // traces from a working core in order to debug a non-working core.  when
  120. // trace is enabled, the UART print is blocked, also, the trace does not
  121. // dump data when the core is in reset.
  122. // the trace file is stored on "sim/darksocv.txt"
  123. //`define __TRACE__
  124. //`define __TRACEFULL__

  125. // performance measurement:
  126. //
  127. // The performance measurement can be done in the simulation level by
  128. // eabling the __PERFMETER__ define, in order to check how the clock cycles
  129. // are used in the core. The report is displayed when the FINISH_REQ signal
  130. // is actived by the UART.
  131. // the performance counters does not count when the core is in reset.
  132. `define __PERFMETER__

  133. // initial PC
  134. //
  135. // Typically, the PC is set [by HW] to address 0, representing the start of
  136. // ROM memory and the SP is set [by SW] to the final of RAM memory.  In the
  137. // linker, the start of ROM memory matches with the .text area, which is
  138. // defined in the boot.c code and the start of RAM memory matches with the
  139. // .data and other volatile data, in a way that the stack can be positioned
  140. // in the top of RAM and does not match with the .data.
  141. `define __RESETPC__ 32'd0

  142. ////////////////////////////////////////////////////////////////////////////////
  143. // darksocv configuration:
  144. ////////////////////////////////////////////////////////////////////////////////

  145. // harvard architecture
  146. //
  147. // darkriscv core is *always* harvard, but it possible multiplex the instr.
  148. // and data buses over the time on the SoC level, in a way that it mimics a
  149. // classic von neumann architecture, which is useful for single-port memory,
  150. // such as SDRAMs, PSRAM, etc. when multiplexed, the instruction fetch turns
  151. // to be very slow, so caches are essential with this scenario!
  152. //`define __HARVARD__

  153. // cache depth
  154. //
  155. // when enabled, the caches will try map and store the read operations, in a
  156. // way that future read operations in the same address will be faster! it is
  157. // specially applicable to non-harvard SoC configuration, since that the
  158. // harvard SoC configuration is faster than the cache!
  159. // the cache depth N means that the each cache will be 32-bit x 2^N
  160. `define __LUTCACHE__
  161. `define __CDEPTH__ 6
  162. `define __ICACHE__
  163. `define __DCACHE__

  164. // interactive simulation:
  165. //
  166. // When enabled, will trick the simulator in order to enable interactive
  167. // access via the stdin, in a way that is possible type interactive commands,
  168. // which will make your simulator crazy! unfortunately, it works only with
  169. // iverilog... at least, Xilinx ISIM does not liket the $fgetc()
  170. //`define __INTERACTIVE__

  171. // icarus register debug:
  172. //
  173. // As most people observed, the icarus verilog does not dump the register
  174. // bank because icarus does not dump arrays by default. However, it is possible
  175. // activate this special option in order to dump the register bank. This
  176. // makes no effect in other simulators, but it appears as a warning.
  177. //`define __REGDUMP__

  178. // memory size:
  179. //
  180. // The current test firmware requires 8KB of memory, but it depends of the
  181. // memory layout: whenthe I-bus and D-bus are both attached in the same BRAM,
  182. // it is possible assume that 8kB is enough, but when the I-bus and D-bus are
  183. // attached to separate memories, the I-BRAM requires around 5KB and the
  184. // D-BRAM requires about 1.5KB. A safe solution is just simply and set the
  185. // size as the same.
  186. // The size is defined as 2**MLEN, i.e. the address bits used in the memory.
  187. // WARNING: this setup must match with the src/darksocv.ld.src file!
  188. `define MLEN 15 // MEM[14:0] -> 32KBytes LENGTH = 0x8000 for coremark!

  189. // read-modify-write cycle:
  190. //
  191. // Generate RMW cycles when writing in the memory. This option basically
  192. // makes the read and write cycle symmetric and may work better in the cases
  193. // when the 32-bit memory does not support separate write enables for
  194. // separate 16-bit and 8-bit words. Typically, the RMW cycle results in a
  195. // decrease of 5% in the performance (not the clock, but the instruction
  196. // pipeline eficiency) due to memory wait-states.
  197. //`define __RMW_CYCLE__

  198. // bram wait states
  199. //
  200. // to simulate high latency memories, is possible set the number of wait-states
  201. // for bram here! case not configured, wait-states defaults to 1.
  202. //`define __WAITSTATE__ 3

  203. // UART speed is set in bits per second, typically 115200 bps:
  204. //`define __UARTSPEED__ 115200

  205. // UART queue:
  206. //
  207. // Optional RX/TX queue for communication oriented applications. The concept
  208. // foreseen 256 bytes for TX and RX, in a way that frames up to 128 bytes can
  209. // be easily exchanged via UART.
  210. //`define __UARTQUEUE__

  211. ////////////////////////////////////////////////////////////////////////////////
  212. // board definition:
  213. ////////////////////////////////////////////////////////////////////////////////

  214. // The board is automatically defined in the xst/xise files via Makefile or
  215. // ISE. Case it is not the case, please define you board name here:
  216. //`define AVNET_MICROBOARD_LX9
  217. //`define XILINX_AC701_A200
  218. //`define QMTECH_SDRAM_LX16

  219. // the following defines are automatically defined:

  220. `ifdef __ICARUS__
  221.     `define SIMULATION 1
  222. `endif

  223. `ifdef XILINX_ISIM
  224.     `define SIMULATION 2
  225. `endif

  226. `ifdef MODEL_TECH
  227.     `define SIMULATION 3
  228. `endif

  229. `ifdef XILINX_SIMULATOR
  230.     `define SIMULATION 4
  231. `endif

  232. // the board definition is done on the tool, otherwise we assume simulation

  233. `ifdef AVNET_MICROBOARD_LX9
  234.     `define BOARD_ID 1
  235.     //`define BOARD_CK 100000000
  236.     //`define BOARD_CK 66666666
  237.     //`define BOARD_CK 40000000
  238.     // example of DCM logic:
  239.     `define BOARD_CK_REF 100000000
  240.     `define BOARD_CK_MUL 6
  241.     `ifdef __3STAGE__
  242.         `define BOARD_CK_DIV 6 // 3-stage, 1-ws, 9=66MHz 6=100MHz
  243.     `else
  244.         `define BOARD_CK_DIV 9 // 2-stage, 1-ws, 9=66MHz 6=100MHz
  245.     `endif
  246.     `define XILINX6CLK 1
  247. `endif

  248. `ifdef XILINX_AC701_A200
  249.     `define BOARD_ID 2
  250.     //`define BOARD_CK 90000000
  251.     `define BOARD_CK_REF 90000000
  252.     `define BOARD_CK_MUL 4
  253.     `define BOARD_CK_DIV 2
  254. `endif

  255. `ifdef QMTECH_SDRAM_LX16
  256.     `define BOARD_ID 3
  257.     `define BOARD_CK_REF 50000000
  258.     `define BOARD_CK_MUL 4
  259.     `define BOARD_CK_DIV 2
  260.     `define INVRES 1
  261.     `define XILINX6CLK 1
  262. `endif

  263. `ifdef QMTECH_SPARTAN7_S15
  264.     `define BOARD_ID 4
  265.     `define BOARD_CK_REF 50000000
  266.     `define BOARD_CK_MUL 20
  267.     `define BOARD_CK_DIV 10
  268.     `define XILINX7CLK 1
  269.     `define VIVADO 1
  270.     `define INVRES 1
  271. `endif

  272. `ifdef LATTICE_BREVIA2_XP2
  273.     `define BOARD_ID 5
  274.     `define BOARD_CK 50000000
  275.     `define INVRES 1
  276. `endif

  277. `ifdef LATTICE_ECP5_COLORLIGHTI9
  278.     `define LATTICE_ECP5_PLL_REF25MHZ 1
  279.     `define BOARD_ID 14
  280.     `define BOARD_CK 125_000_000 // cause we use a pll with 25MHz ref clks
  281.     `define INVRES 1
  282. `endif

  283. `ifdef LATTICE_ECP5_COLORLIGHTI5
  284.     `define LATTICE_ECP5_PLL_REF25MHZ 1
  285.     `define BOARD_ID 15
  286.     `define BOARD_CK 125_000_000 // cause we use a pll with 25MHz ref clks
  287.     `define INVRES 1
  288. `endif

  289. `ifdef LATTICE_ECP5_ULX3S
  290.     `define LATTICE_ECP5_PLL_REF25MHZ 1
  291.     `define BOARD_ID 16
  292.     `define BOARD_CK 125_000_000 // cause we use a pll with 25MHz ref clks
  293.     `define INVRES 1
  294. `endif

  295. `ifdef LATTICE_ICE40_BREAKOUT_HX8K
  296.     `define BOARD_ID 17
  297.     `define BOARD_CK 65_000_000 // cause we use a pll with 25MHz ref clks
  298.     `define INVRES 1
  299. `endif


  300. `ifdef PISWORDS_RS485_LX9
  301.     `define BOARD_ID 6
  302.     `define BOARD_CK_REF 50000000
  303.     `define BOARD_CK_MUL 4
  304.     `define BOARD_CK_DIV 2
  305.     `define INVRES 1
  306.     `define XILINX6CLK 1
  307. `endif

  308. `ifdef DIGILENT_SPARTAN3_S200
  309.     `define BOARD_ID 7
  310.     `define BOARD_CK 50000000
  311.     `define __RMW_CYCLE__
  312. `endif

  313. `ifdef ALIEXPRESS_HPC40GBE_K420
  314.     `define BOARD_ID 8
  315.     //`define BOARD_CK 200000000
  316.     `define BOARD_CK_REF 100000000
  317.     `define BOARD_CK_MUL 12
  318.     `define BOARD_CK_DIV 5
  319.     `define XILINX7CLK 1
  320.     `define INVRES 1
  321. `endif

  322. `ifdef QMTECH_ARTIX7_A35
  323.     `define BOARD_ID 9
  324.     `define BOARD_CK_REF 50000000
  325.     `define BOARD_CK_MUL 20
  326.     `define BOARD_CK_DIV 10
  327.     `define XILINX7CLK 1
  328.     `define VIVADO 1
  329.     `define INVRES 1
  330. `endif

  331. `ifdef ALIEXPRESS_HPC40GBE_XKCU040
  332.     `define BOARD_ID 10
  333.     //`define BOARD_CK 200000000
  334.     `define BOARD_CK_REF 100000000
  335.     `define BOARD_CK_MUL 8  // x8/2 = 400MHZ (overclock!)
  336.     `define BOARD_CK_DIV 2  // vivado reco. = 250MHz
  337.     `define XILINX7CLK 1
  338.     `define INVRES 1
  339. `endif

  340. `ifdef PAPILIO_DUO_LOGICSTART
  341.     `define BOARD_ID 11
  342.     `define BOARD_CK_REF 32000000
  343.     `define BOARD_CK_MUL 2
  344.     `define BOARD_CK_DIV 2
  345.     `define XILINX6CLK 1
  346. `endif

  347. `ifdef QMTECH_KINTEX7_K325
  348.     `define BOARD_ID 12
  349.     `define BOARD_CK_REF 50000000
  350.     `define BOARD_CK_MUL 20
  351.     `define BOARD_CK_DIV 4
  352.     `define XILINX7CLK 1
  353.     `define INVRES 1
  354. `endif

  355. `ifdef SCARAB_MINISPARTAN6_PLUS_LX9
  356.     `define BOARD_ID 13
  357.     `define BOARD_CK_REF 50000000
  358.     `define BOARD_CK_MUL 4
  359.     `define BOARD_CK_DIV 2
  360.     // `define INVRES 0
  361.     `define XILINX6CLK 1
  362. `endif

  363. `ifdef QMTECH_CYCLONE10_CL016
  364.     `define BOARD_ID 17
  365.     `define BOARD_CK 50000000
  366.          `define INVRES 1
  367.          `define MIFBRAM 1
  368.     `define __RMW_CYCLE__
  369. `endif

  370. `ifdef PISSWORDS_CH34X_LX16
  371.     `define BOARD_ID 18
  372.     `ifdef __3STAGE__
  373.         `define BOARD_CK_REF 50000000
  374.         `define BOARD_CK_MUL 4
  375.         `define BOARD_CK_DIV 2
  376.         `define XILINX6CLK 1
  377.     `else
  378.         `define BOARD_CK 50000000
  379.     `endif
  380.     `define INVRES 1   
  381.     `define __SDRAM__ 1
  382. `endif

  383. `ifndef BOARD_ID
  384.     `define BOARD_ID 0
  385.     `define BOARD_CK 100000000
  386.     //`define __SDRAM__ 1
  387. `endif

  388. `ifdef BOARD_CK_REF
  389.     `define BOARD_CK (`BOARD_CK_REF * `BOARD_CK_MUL / `BOARD_CK_DIV)
  390. `endif

  391. // darkuart baudrate automtically calculated according to board clock:

  392. `ifndef __UARTSPEED__
  393.   `define __UARTSPEED__ 115200
  394. `endif

  395. `define  __BAUD__ ((`BOARD_CK/`__UARTSPEED__))

  396. // register number depends of CPU type RV32[EI] and number of threads

  397. `ifdef __THREADS__

  398.     `ifdef __RV32E__
  399.         `define RLEN 16*(2**`__THREADS__)
  400.     `else
  401.         `define RLEN 32*(2**`__THREADS__)
  402.     `endif
  403.    
  404.     `define __CSR__
  405. `else
  406.     `ifdef __RV32E__
  407.         `define RLEN 16
  408.     `else
  409.         `define RLEN 32
  410.     `endif
  411. `endif

  412. `ifdef __INTERRUPT__
  413.     `define __CSR__
  414. `endif

  415. `ifdef __EBREAK__
  416.     `define __CSR__
  417. `endif


复制代码



darkriscv.v (CPU核心模块)




  1. /*
  2. * Copyright (c) 2018, Marcelo Samsoniuk
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright notice, this
  9. *   list of conditions and the following disclaimer.
  10. *
  11. * * Redistributions in binary form must reproduce the above copyright notice,
  12. *   this list of conditions and the following disclaimer in the documentation
  13. *   and/or other materials provided with the distribution.
  14. *
  15. * * Neither the name of the copyright holder nor the names of its
  16. *   contributors may be used to endorse or promote products derived from
  17. *   this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  20. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  23. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  25. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  26. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  27. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */

  30. `timescale 1ns / 1ps

  31. // implemented opcodes:

  32. `define LUI     7'b01101_11      // lui   rd,imm[31:12]
  33. `define AUIPC   7'b00101_11      // auipc rd,imm[31:12]
  34. `define JAL     7'b11011_11      // jal   rd,imm[xxxxx]
  35. `define JALR    7'b11001_11      // jalr  rd,rs1,imm[11:0]
  36. `define BCC     7'b11000_11      // bcc   rs1,rs2,imm[12:1]
  37. `define LCC     7'b00000_11      // lxx   rd,rs1,imm[11:0]
  38. `define SCC     7'b01000_11      // sxx   rs1,rs2,imm[11:0]
  39. `define MCC     7'b00100_11      // xxxi  rd,rs1,imm[11:0]
  40. `define RCC     7'b01100_11      // xxx   rd,rs1,rs2
  41. `define SYS     7'b11100_11      // exx, csrxx, mret

  42. // proprietary extension (custom-0)
  43. `define CUS     7'b00010_11      // cus   rd,rs1,rs2,fc3,fct5

  44. // not implemented opcodes:
  45. //`define FCC     7'b00011_11      // fencex


  46. // configuration file

  47. `include "../rtl/config.vh"

  48. module darkriscv
  49. #(
  50.     parameter CPTR = 0
  51. )
  52. (
  53.     input             CLK,   // clock
  54.     input             RES,   // reset
  55.     input             HLT,   // halt

  56. `ifdef __INTERRUPT__
  57.     input             IRQ,   // interrupt request
  58. `endif

  59.     input      [31:0] IDATA, // instruction data bus
  60.     output     [31:0] IADDR, // instruction addr bus

  61.     input      [31:0] DATAI, // data bus (input)
  62.     output     [31:0] DATAO, // data bus (output)
  63.     output     [31:0] DADDR, // addr bus

  64.     output     [ 2:0] DLEN, // data length
  65.     output            DRW,  // data read/write
  66.     output            DRD,  // data read
  67.     output            DWR,  // data write
  68.     output            DAS,  // address strobe
  69.    
  70. `ifdef SIMULATION
  71.     input             ESIMREQ,  // end simulation req
  72.     output reg        ESIMACK = 0,  // end simulation ack
  73. `endif

  74.     output [3:0]  DEBUG       // old-school osciloscope based debug! :)
  75. );

  76.     // dummy 32-bit words w/ all-0s and all-1s:

  77.     wire [31:0] ALL0  = 0;
  78.     wire [31:0] ALL1  = -1;

  79.     reg XRES = 1;

  80. `ifdef __THREADS__
  81.     reg [`__THREADS__-1:0] TPTR = 0;     // thread ptr
  82. `endif

  83.     // pipeline flow control on HLT!

  84.     reg        HLT2   = 0;
  85.     reg [31:0] IDATA2 = 0;

  86.     always@(posedge CLK)
  87.     begin
  88.         HLT2 <= HLT;
  89.         
  90.         if(HLT2^HLT) IDATA2 <= IDATA;   
  91.     end

  92.     wire[31:0] IDATAX = XRES ? 0 : HLT2 ? IDATA2 : IDATA;

  93.     // decode: IDATA is break apart as described in the RV32I specification

  94. `ifdef __3STAGE__

  95.     reg [31:0] XIDATA;

  96.     reg XLUI, XAUIPC, XJAL, XJALR, XBCC, XLCC, XSCC, XMCC, XRCC, XCUS, XSYS; //, XFCC, XSYS;

  97.     reg [31:0] XSIMM;
  98.     reg [31:0] XUIMM;

  99.     always@(posedge CLK)
  100.     begin
  101.         XIDATA <= HLT ? XIDATA : IDATAX;

  102.         XLUI   <= HLT ? XLUI   : IDATAX[6:0]==`LUI;
  103.         XAUIPC <= HLT ? XAUIPC : IDATAX[6:0]==`AUIPC;
  104.         XJAL   <= HLT ? XJAL   : IDATAX[6:0]==`JAL;
  105.         XJALR  <= HLT ? XJALR  : IDATAX[6:0]==`JALR;

  106.         XBCC   <= HLT ? XBCC   : IDATAX[6:0]==`BCC;
  107.         XLCC   <= HLT ? XLCC   : IDATAX[6:0]==`LCC;
  108.         XSCC   <= HLT ? XSCC   : IDATAX[6:0]==`SCC;
  109.         XMCC   <= HLT ? XMCC   : IDATAX[6:0]==`MCC;

  110.         XRCC   <= HLT ? XRCC   : IDATAX[6:0]==`RCC;
  111.         XCUS   <= HLT ? XRCC   : IDATAX[6:0]==`CUS;
  112.         //XFCC   <= HLT ? XFCC   : IDATAX[6:0]==`FCC;
  113.         XSYS   <= HLT ? XSYS   : IDATAX[6:0]==`SYS;

  114.         // signal extended immediate, according to the instruction type:

  115.         XSIMM  <= HLT ? XSIMM :
  116.                  IDATAX[6:0]==`SCC ? { IDATAX[31] ? ALL1[31:12]:ALL0[31:12], IDATAX[31:25],IDATAX[11:7] } : // s-type
  117.                  IDATAX[6:0]==`BCC ? { IDATAX[31] ? ALL1[31:13]:ALL0[31:13], IDATAX[31],IDATAX[7],IDATAX[30:25],IDATAX[11:8],ALL0[0] } : // b-type
  118.                  IDATAX[6:0]==`JAL ? { IDATAX[31] ? ALL1[31:21]:ALL0[31:21], IDATAX[31], IDATAX[19:12], IDATAX[20], IDATAX[30:21], ALL0[0] } : // j-type
  119.                  IDATAX[6:0]==`LUI||
  120.                  IDATAX[6:0]==`AUIPC ? { IDATAX[31:12], ALL0[11:0] } : // u-type
  121.                                       { IDATAX[31] ? ALL1[31:12]:ALL0[31:12], IDATAX[31:20] }; // i-type
  122.         // non-signal extended immediate, according to the instruction type:

  123.         XUIMM  <= HLT ? XUIMM :
  124.                  IDATAX[6:0]==`SCC ? { ALL0[31:12], IDATAX[31:25],IDATAX[11:7] } : // s-type
  125.                  IDATAX[6:0]==`BCC ? { ALL0[31:13], IDATAX[31],IDATAX[7],IDATAX[30:25],IDATAX[11:8],ALL0[0] } : // b-type
  126.                  IDATAX[6:0]==`JAL ? { ALL0[31:21], IDATAX[31], IDATAX[19:12], IDATAX[20], IDATAX[30:21], ALL0[0] } : // j-type
  127.                  IDATAX[6:0]==`LUI||
  128.                  IDATAX[6:0]==`AUIPC ? { IDATAX[31:12], ALL0[11:0] } : // u-type
  129.                                       { ALL0[31:12], IDATAX[31:20] }; // i-type
  130.     end

  131.     reg [1:0] FLUSH = -1;  // flush instruction pipeline

  132. `else

  133.     wire [31:0] XIDATA;

  134.     wire XLUI, XAUIPC, XJAL, XJALR, XBCC, XLCC, XSCC, XMCC, XRCC, XCUS, XSYS; //, XFCC, XSYS;

  135.     wire [31:0] XSIMM;
  136.     wire [31:0] XUIMM;

  137.     assign XIDATA = IDATAX;

  138.     assign XLUI   = IDATAX[6:0]==`LUI;
  139.     assign XAUIPC = IDATAX[6:0]==`AUIPC;
  140.     assign XJAL   = IDATAX[6:0]==`JAL;
  141.     assign XJALR  = IDATAX[6:0]==`JALR;

  142.     assign XBCC   = IDATAX[6:0]==`BCC;
  143.     assign XLCC   = IDATAX[6:0]==`LCC;
  144.     assign XSCC   = IDATAX[6:0]==`SCC;
  145.     assign XMCC   = IDATAX[6:0]==`MCC;

  146.     assign XRCC   = IDATAX[6:0]==`RCC;
  147.     assign XCUS   = IDATAX[6:0]==`CUS;
  148.     //assign XFCC   <= IDATAX[6:0]==`FCC;
  149.     assign XSYS   = IDATAX[6:0]==`SYS;

  150.     // signal extended immediate, according to the instruction type:

  151.     assign XSIMM  =
  152.                      IDATAX[6:0]==`SCC ? { IDATAX[31] ? ALL1[31:12]:ALL0[31:12], IDATAX[31:25],IDATAX[11:7] } : // s-type
  153.                      IDATAX[6:0]==`BCC ? { IDATAX[31] ? ALL1[31:13]:ALL0[31:13], IDATAX[31],IDATAX[7],IDATAX[30:25],IDATAX[11:8],ALL0[0] } : // b-type
  154.                      IDATAX[6:0]==`JAL ? { IDATAX[31] ? ALL1[31:21]:ALL0[31:21], IDATAX[31], IDATAX[19:12], IDATAX[20], IDATAX[30:21], ALL0[0] } : // j-type
  155.                      IDATAX[6:0]==`LUI||
  156.                      IDATAX[6:0]==`AUIPC ? { IDATAX[31:12], ALL0[11:0] } : // u-type
  157.                                           { IDATAX[31] ? ALL1[31:12]:ALL0[31:12], IDATAX[31:20] }; // i-type
  158.         // non-signal extended immediate, according to the instruction type:

  159.     assign XUIMM  =
  160.                      IDATAX[6:0]==`SCC ? { ALL0[31:12], IDATAX[31:25],IDATAX[11:7] } : // s-type
  161.                      IDATAX[6:0]==`BCC ? { ALL0[31:13], IDATAX[31],IDATAX[7],IDATAX[30:25],IDATAX[11:8],ALL0[0] } : // b-type
  162.                      IDATAX[6:0]==`JAL ? { ALL0[31:21], IDATAX[31], IDATAX[19:12], IDATAX[20], IDATAX[30:21], ALL0[0] } : // j-type
  163.                      IDATAX[6:0]==`LUI||
  164.                      IDATAX[6:0]==`AUIPC ? { IDATAX[31:12], ALL0[11:0] } : // u-type
  165.                                           { ALL0[31:12], IDATAX[31:20] }; // i-type

  166.     reg FLUSH = -1;  // flush instruction pipeline

  167. `endif

  168. `ifdef __THREADS__
  169.     `ifdef __RV32E__

  170.         reg [`__THREADS__-1:0] RESMODE = -1;

  171.         wire [`__THREADS__+3:0] DPTR   = XRES ? { RESMODE, 4'd0 } : { TPTR, XIDATA[10: 7] }; // set SP_RESET when RES==1
  172.         wire [`__THREADS__+3:0] S1PTR  = { TPTR, XIDATA[18:15] };
  173.         wire [`__THREADS__+3:0] S2PTR  = { TPTR, XIDATA[23:20] };
  174.     `else
  175.         reg [`__THREADS__-1:0] RESMODE = -1;

  176.         wire [`__THREADS__+4:0] DPTR   = XRES ? { RESMODE, 5'd0 } : { TPTR, XIDATA[11: 7] }; // set SP_RESET when RES==1
  177.         wire [`__THREADS__+4:0] S1PTR  = { TPTR, XIDATA[19:15] };
  178.         wire [`__THREADS__+4:0] S2PTR  = { TPTR, XIDATA[24:20] };
  179.     `endif
  180. `else
  181.     `ifdef __RV32E__
  182.         wire [3:0] DPTR   = XIDATA[10: 7]; // set SP_RESET when RES==1
  183.         wire [3:0] S1PTR  = XIDATA[18:15];
  184.         wire [3:0] S2PTR  = XIDATA[23:20];
  185.     `else
  186.         wire [4:0] DPTR   = XIDATA[11: 7]; // set SP_RESET when RES==1
  187.         wire [4:0] S1PTR  = XIDATA[19:15];
  188.         wire [4:0] S2PTR  = XIDATA[24:20];
  189.     `endif
  190. `endif

  191.     wire [6:0] OPCODE = FLUSH ? 0 : XIDATA[6:0];
  192.     wire [2:0] FCT3   = XIDATA[14:12];
  193.     wire [6:0] FCT7   = XIDATA[31:25];

  194.     wire [31:0] SIMM  = XSIMM;
  195.     wire [31:0] UIMM  = XUIMM;

  196.     // main opcode decoder:

  197.     wire    LUI = FLUSH ? 0 : XLUI;   // OPCODE==7'b0110111;
  198.     wire  AUIPC = FLUSH ? 0 : XAUIPC; // OPCODE==7'b0010111;
  199.     wire    JAL = FLUSH ? 0 : XJAL;   // OPCODE==7'b1101111;
  200.     wire   JALR = FLUSH ? 0 : XJALR;  // OPCODE==7'b1100111;

  201.     wire    BCC = FLUSH ? 0 : XBCC; // OPCODE==7'b1100011; //FCT3
  202.     wire    LCC = FLUSH ? 0 : XLCC; // OPCODE==7'b0000011; //FCT3
  203.     wire    SCC = FLUSH ? 0 : XSCC; // OPCODE==7'b0100011; //FCT3
  204.     wire    MCC = FLUSH ? 0 : XMCC; // OPCODE==7'b0010011; //FCT3

  205.     wire    RCC = FLUSH ? 0 : XRCC; // OPCODE==7'b0110011; //FCT3
  206.     wire    CUS = FLUSH ? 0 : XCUS; // OPCODE==7'b0110011; //FCT3
  207.     //wire    FCC = FLUSH ? 0 : XFCC; // OPCODE==7'b0001111; //FCT3
  208.     wire    SYS = FLUSH ? 0 : XSYS; // OPCODE==7'b1110011; //FCT3

  209. `ifdef __THREADS__
  210.     `ifdef __3STAGE__
  211.         reg [31:0] NXPC2 [0:(2**`__THREADS__)-1];       // 32-bit program counter t+2
  212.     `endif
  213. `else
  214.     `ifdef __3STAGE__
  215.         reg [31:0] NXPC2;       // 32-bit program counter t+2
  216.     `endif
  217. `endif

  218.     reg [31:0] REGS [0:`RLEN-1];        // general-purpose 32x32-bit registers (s1)

  219.     reg [31:0] NXPC;        // 32-bit program counter t+1
  220.     reg [31:0] PC;                    // 32-bit program counter t+0

  221. `ifdef SIMULATION
  222.     integer i;
  223.    
  224.     initial for(i=0;i!=`RLEN;i=i+1) REGS[i] = 0;
  225. `endif

  226.     // source-1 and source-1 register selection

  227.     wire          [31:0] U1REG = REGS[S1PTR];
  228.     wire          [31:0] U2REG = REGS[S2PTR];

  229.     wire signed   [31:0] S1REG = U1REG;
  230.     wire signed   [31:0] S2REG = U2REG;


  231.     // L-group of instructions (OPCODE==7'b0000011)

  232.     wire [31:0] LDATA = FCT3[1:0]==0 ? { FCT3[2]==0&&DATAI[ 7] ? ALL1[31: 8]:ALL0[31: 8] , DATAI[ 7: 0] } :
  233.                         FCT3[1:0]==1 ? { FCT3[2]==0&&DATAI[15] ? ALL1[31:16]:ALL0[31:16] , DATAI[15: 0] } :
  234.                                         DATAI;

  235.     // C-group: CSRRW

  236. `ifdef __CSR__

  237.     wire CSRX  = SYS && FCT3[1:0];

  238.     `ifdef __INTERRUPT__
  239.         reg [31:0] MSTATUS  = 0;
  240.         reg [31:0] MSCRATCH = 0;
  241.         reg [31:0] MCAUSE   = 0;
  242.         reg [31:0] MEPC     = 0;
  243.         reg [31:0] MTVEC    = 0;
  244.         reg [31:0] MIE      = 0;
  245.         reg [31:0] MIP      = 0;

  246.         wire MRET = SYS && FCT3==0 && XIDATA[31:20]==12'b001100000010;
  247.     `endif

  248.     `ifdef __EBREAK__
  249.         reg [31:0] SSTATUS  = 0;
  250.         reg [31:0] SSCRATCH = 0;
  251.         reg [31:0] SCAUSE   = 0;
  252.         reg [31:0] SEPC     = 0;
  253.         reg [31:0] STVEC    = 0;
  254.         reg [31:0] SIE      = 0;
  255.         reg [31:0] SIP      = 0;

  256.         wire EBRK = SYS && FCT3==0 && XIDATA[31:20]==12'b000000000001;
  257.         wire SRET = SYS && FCT3==0 && XIDATA[31:20]==12'b000100000010;
  258.     `endif

  259.     wire [31:0] CRDATA =
  260.     `ifdef __THREADS__   
  261.                         XIDATA[31:20]==12'hf14 ? { CPTR, TPTR } : // core/thread number
  262.     `else
  263.                         XIDATA[31:20]==12'hf14 ? CPTR  : // core number
  264.     `endif   
  265.     `ifdef __INTERRUPT__
  266.                         XIDATA[31:20]==12'h344 ? MIP      : // machine interrupt pending
  267.                         XIDATA[31:20]==12'h304 ? MIE      : // machine interrupt enable
  268.                         XIDATA[31:20]==12'h341 ? MEPC     : // machine exception PC
  269.                         XIDATA[31:20]==12'h342 ? MCAUSE   : // machine expection cause
  270.                         XIDATA[31:20]==12'h305 ? MTVEC    : // machine vector table
  271.                         XIDATA[31:20]==12'h300 ? MSTATUS  : // machine status
  272.                         XIDATA[31:20]==12'h340 ? MSCRATCH : // machine status
  273.     `endif
  274.     `ifdef __EBREAK__
  275.                         XIDATA[31:20]==12'h144 ? SIP      : // machine interrupt pending
  276.                         XIDATA[31:20]==12'h104 ? SIE      : // machine interrupt enable
  277.                         XIDATA[31:20]==12'h141 ? SEPC     : // machine exception PC
  278.                         XIDATA[31:20]==12'h142 ? SCAUSE   : // machine expection cause
  279.                         XIDATA[31:20]==12'h105 ? STVEC    : // machine vector table
  280.                         XIDATA[31:20]==12'h100 ? SSTATUS  : // machine status
  281.                         XIDATA[31:20]==12'h140 ? SSCRATCH : // machine status
  282.     `endif
  283.                                                  0;         // unknown

  284.     wire [31:0] WRDATA = FCT3[1:0]==3 ? (CRDATA & ~CRMASK) : FCT3[1:0]==2 ? (CRDATA | CRMASK) : CRMASK;
  285.     wire [31:0] CRMASK = FCT3[2] ? XIDATA[19:15] : U1REG;
  286.    
  287. `endif


  288.     // RM-group of instructions (OPCODEs==7'b0010011/7'b0110011), merged! src=immediate(M)/register(R)

  289.     wire signed [31:0] S2REGX = XMCC ? SIMM : S2REG;
  290.     wire        [31:0] U2REGX = XMCC ? UIMM : U2REG;

  291.     wire [31:0] RMDATA = FCT3==7 ? U1REG&S2REGX :
  292.                          FCT3==6 ? U1REG|S2REGX :
  293.                          FCT3==4 ? U1REG^S2REGX :
  294.                          FCT3==3 ? U1REG<U2REGX : // unsigned
  295.                          FCT3==2 ? S1REG<S2REGX : // signed
  296.                          FCT3==0 ? (XRCC&&FCT7[5] ? U1REG-S2REGX : U1REG+S2REGX) :
  297.                          FCT3==1 ? S1REG<<U2REGX[4:0] :
  298.                          //FCT3==5 ?
  299.                          !FCT7[5] ? S1REG>>U2REGX[4:0] :
  300. `ifdef MODEL_TECH
  301.                                    -((-S1REG)>>U2REGX[4:0]); // workaround for modelsim
  302. `else
  303.                                    $signed(S1REG)>>>U2REGX[4:0];  // (FCT7[5] ? U1REG>>>U2REG[4:0] :
  304. `endif

  305. `ifdef __MAC16X16__

  306.     // MAC instruction rd += s1*s2 (OPCODE==7'b1111111)
  307.     //
  308.     // 0000000 01100 01011 100 01100 0110011 xor a2,a1,a2
  309.     // 0000000 01010 01100 000 01010 0110011 add a0,a2,a0
  310.     // 0000000 01100 01011 000 01010 0001011 mac a0,a1,a2
  311.     //
  312.     // 0000 0000 1100 0101 1000 0101 0000 1011 = 00c5850b

  313.     wire MAC = CUS && FCT3==0;

  314.     wire signed [15:0] K1TMP = S1REG[15:0];
  315.     wire signed [15:0] K2TMP = S2REG[15:0];
  316.     wire signed [31:0] KDATA = K1TMP*K2TMP;

  317. `endif

  318.     // J/B-group of instructions (OPCODE==7'b1100011)

  319.     wire BMUX       = FCT3==7 && U1REG>=U2REG  || // bgeu
  320.                       FCT3==6 && U1REG< U2REGX || // bltu
  321.                       FCT3==5 && S1REG>=S2REG  || // bge
  322.                       FCT3==4 && S1REG< S2REGX || // blt
  323.                       FCT3==1 && U1REG!=U2REGX || // bne
  324.                       FCT3==0 && U1REG==U2REGX; // beq

  325.     wire [31:0] PCSIMM = PC+SIMM;
  326.     wire        JREQ = JAL||JALR||(BCC && BMUX);
  327.     wire [31:0] JVAL = JALR ? DADDR : PCSIMM; // SIMM + (JALR ? U1REG : PC);

  328.     always@(posedge CLK)
  329.     begin
  330. `ifdef __THREADS__
  331.         RESMODE <= RES ? -1 : RESMODE ? RESMODE-1 : 0;
  332.         XRES <= |RESMODE;
  333. `else
  334.         XRES <= RES;
  335. `endif

  336. `ifdef __3STAGE__
  337.             FLUSH <= XRES ? 2 : HLT ? FLUSH :        // reset and halt
  338.                                FLUSH ? FLUSH-1 :
  339.     `ifdef __EBREAK__
  340.                             EBRK ? 2 : // ebreak jmps to system level, i.e. sepc = PC; PC = stvec
  341.                             SRET ? 2 : // sret returns from system level, i.e. PC = sepc
  342.     `endif
  343.     `ifdef __INTERRUPT__
  344.                             MRET ? 2 : // mret returns from interrupt, i.e. PC = mepc
  345.     `endif

  346.                                JREQ ? 2 : 0;  // flush the pipeline!
  347. `else
  348.         FLUSH <= XRES ? 1 : HLT ? FLUSH :        // reset and halt
  349.                        JREQ;  // flush the pipeline!
  350. `endif

  351. `ifdef __INTERRUPT__

  352.     `ifdef __EBREAK__
  353.         MIP[11] <= IRQ&&MSTATUS[3]&&MIE[11]&&!SIP[1];
  354.     `else
  355.         MIP[11] <= IRQ&&MSTATUS[3]&&MIE[11];
  356.     `endif
  357.    
  358.         if(XRES)
  359.         begin
  360.             MTVEC    <= 0;
  361.             MEPC     <= 0;
  362.             MIE      <= 0;
  363.             MCAUSE   <= 0;
  364.             MSTATUS  <= 0;
  365.             MSCRATCH <= 0;
  366.         end
  367.         else
  368.         if(!HLT||!FLUSH)
  369.         begin
  370.             if(CSRX)
  371.             begin
  372.                 case(XIDATA[31:20])
  373.                     12'h300: MSTATUS  <= WRDATA;
  374.                     12'h340: MSCRATCH <= WRDATA;
  375.                     12'h305: MTVEC    <= WRDATA;
  376.                     12'h341: MEPC     <= WRDATA;
  377.                     12'h304: MIE      <= WRDATA;
  378.                 endcase
  379.             end
  380.             else
  381.             if(MIP[11] && JREQ)
  382.             begin
  383.                 MEPC   <= JVAL;             // interrupt saves the next PC!
  384.                 MSTATUS[3] <= 0;            // no interrupts when handling ebreak!
  385.                 MSTATUS[7] <= MSTATUS[3];   // copy old MIE bit
  386.                 MCAUSE <= 32'h8000000b;     // ext interrupt
  387.             end
  388.             else
  389.             if(MRET)
  390.             begin
  391.                 MSTATUS[3] <= MSTATUS[7]; // return last MIE bit
  392.             end
  393.         end
  394. `endif

  395. `ifdef __EBREAK__
  396.    
  397.         if(XRES)
  398.         begin
  399.             STVEC    <= 0;
  400.             SEPC     <= 0;
  401.             SIE      <= 0;
  402.             SIP      <= 0;
  403.             SCAUSE   <= 0;
  404.             SSTATUS  <= 0;
  405.             SSCRATCH <= 0;
  406.         end
  407.         else
  408.         if(!HLT||!FLUSH)
  409.         begin
  410.             if(EBRK) // ebreak cannot be blocked!
  411.             begin
  412.                 SEPC   <= PC;               // ebreak saves the current PC!
  413.                 SSTATUS[1] <= 0;            // no interrupts when handling ebreak!
  414.                 SSTATUS[5] <= SSTATUS[1];   // copy old MIE bit
  415.                 SCAUSE <= 32'h00000003;     // ebreak
  416.                 SIP[1] <= 1;                // set when ebreak!
  417.             end
  418.             else
  419.             if(CSRX)
  420.             begin
  421.                 case(XIDATA[31:20])
  422.                     12'h100: SSTATUS  <= WRDATA;
  423.                     12'h140: SSCRATCH <= WRDATA;
  424.                     12'h105: STVEC    <= WRDATA;
  425.                     12'h141: SEPC     <= WRDATA;
  426.                     12'h104: SIE      <= WRDATA;
  427.                 endcase
  428.             end
  429.             else
  430.             if(SRET)
  431.             begin
  432.                 SSTATUS[3] <= SSTATUS[7]; // return last MIE bit
  433.                 SIP[1] <= 0;              //return from ebreak
  434.             end
  435.         end
  436.         
  437. `endif

  438. `ifdef __RV32E__
  439.         REGS[DPTR] <=   XRES||DPTR[3:0]==0 ? 0  :        // reset x0
  440. `else
  441.         REGS[DPTR] <=   XRES||DPTR[4:0]==0 ? 0  :        // reset x0
  442. `endif
  443.                        HLT ? REGS[DPTR] :        // halt
  444.                        LCC ? LDATA :
  445.                      AUIPC ? PCSIMM :
  446.                       JAL||
  447.                       JALR ? NXPC :
  448.                        LUI ? SIMM :
  449.                   MCC||RCC ? RMDATA:

  450. `ifdef __MAC16X16__
  451.                        MAC ? REGS[DPTR]+KDATA :
  452. `endif
  453. `ifdef __CSR__
  454.                        CSRX ? CRDATA :
  455. `endif
  456.                              REGS[DPTR];

  457. `ifdef __3STAGE__

  458.     `ifdef __THREADS__

  459.         NXPC <= /*XRES ? `__RESETPC__ :*/ HLT ? NXPC : NXPC2[TPTR];

  460.         NXPC2[XRES ? RESMODE : TPTR] <=  XRES ? `__RESETPC__ : HLT ? NXPC2[TPTR] :   // reset and halt
  461.                                       JREQ ? JVAL :                            // jmp/bra
  462.                                                  NXPC2[TPTR]+4;                   // normal flow

  463.         TPTR <= XRES ? 0 : HLT ? TPTR :        // reset and halt
  464.                             JAL /*JREQ*/ ? TPTR+1 : TPTR;
  465.                      //TPTR==0/*&& IREQ*/&&JREQ ? 1 :         // wait pipeflush to switch to irq
  466.                  //TPTR==1/*&&!IREQ*/&&JREQ ? 0 : TPTR;  // wait pipeflush to return from irq

  467.     `else
  468.         NXPC <= /*XRES ? `__RESETPC__ :*/ HLT ? NXPC : NXPC2;

  469.             NXPC2 <=  XRES ? `__RESETPC__ : HLT ? NXPC2 :   // reset and halt
  470.         `ifdef __EBREAK__
  471.                      SRET ? SEPC :  // return from system call
  472.                      EBRK ? STVEC : // ebreak causes an system call                     
  473.         `endif

  474.         `ifdef __INTERRUPT__
  475.                      MRET ? MEPC :  // return from interrupt
  476.                     MIP[11]&&JREQ ? MTVEC : // pending interrupt + pipeline flush
  477.         `endif
  478.                          JREQ ? JVAL :                    // jmp/bra
  479.                                 NXPC2+4;                   // normal flow

  480.     `endif

  481. `else
  482.         NXPC <= XRES ? `__RESETPC__ : HLT ? NXPC :   // reset and halt
  483.         
  484.         `ifdef __EBREAK__
  485.                      MRET ? MEPC :
  486.                      EBRK ? MTVEC : // ebreak causes an interrupt
  487.         `endif
  488.         `ifdef __INTERRUPT__
  489.                      MRET ? MEPC :
  490.                     MIP[11]&&JREQ ? MTVEC : // pending interrupt + pipeline flush
  491.         `endif
  492.               JREQ ? JVAL :                   // jmp/bra
  493.                      NXPC+4;                   // normal flow
  494. `endif
  495.         PC   <= /*XRES ? `__RESETPC__ :*/ HLT ? PC : NXPC; // current program counter
  496.     end

  497.     // IO and memory interface

  498.     assign DATAO = U2REG;
  499.     assign DADDR = U1REG + SIMM;

  500.     // based in the Scc and Lcc

  501.     assign DRW      = !SCC;
  502.     assign DLEN[0] = (SCC||LCC)&&FCT3[1:0]==0; // byte
  503.     assign DLEN[1] = (SCC||LCC)&&FCT3[1:0]==1; // word
  504.     assign DLEN[2] = (SCC||LCC)&&FCT3[1:0]==2; // long

  505.     assign DWR     = SCC;
  506.     assign DRD     = LCC;
  507.     assign DAS     = SCC||LCC;

  508. `ifdef __3STAGE__
  509.     `ifdef __THREADS__
  510.         assign IADDR = NXPC2[TPTR];
  511.     `else
  512.         assign IADDR = NXPC2;
  513.     `endif
  514. `else
  515.     assign IADDR = NXPC;
  516. `endif
  517.    
  518. `ifdef __INTERRUPT__
  519.     assign DEBUG = { IRQ, MIP, MIE, MRET };
  520. `else
  521.     assign DEBUG = { XRES, |FLUSH, SCC, LCC };
  522. `endif

  523. `ifdef SIMULATION

  524.     `ifdef __PERFMETER__

  525.         integer clocks=0, running=0, load=0, store=0, flush=0, halt=0;

  526.     `ifdef __THREADS__
  527.         integer thread[0:(2**`__THREADS__)-1],curtptr=0,cnttptr=0;
  528.         integer j;

  529.         initial for(j=0;j!=(2**`__THREADS__);j=j+1) thread[j] = 0;
  530.     `endif

  531.         always@(posedge CLK)
  532.         begin
  533.             if(!XRES)
  534.             begin
  535.                 clocks = clocks+1;

  536.                 if(HLT)
  537.                 begin
  538.                          if(SCC)        store = store+1;
  539.                     else if(LCC)        load  = load +1;
  540.                     else                 halt  = halt +1;
  541.                 end
  542.                 else
  543.                 if(|FLUSH)
  544.                 begin
  545.                     flush=flush+1;
  546.                 end
  547.                 else
  548.                 begin

  549.         `ifdef __THREADS__
  550.                     for(j=0;j!=(2**`__THREADS__);j=j+1)
  551.                             thread[j] = thread[j]+(j==TPTR?1:0);

  552.                     if(TPTR!=curtptr)
  553.                     begin
  554.                         curtptr = TPTR;
  555.                         cnttptr = cnttptr+1;
  556.                     end
  557.         `endif
  558.                     running = running +1;
  559.                 end

  560.                 if(ESIMREQ)
  561.                 begin
  562.                     $display("****************************************************************************");
  563.                     $display("DarkRISCV Pipeline Report (%0d clocks, %0d instr, CPI = %.2f):",
  564.                         clocks,running,1.0*clocks/running);

  565.                     $display("core%0d: %0d%% run, %0d%% wait (%0d%% i-bus, %0d%% d-bus/rd, %0d%% d-bus/wr), %0d%% flush",
  566.                         CPTR,
  567.                         100.0*running/clocks,
  568.                         100.0*(load+store+halt)/clocks,
  569.                         100.0*halt/clocks,
  570.                         100.0*load/clocks,
  571.                         100.0*store/clocks,
  572.                         100.0*flush/clocks);

  573.          `ifdef __THREADS__
  574.                     for(j=0;j!=(2**`__THREADS__);j=j+1) $display("  thread%0d: %0d%% running",j,100.0*thread[j]/clocks);

  575.                     $display("%0d thread switches, %0d clocks/threads",cnttptr,clocks/cnttptr);
  576.          `endif
  577.                     $display("****************************************************************************");
  578.                     $finish();
  579.                 end
  580.             end

  581.         `ifdef __EBREAK__
  582.             if(0 && !HLT&&!FLUSH&&EBRK)
  583.             begin
  584.                 $display("breakpoint at %x",PC);
  585.                 $stop();
  586.             end
  587.         `endif        
  588.         
  589.             if(!FLUSH && IDATA===32'dx)
  590.             begin
  591.                 $display("invalid IDATA at %x",PC);
  592.                 $stop();  
  593.             end
  594.             
  595.             if(LCC&&!HLT&&!FLUSH&&( (DLEN==4 && DATAI[31:0]===32'dx)||
  596.                                     (DLEN==2 && DATAI[15:0]===16'dx)||
  597.                                     (DLEN==1 && DATAI[ 7:0]=== 8'dx)))
  598.             begin
  599.                 $display("invalid DATAI@%x at %x",DADDR,PC);
  600.                 $stop();
  601.             end
  602.             
  603.         `ifdef __TRACE__
  604.             if(!XRES)
  605.             begin
  606.             `ifdef __TRACEFULL__
  607.                 if(FLUSH)
  608.                     $display("trace: %x:%x       flushed",PC,XIDATA);
  609.                 else
  610.                 if(HLT)
  611.                 begin
  612.                     //$display("%x:%x       %s halted       %x:%x",PC,XIDATA,LCC?"lx":"sx",DADDR,LCC?LDATA:DATAO);
  613.                     $display("trace: %x:%x       halted",PC,XIDATA);
  614.                 end
  615.                 else
  616.             `else
  617.                 if(!FLUSH && !HLT)
  618.             `endif
  619.                 begin
  620.                     case(XIDATA[6:0])
  621.                         `LUI:     $display("trace: %x:%x lui   %%x%0x,%0x",                PC,XIDATA,DPTR,$signed(SIMM));
  622.                         `AUIPC:   $display("trace: %x:%x auipc %%x%0x,PC[%0x]",            PC,XIDATA,DPTR,$signed(SIMM));
  623.                         `JAL:     $display("trace: %x:%x jal   %%x%0x,%0x",                PC,XIDATA,DPTR,$signed(SIMM));
  624.                         `JALR:    $display("trace: %x:%x jalr  %%x%0x,%%x%0x,%0d",         PC,XIDATA,DPTR,S1PTR,$signed(SIMM));
  625.                         `BCC:     $display("trace: %x:%x bcc   %%x%0x,%%x%0x,PC[%0d]",     PC,XIDATA,S1PTR,S2PTR,$signed(SIMM));
  626.                         `LCC:     $display("trace: %x:%x lx    %%x%0x,%%x%0x[%0d]\t%x:%x",  PC,XIDATA,DPTR,S1PTR,$signed(SIMM),DADDR,LDATA);
  627.                         `SCC:     $display("trace: %x:%x sx    %%x%0x,%%x%0x[%0d]\t%x:%x",  PC,XIDATA,DPTR,S1PTR,$signed(SIMM),DADDR,DATAO);
  628.                         `MCC:     $display("trace: %x:%x alui  %%x%0x,%%x%0x,%0d",         PC,XIDATA,DPTR,S1PTR,$signed(SIMM));
  629.                         `RCC:     $display("trace: %x:%x alu   %%x%0x,%%x%0x,%%x%0x",      PC,XIDATA,DPTR,S1PTR,S2PTR);
  630.                         `SYS:     $display("trace: %x:%x sys   (no decode)",               PC,XIDATA);
  631.                         `CUS:     $display("trace: %x:%x cus   (no decode)",               PC,XIDATA);
  632.                         default:  $display("trace: %x:%x ???   (no decode)",               PC,XIDATA);
  633.                     endcase
  634.                 end
  635.             end        
  636.         `endif
  637.         
  638.         end

  639.     `else
  640.         always@(posedge CLK) if(ESIMREQ) ESIMACK <= 1;
  641.     `endif


  642. `endif

  643. endmodule


复制代码


darkbridge.v (把cpu核心和L1缓存整合在一起的模块)




  1. /*
  2. * Copyright (c) 2018, Marcelo Samsoniuk
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright notice, this
  9. *   list of conditions and the following disclaimer.
  10. *
  11. * * Redistributions in binary form must reproduce the above copyright notice,
  12. *   this list of conditions and the following disclaimer in the documentation
  13. *   and/or other materials provided with the distribution.
  14. *
  15. * * Neither the name of the copyright holder nor the names of its
  16. *   contributors may be used to endorse or promote products derived from
  17. *   this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  20. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  23. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  25. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  26. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  27. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */

  30. `timescale 1ns / 1ps
  31. `include "../rtl/config.vh"

  32. module darkbridge
  33. (
  34.     input         CLK,      // clock
  35.     input         RES,      // reset
  36.     output        HLT,

  37. `ifdef __INTERRUPT__
  38.     input         XIRQ,
  39. `endif

  40.     // x-bus

  41.     output        XXDREQ,
  42.     output        XXWR,
  43.     output        XXRD,
  44.     output [3:0]  XXBE,
  45.     output [31:0] XXADDR,
  46.     output [31:0] XXATAO,
  47.     input  [31:0] XXATAI,
  48.     input         XXDACK,

  49. `ifdef __HARVARD__
  50.     output        YDREQ,
  51.     output [31:0] YADDR,
  52.     input  [31:0] YDATA,
  53.     input         YDACK,
  54. `endif

  55. `ifdef SIMULATION
  56.     input       ESIMREQ,
  57.     output      ESIMACK,
  58. `endif
  59.     output [3:0] DEBUG      // osciloscope
  60. );

  61.     // darkriscv bus interface

  62.     wire [31:0] IADDR;
  63.     wire [31:0] IDATA;
  64.     wire        IDACK;
  65.    
  66.     wire [31:0] DADDR;
  67.     wire [31:0] DATAO;
  68.     wire [31:0] DATAI;
  69.     wire [ 2:0] DLEN;
  70.     wire        IHLT,
  71.                 DRW,
  72.                 DWR,
  73.                 DRD,
  74.                 DAS;
  75.     wire        DDACK;

  76.    
  77.     // darkriscv

  78.     wire [3:0]  KDEBUG;
  79.    
  80.     darkriscv
  81.     #(
  82.         .CPTR(0)
  83.     )
  84.     core0
  85.     (
  86.         .CLK    (CLK),
  87.         .RES    (RES),
  88.         .HLT    (IHLT),

  89. `ifdef __INTERRUPT__
  90.         .IRQ    (XIRQ),
  91. `endif

  92.         .IDATA  (IDATA),
  93.         .IADDR  (IADDR),
  94.         .DADDR  (DADDR),

  95.         .DATAI  (DATAI),
  96.         .DATAO  (DATAO),
  97.         .DLEN   (DLEN),
  98.         .DRW    (DRW),
  99.         .DWR    (DWR),
  100.         .DRD    (DRD),
  101.         .DAS    (DAS),

  102. `ifdef SIMULATION
  103.         .ESIMREQ(ESIMREQ),
  104.         .ESIMACK(ESIMACK),
  105. `endif

  106.         .DEBUG  (KDEBUG)
  107.     );

  108.     // instruction cache

  109.     wire         YDREQ;
  110.     wire  [31:0] YADDR;
  111.     wire  [31:0] YDATA;
  112.     wire         YDACK;

  113. `ifdef __ICACHE__
  114.   
  115.     darkcache #(.ID(0)) l1_inst
  116.     (
  117.         .CLK    (CLK),
  118.         .RES    (RES),
  119.         .HLT    (HLT),
  120.         
  121.         .DAS    (!RES),
  122.         .DRD    (1'b1),
  123.         .DWR    (1'b0),
  124.         .DLEN   (3'd4),
  125.         .DADDR  (IADDR),   
  126.         .DATAI  (32'd0),
  127.         .DATAP  (IDATA),
  128.         .DDACK  (IDACK),

  129.         .XDREQ    (YDREQ),
  130.         //.XRD    (XRD),
  131.         //.XWR    (XWR),
  132.         //.XBE    (XBE),
  133.         .XADDR  (YADDR),   
  134.         .XATAI  (YDATA),
  135.         //.XATAO  (XDATO),
  136.         .XDACK  (YDACK)
  137.     );

  138. `else

  139.     assign YDREQ = !RES;
  140.     assign YADDR = IADDR;
  141.     assign IDATA = YDATA;
  142.     assign IDACK = YDACK;

  143. `endif

  144.     // data cache

  145.     wire        XDREQ;
  146.     wire        XWR;
  147.     wire        XRD;
  148.     wire [3:0]  XBE;
  149.     wire [31:0] XADDR;
  150.     wire [31:0] XATAO;
  151.     wire        XDACK;
  152.     wire [31:0] XATAI;
  153.    
  154. `ifndef __HARVARD__
  155.     reg [31:0] XATAI2 = 0;   
  156.     reg        XDACK2 = 0;
  157. `endif

  158. `ifdef __DCACHE__
  159.    
  160.     darkcache #(.ID(1)) l1_data   
  161.     (
  162.         .CLK    (CLK),
  163.         .RES    (RES),
  164.         .HLT    (HLT),
  165.         
  166.         .DAS    (DAS),
  167.         .DRD    (DRD),
  168.         .DWR    (DWR),
  169.         .DLEN   (DLEN),
  170.         .DADDR  (DADDR),   
  171.         .DATAI  (DATAO),
  172.         .DATAO  (DATAI),
  173.         .DDACK  (DDACK),

  174.         .XDREQ  (XDREQ),
  175.         .XRD    (XRD),
  176.         .XWR    (XWR),
  177.         .XBE    (XBE),
  178.         .XADDR  (XADDR),   
  179.         .XATAI  (XATAI),
  180.         .XATAO  (XATAO),
  181.         .XDACK  (XDACK)
  182.     );

  183. `else

  184.     assign XDREQ = DAS;
  185.     assign XRD   = DRD;
  186.     assign XWR   = DWR;

  187.     assign XADDR = DADDR;

  188.     assign XBE   = DLEN[0] ? ( DADDR[1:0]==3 ? 4'b1000 : // 8-bit
  189.                                DADDR[1:0]==2 ? 4'b0100 :
  190.                                DADDR[1:0]==1 ? 4'b0010 :
  191.                                                4'b0001 ) :
  192.                    DLEN[1] ? ( DADDR[1]==1   ? 4'b1100 : // 16-bit
  193.                                                4'b0011 ) :
  194.                                                4'b1111;  // 32-bit
  195.    
  196.     assign XATAO = DLEN[0] ? ( DADDR[1:0]==3 ? {        DATAO[ 7: 0], 24'd0 } :
  197.                                DADDR[1:0]==2 ? {  8'd0, DATAO[ 7: 0], 16'd0 } :
  198.                                DADDR[1:0]==1 ? { 16'd0, DATAO[ 7: 0],  8'd0 } :
  199.                                                { 24'd0, DATAO[ 7: 0]        } ):
  200.                    DLEN[1] ? ( DADDR[1]==1   ? { DATAO[15: 0], 16'd0 } :
  201.                                                { 16'd0, DATAO[15: 0] } ):
  202.                                                         DATAO;

  203.     assign DATAI = DLEN[0] ? ( DADDR[1:0]==3 ? XATAI[31:24] :
  204.                                DADDR[1:0]==2 ? XATAI[23:16] :
  205.                                DADDR[1:0]==1 ? XATAI[15: 8] :
  206.                                                XATAI[ 7: 0] ):
  207.                    DLEN[1] ? ( DADDR[1]==1   ? XATAI[31:16] :
  208.                                                XATAI[15: 0] ):
  209.                                                XATAI;

  210.     assign DDACK = XXDACK;

  211. `endif

  212. `ifdef __HARVARD__

  213.     assign XXDREQ = XDREQ;
  214.     assign XXWR   = XWR;
  215.     assign XXRD   = XRD;
  216.     assign XXBE   = XBE;
  217.     assign XXADDR = XADDR;
  218.     assign XXATAO = XATAO;

  219.     assign XATAI  = XXATAI;
  220.     assign XDACK  = XXDACK;

  221.     assign IHLT = (!RES && !IDACK) || (DAS && !DDACK);
  222.    
  223.     assign HLT  = IHLT;

  224. `else

  225.     reg [1:0] XSTATE = 0;
  226.    
  227.     always@(posedge CLK)
  228.     begin
  229.         XSTATE <=   RES                          ? 0 :
  230.                     XSTATE==0 && XDREQ           ? 2 : // idle to data
  231.                     XSTATE==0 && YDREQ           ? 1 : // idle to instr
  232.                     XSTATE==2 && XXDACK && YDREQ ? 1 : // data to instr
  233.                     XSTATE==2 && XXDACK          ? 0 : // data to idle                  
  234.                     XSTATE==1 && XXDACK          ? 0 : // instr to idle
  235.                                                    XSTATE; // no change        
  236.                                                    
  237.             XATAI2 <= (XSTATE==2 && XXDACK) ? XXATAI : XATAI2;

  238.             XDACK2 <= XDREQ && (XSTATE==2 && XXDACK) ? XXDACK :
  239.                       YDREQ && (XSTATE==1 && XXDACK) ? 0      : XDACK2;

  240.     end

  241.     assign XXDREQ = XSTATE==2 ? XDREQ : XSTATE==1 ? YDREQ : 1'b0;
  242.     assign XXWR   = XSTATE==2 ? XWR   : XSTATE==1 ? 1'b0  : 1'b0;
  243.     assign XXRD   = XSTATE==2 ? XRD   : XSTATE==1 ? 1'b1  : 1'b0;
  244.     assign XXBE   = XSTATE==2 ? XBE   : XSTATE==1 ? 4'd15 : 4'd0;
  245.     assign XXADDR = XSTATE==2 ? XADDR : XSTATE==1 ? YADDR : 32'd0;
  246.     assign XXATAO = XSTATE==2 ? XATAO : XSTATE==1 ? 32'd0 : 32'd0;

  247.     assign YDATA  = XXATAI;
  248.     assign YDACK  = XSTATE==1 && XXDACK;

  249.     assign XATAI = XSTATE==1 ? XATAI2 : XXATAI;
  250.     assign XDACK = XSTATE==1 ? XDACK2 : XXDACK;

  251.     assign IHLT = (!RES && !IDACK) || (DAS && !DDACK);
  252.    
  253.     assign HLT  = 0;

  254. `endif
  255.    
  256.     assign DEBUG = { XDREQ, HLT, XDACK, IDACK };

  257. endmodule


复制代码


darkcache.v (L1缓存模块)




  1. /*
  2. * Copyright (c) 2018, Marcelo Samsoniuk
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright notice, this
  9. *   list of conditions and the following disclaimer.
  10. *
  11. * * Redistributions in binary form must reproduce the above copyright notice,
  12. *   this list of conditions and the following disclaimer in the documentation
  13. *   and/or other materials provided with the distribution.
  14. *
  15. * * Neither the name of the copyright holder nor the names of its
  16. *   contributors may be used to endorse or promote products derived from
  17. *   this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  20. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  23. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  25. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  26. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  27. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */

  30. `timescale 1ns / 1ps
  31. `include "../rtl/config.vh"

  32. module darkcache
  33. #(
  34.     parameter ID = 0
  35. )
  36. (
  37.     input           CLK,    // clock
  38.     input           RES,    // reset
  39.     input           HLT,

  40.     // darkriscv

  41.     input           DAS,    // address valid
  42.     input           DRD,    // read/write
  43.     input           DWR,    // read/write
  44.     input   [2:0]   DLEN,   // data length in bytes
  45.     input   [31:0]  DADDR,  // address
  46.     input   [31:0]  DATAI,  // data input
  47.     output  [31:0]  DATAO,  // data output
  48.     output          DDACK,  // data ack

  49.     output  [31:0]  DATAP, // pipelined data output
  50.    
  51.     // memory
  52.    
  53.     output          XDREQ,    // address valid
  54.     output          XRD,    // data read
  55.     output          XWR,    // data write
  56.     output [3:0]    XBE,    // byte enable
  57.     output [31:0]   XADDR,  // address
  58.     output [31:0]   XATAO,  // data output
  59.     input  [31:0]   XATAI,  // data input
  60.     input           XDACK,   // data ack

  61.     output  [3:0]   DEBUG   // osciloscope
  62. );

  63.     // cache

  64. `ifdef __CDEPTH__

  65.   `ifdef __LUTCACHE__
  66.    
  67.     wire [31:0] CDATO;
  68.    
  69.     reg  [31:`__CDEPTH__+2] CTAG   [0:2**`__CDEPTH__-1];   
  70.     reg  [31:0]             CDATA  [0:2**`__CDEPTH__-1];
  71.     reg                     CVAL   [0:2**`__CDEPTH__-1];
  72.    
  73.     integer i;
  74.    
  75.     initial
  76.     begin
  77.         $display("cache%0d: %0dx32-bits (%0d bytes)",
  78.             ID,
  79.             (2**`__CDEPTH__),
  80.             4*(2**`__CDEPTH__));
  81.             
  82.         for(i=0;i!=2**`__CDEPTH__;i=i+1)
  83.         begin            
  84.             CDATA [i] = 0;
  85.             CTAG  [i] = 0;
  86.             CVAL  [i] = 0;
  87.         end
  88.     end

  89.     wire [`__CDEPTH__-1:0]  CINDEX = DADDR[`__CDEPTH__+1:2];

  90.     wire HIT = RES ? 0 : (DRD && CVAL[CINDEX] && CTAG[CINDEX]==DADDR[31:`__CDEPTH__+2]);
  91.     wire CLR = RES ? 0 : (DWR && CVAL[CINDEX] && CTAG[CINDEX]==DADDR[31:`__CDEPTH__+2]);

  92.     wire DTREQ = RES||HIT ? 0 : (DADDR[31:30]==0||DADDR[31:30]==2) && DRD;

  93.     reg [31:0] DATAOFF = 0;

  94.     always@(posedge CLK)
  95.     begin
  96.         if(DTREQ && XDACK)
  97.         begin
  98.             //$display("cache%0d: miss_on_rd %x:%x\n",ID,DADDR,XATAI);
  99.             CDATA [CINDEX]  <= XATAI;
  100.             CTAG  [CINDEX]  <= DADDR[31:`__CDEPTH__+2];
  101.             CVAL  [CINDEX]  <= 1;
  102.         end
  103.         else
  104.         if(CLR)
  105.         begin
  106.             if(DLEN==4)
  107.             begin
  108.                 //$display("cache%0d: miss_on_wr %x:%x\n",ID,DADDR,DATAI);
  109.                 CDATA [CINDEX]  <= DATAI;
  110.                 CTAG  [CINDEX]  <= DADDR[31:`__CDEPTH__+2];
  111.                 CVAL  [CINDEX]  <= 1;   
  112.             end
  113.             else
  114.             begin
  115.                 //$display("cache%0d: flush_on_wr %x:%x\n",ID,DADDR,DATAI);
  116.                 CVAL  [CINDEX]  <= 0;
  117.             end
  118.         end

  119.         // if(HIT) $display("cache%0d: hit_on_rd %x:%x\n",ID,DADDR,DATAI);

  120.         if(!HLT) DATAOFF <= CDATO;
  121.     end

  122.     assign CDATO  = HIT ? CDATA[CINDEX] : XATAI;        
  123.     assign DATAP  = DATAOFF;   
  124.    
  125.     assign DDACK = HIT ? 1 : XDACK;
  126.    
  127.   `else

  128.     wire [31:0] CDATO;   
  129. /*
  130.     reg  [31:`__CDEPTH__+2] CTAG   [0:2**`__CDEPTH__-1];   
  131.     reg  [31:0]             CDATA  [0:2**`__CDEPTH__-1];
  132.     reg                     CVAL   [0:2**`__CDEPTH__-1];
  133. */
  134.     (* ram_style = "block" *) reg  [31:0]             COMBO  [0:2*2**`__CDEPTH__-1];
  135.    
  136.     integer i;
  137.    
  138.     initial
  139.     begin
  140.         $display("cache%0d: %0dx32-bits (%0d bytes)",
  141.             ID,
  142.             (2**`__CDEPTH__),
  143.             4*(2**`__CDEPTH__));
  144.             
  145.         for(i=0;i!=2*2**`__CDEPTH__;i=i+1)
  146.         begin            
  147.         /*
  148.             CDATA [i] = 0;
  149.             CTAG  [i] = 0;
  150.             CVAL  [i] = 0;
  151.         */
  152.             COMBO [i] = 0;
  153.         end
  154.     end

  155.     wire [`__CDEPTH__-1:0]  CINDEX = DADDR[`__CDEPTH__+1:2];

  156.     wire [`__CDEPTH__:0]  CINDEX1 = { 1'b0, CINDEX };
  157.     wire [`__CDEPTH__:0]  CINDEX2 = { 1'b1, CINDEX };


  158.     wire HIT = RES ? 0 : (DRD && CVALFF && CTAGFF==DADDR[31:`__CDEPTH__+2]);
  159.     wire CLR = RES ? 0 : (DWR && CVALFF && CTAGFF==DADDR[31:`__CDEPTH__+2]);

  160.     wire DTREQ = RES||HIT ? 0 : (DADDR[31:30]==0||DADDR[31:30]==2) && DRD;

  161.     reg [31:0] DATAOFF = 0;

  162.     reg [31:0] COMBOFF1 = 0;
  163.     reg [31:0] COMBOFF2 = 0;

  164.     wire  [31:0]             CDATAFF = COMBOFF1[31:0];
  165.     wire  [31:`__CDEPTH__+2] CTAGFF  = COMBOFF2[31:`__CDEPTH__+2];
  166.     wire  [`__CDEPTH__+1:1]  FILLER  = COMBOFF2[`__CDEPTH__+1:1];
  167.     wire                     CVALFF  = COMBOFF2[0];

  168.     reg HIT2 = 0;

  169.    

  170.     always@(posedge CLK)
  171.     begin
  172.         HIT2 <= HIT;
  173.         
  174.         if((DTREQ && XDACK)||CLR)    COMBO [CINDEX1]  <= (DTREQ && XDACK) ? /*{ DADDR[31:`__CDEPTH__+2], ~FILLER, 1'b1 }*/ DADDR|1'b1 : 0;
  175.         if((DTREQ && XDACK)||CLR)    COMBO [CINDEX2]  <= (DTREQ && XDACK) ? XATAI :  0;

  176.         
  177.         COMBOFF1 <= COMBO[CINDEX1];
  178.         COMBOFF2 <= COMBO[CINDEX2];
  179.     /*
  180.         CTAGFF  <= CTAG [CINDEX];
  181.         CDATAFF <= CDATA[CINDEX];
  182.         CVALFF  <= CVAL [CINDEX];
  183.    
  184.         if((DTREQ && XDACK)||CLR)
  185.         begin
  186.             //$display("cache%0d: miss_on_rd %x:%x\n",ID,DADDR,XATAI);
  187.             
  188.             CDATA [CINDEX]  <= XATAI;
  189.             CTAG  [CINDEX]  <= DADDR[31:`__CDEPTH__+2];
  190.             CVAL  [CINDEX]  <= 1;               
  191.         end
  192.         
  193.         else
  194.         if(CLR)
  195.         begin
  196.             if(DLEN==4)
  197.             begin
  198.                 //$display("cache%0d: miss_on_wr %x:%x\n",ID,DADDR,DATAI);
  199.                 CDATA [CINDEX]  <= DATAI;
  200.                 CTAG  [CINDEX]  <= DADDR[31:`__CDEPTH__+2];
  201.                 CVAL  [CINDEX]  <= 1;   
  202.             end
  203.             else
  204.             begin
  205.                 //$display("cache%0d: flush_on_wr %x:%x\n",ID,DADDR,DATAI);
  206.                 COMBO  [CINDEX]  <= 0;
  207.             end
  208.         end
  209. */
  210.         // if(HIT) $display("cache%0d: hit_on_rd %x:%x\n",ID,DADDR,DATAI);

  211.         if(!HLT) DATAOFF <= CDATO;
  212.     end

  213.     assign CDATO  = HIT ? CDATAFF : XATAI;        
  214.     assign DATAP  = DATAOFF;

  215.     assign DDACK = HIT2 ? 1 : XDACK;
  216.    
  217.   `endif

  218. `else

  219.     wire [31:0] CDATO = XATAI;
  220.     wire        HIT   = 0;

  221.     assign DDACK = XDACK;

  222. `endif

  223.     // convert darkriscv bus to xbus

  224.     assign XDREQ = HIT ? 0 : DAS;
  225.     assign XRD   = HIT ? 0 : DRD;
  226.     assign XWR   = HIT ? 0 : DWR;

  227.     assign XADDR = HIT ? 0 : DADDR;

  228.     assign XBE   = HIT ? 0 : DLEN[0] ? ( DADDR[1:0]==3 ? 4'b1000 : // 8-bit
  229.                                          DADDR[1:0]==2 ? 4'b0100 :
  230.                                          DADDR[1:0]==1 ? 4'b0010 :
  231.                                                          4'b0001 ) :
  232.                              DLEN[1] ? ( DADDR[1]==1   ? 4'b1100 : // 16-bit
  233.                                                          4'b0011 ) :
  234.                                                          4'b1111;  // 32-bit
  235.    
  236.     assign XATAO = HIT ? 0 : DLEN[0] ? ( DADDR[1:0]==3 ? {        DATAI[ 7: 0], 24'd0 } :
  237.                                          DADDR[1:0]==2 ? {  8'd0, DATAI[ 7: 0], 16'd0 } :
  238.                                          DADDR[1:0]==1 ? { 16'd0, DATAI[ 7: 0],  8'd0 } :
  239.                                                          { 24'd0, DATAI[ 7: 0]        } ):
  240.                              DLEN[1] ? ( DADDR[1]==1   ? { DATAI[15: 0], 16'd0 } :
  241.                                                          { 16'd0, DATAI[15: 0] } ):
  242.                                                                   DATAI;

  243.     assign DATAO = DLEN[0] ? ( DADDR[1:0]==3 ? CDATO[31:24] :
  244.                                DADDR[1:0]==2 ? CDATO[23:16] :
  245.                                DADDR[1:0]==1 ? CDATO[15: 8] :
  246.                                                CDATO[ 7: 0] ):
  247.                    DLEN[1] ? ( DADDR[1]==1   ? CDATO[31:16] :
  248.                                                CDATO[15: 0] ):
  249.                                                CDATO;

  250.     assign DEBUG = { DAS, HIT, XDREQ, XDACK };

  251. endmodule


复制代码


darkram.v (内存模块)




  1. /*
  2. * Copyright (c) 2018, Marcelo Samsoniuk
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright notice, this
  9. *   list of conditions and the following disclaimer.
  10. *
  11. * * Redistributions in binary form must reproduce the above copyright notice,
  12. *   this list of conditions and the following disclaimer in the documentation
  13. *   and/or other materials provided with the distribution.
  14. *
  15. * * Neither the name of the copyright holder nor the names of its
  16. *   contributors may be used to endorse or promote products derived from
  17. *   this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  20. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  23. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  25. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  26. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  27. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */

  30. `timescale 1ns / 1ps
  31. `include "../rtl/config.vh"

  32. module darkram
  33. (
  34.     input           CLK,    // clock
  35.     input           RES,    // reset
  36.     input           HLT,    // halt
  37.    
  38.     input           IDREQ,
  39.     input  [31:0]   IADDR,
  40.     output [31:0]   IDATA,
  41.     output          IDACK,

  42.     input           XDREQ,
  43.     input           XRD,
  44.     input           XWR,
  45.     input  [3:0]    XBE,
  46.     input  [31:0]   XADDR,
  47.     input  [31:0]   XATAI,
  48.     output [31:0]   XATAO,
  49.     output          XDACK,
  50.    
  51.     output [3:0]    DEBUG
  52. );

  53.     // ro/rw memories

  54.     reg [31:0] MEM [0:2**`MLEN/4-1]; // ro memory

  55.     // memory initialization

  56.     integer i;
  57.     initial
  58.     begin
  59.     `ifdef SIMULATION
  60.         $display("dpram: unified BRAM w/ %0dx32-bit",2**`MLEN/4);
  61.         `ifdef __WAITSTATE__
  62.             $display("dpram: waitstates=%0d enabled (default=1)",`__WAITSTATE__);
  63.         `endif
  64.         `ifdef __RMW_CYCLE__
  65.             $display("dpram: RMW cycle enabled.",);
  66.         `endif
  67.             
  68.         for(i=0;i!=2**`MLEN/4;i=i+1)
  69.         begin
  70.             MEM[i] = 32'd0;
  71.         end
  72.     `endif

  73.      // workaround for vivado: no path in simulation and .mem extension

  74.     `ifdef XILINX_SIMULATOR
  75.         $readmemh("darksocv.mem",MEM);
  76.         `elsif MODEL_TECH
  77.             $readmemh("../../../../src/darksocv.mem",MEM);
  78.     `else
  79.         $readmemh("../src/darksocv.mem",MEM,0);
  80.     `endif
  81.     end

  82.     // instruction memory

  83. `ifdef __ICACHE__

  84.     reg [3:0]  ITACK  = 0;
  85.     reg [31:0] ROMFF  = 0;

  86.     always@(posedge CLK)
  87.     begin
  88.     `ifdef __WAITSTATE__        
  89.         ITACK <= RES ? 0 : ITACK ? ITACK-1 : IDREQ ? `__WAITSTATE__ : 0;
  90.     `else
  91.         ITACK <= RES ? 0 : ITACK ? ITACK-1 : IDREQ ? 1 : 0;
  92.     `endif   
  93.    
  94.         ROMFF <= MEM[IADDR[`MLEN-1:2]];
  95.     end

  96.     assign IDATA = ROMFF;
  97.     assign IDACK = ITACK==1;

  98. `else

  99.     reg [3:0]  ITACK  = 0;
  100.     reg [31:0] ROMFF  = 0;

  101.     always@(posedge CLK)
  102.     begin
  103.     `ifdef __WAITSTATE__
  104.         ITACK <= RES ? 0 : ITACK ? ITACK-1 : IDREQ ? `__WAITSTATE__ : 0; // i-bus wait-state
  105.     `endif

  106.         ROMFF <= MEM[IADDR[`MLEN-1:2]];
  107.         // if(!RES && !HLT) $display("bram: addr=%x inst=%x\n",IADDR,ROMFF);
  108.     end

  109.     assign IDATA = ROMFF;
  110.    
  111.     `ifdef __WAITSTATE__
  112.         assign IDACK = ITACK==1;
  113.     `else
  114.         assign IDACK = IDREQ;
  115.     `endif

  116. `endif

  117.     // data memory

  118.     reg [3:0] DTACK  = 0;
  119.     reg [31:0] RAMFF = 0;

  120.     always@(posedge CLK) // stage #1.0
  121.     begin
  122.     `ifdef __RMW_CYCLE__   
  123.         `ifdef __WAITSTATE__
  124.             DTACK <= RES ? 0 : DTACK ? DTACK-1 : XDREQ && (XRD||XWR) ? `__WAITSTATE__ : 0;
  125.         `else
  126.             DTACK <= RES ? 0 : DTACK ? DTACK-1 : XDREQ && (XRD||XWR) ? 1 : 0;
  127.         `endif
  128.     `else
  129.         `ifdef __WAITSTATE__
  130.             DTACK <= RES ? 0 : DTACK ? DTACK-1 : XDREQ && XRD ? `__WAITSTATE__ : 0;
  131.         `else
  132.             DTACK <= RES ? 0 : DTACK ? DTACK-1 : XDREQ && XRD ? 1 : 0;
  133.         `endif
  134.     `endif

  135.         RAMFF <= MEM[XADDR[`MLEN-1:2]];

  136.         //individual byte/word/long selection, thanks to HYF!

  137. `ifdef __RMW_CYCLE__

  138.         // read-modify-write operation w/ 1 wait-state:

  139.         if(XWR && XDREQ)
  140.         begin
  141.             MEM[XADDR[`MLEN-1:2]] <=
  142.                                 {
  143.                                     XBE[3] ? XATAI[3 * 8 + 7: 3 * 8] : RAMFF[3 * 8 + 7: 3 * 8],
  144.                                     XBE[2] ? XATAI[2 * 8 + 7: 2 * 8] : RAMFF[2 * 8 + 7: 2 * 8],
  145.                                     XBE[1] ? XATAI[1 * 8 + 7: 1 * 8] : RAMFF[1 * 8 + 7: 1 * 8],
  146.                                     XBE[0] ? XATAI[0 * 8 + 7: 0 * 8] : RAMFF[0 * 8 + 7: 0 * 8]
  147.                                 };
  148.         end

  149. `else
  150.         // write-only operation w/ 0 wait-states:
  151.         
  152.         if(XWR && XDREQ && XBE[3]) MEM[XADDR[`MLEN-1:2]][3 * 8 + 7: 3 * 8] <= XATAI[3 * 8 + 7: 3 * 8];
  153.         if(XWR && XDREQ && XBE[2]) MEM[XADDR[`MLEN-1:2]][2 * 8 + 7: 2 * 8] <= XATAI[2 * 8 + 7: 2 * 8];
  154.         if(XWR && XDREQ && XBE[1]) MEM[XADDR[`MLEN-1:2]][1 * 8 + 7: 1 * 8] <= XATAI[1 * 8 + 7: 1 * 8];
  155.         if(XWR && XDREQ && XBE[0]) MEM[XADDR[`MLEN-1:2]][0 * 8 + 7: 0 * 8] <= XATAI[0 * 8 + 7: 0 * 8];        
  156. `endif
  157.     end

  158.     assign XATAO = RAMFF;
  159.    
  160. `ifdef __RMW_CYCLE__   
  161.     assign XDACK = DTACK==1;
  162. `else
  163.     assign XDACK = DTACK==1 ||(XDREQ&&XWR);
  164. `endif
  165.          
  166.     assign DEBUG = { XDREQ,XRD,XWR,XDACK };

  167. endmodule


复制代码



darksocv.v (SOC也可以称为TOP模块)




  1. /*
  2. * Copyright (c) 2018, Marcelo Samsoniuk
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright notice, this
  9. *   list of conditions and the following disclaimer.
  10. *
  11. * * Redistributions in binary form must reproduce the above copyright notice,
  12. *   this list of conditions and the following disclaimer in the documentation
  13. *   and/or other materials provided with the distribution.
  14. *
  15. * * Neither the name of the copyright holder nor the names of its
  16. *   contributors may be used to endorse or promote products derived from
  17. *   this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  20. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  23. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  25. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  26. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  27. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */

  30. `timescale 1ns / 1ps
  31. `include "../rtl/config.vh"

  32. module darksocv
  33. (
  34.     input        XCLK,      // external clock
  35.     input        XRES,      // external reset

  36.     input        UART_RXD,  // UART receive line
  37.     output       UART_TXD,  // UART transmit line

  38. `ifdef __SDRAM__

  39.     output          S_CLK,
  40.     output          S_CKE,
  41.     output          S_NCS,
  42.     output          S_NWE,
  43.     output          S_NRAS,
  44.     output          S_NCAS,
  45.     output [1:0]    S_DQM,
  46.     output [1:0]    S_BA,
  47.     output [12:0]   S_A,
  48.     inout  [15:0]   S_DB,

  49. `endif

  50.     output [3:0] LED,       // on-board leds
  51.     output [3:0] DEBUG      // osciloscope
  52. );

  53.     // clock and reset

  54.     wire CLK,RES;

  55. `ifdef BOARD_CK
  56.    
  57.     darkpll darkpll0
  58.     (
  59.         .XCLK(XCLK),
  60.         .XRES(XRES),
  61.         .CLK(CLK),
  62.         .RES(RES)
  63.     );

  64. `else

  65.     // internal/external reset logic

  66.     reg [7:0] IRES = -1;

  67.     `ifdef INVRES
  68.         always@(posedge XCLK) IRES <= XRES==0 ? -1 : IRES[7] ? IRES-1 : 0; // reset low
  69.     `else
  70.         always@(posedge XCLK) IRES <= XRES==1 ? -1 : IRES[7] ? IRES-1 : 0; // reset high
  71.     `endif

  72.     assign CLK = XCLK;
  73.     assign RES = IRES[7];

  74. `endif

  75. `ifdef __TESTMODE__
  76.          
  77.     // tips to port darkriscv for a new target:
  78.          //
  79.          // - 1st of all, test the blink code to confirms the reset
  80.          //   polarity, i.e. the LEDs must blink at startup when
  81.          //   the reset button *is not pressed*
  82.          // - 2nd check the blink rate: the 31-bit counter that starts
  83.          //   with BOARD_CK value and counts to zero, blinking w/
  84.          //   50% of this period

  85.          reg [31:0] BLINK = 0;
  86.          
  87.          always@(posedge CLK)
  88.          begin
  89.         BLINK <= RES ? 0 : BLINK ? BLINK-1 : `BOARD_CK;
  90.          end
  91.          
  92.          assign LED      = (BLINK < (`BOARD_CK/2)) ? -1 : 0;
  93.          assign UART_TXD = UART_RXD;
  94. `endif

  95.     // darkbridge interface

  96.     wire        XIRQ;
  97.     wire        XDREQ;
  98.     wire [31:0] XADDR;
  99.     wire [31:0] XATAO;
  100.     wire        XWR,
  101.                 XRD;               
  102.     wire [3:0]  XBE;
  103.     wire [3:0]  XDREQMUX;
  104.    
  105.     assign XDREQMUX[0] = XDREQ && XADDR[31:30]==0;
  106.     assign XDREQMUX[1] = XDREQ && XADDR[31:30]==1;
  107.     assign XDREQMUX[2] = XDREQ && XADDR[31:30]==2;
  108.     assign XDREQMUX[3] = XDREQ && XADDR[31:30]==3;

  109.     wire [31:0] XATAIMUX [0:3];
  110.     wire        XDACKMUX [0:3];
  111.    
  112.     // darkriscv

  113.     wire [3:0]  KDEBUG;
  114.    
  115.     wire        ESIMREQ,ESIMACK;

  116.     wire        HLT;  

  117.     wire        IDREQ;
  118.     wire [31:0] IADDR;
  119.     wire [31:0] IDATA;
  120.     wire        IDACK;

  121. `ifndef __HARVARD__

  122.     assign IDREQ = 0;

  123. `endif

  124.     darkbridge
  125.     bridge0
  126.     (
  127.         .CLK    (CLK),
  128.         .RES    (RES),
  129.         .HLT    (HLT),

  130. `ifdef __INTERRUPT__
  131.         .XIRQ    (XIRQ),
  132. `endif

  133.         .XXDREQ  (XDREQ),
  134.         .XXADDR  (XADDR),
  135.         .XXATAI  (XATAIMUX[XADDR[31:30]]),
  136.         .XXATAO  (XATAO),
  137.         .XXRD    (XRD),
  138.         .XXWR    (XWR),        
  139.         .XXBE    (XBE),
  140.         .XXDACK  (XDACKMUX[XADDR[31:30]]),

  141. `ifdef __HARVARD__
  142.         .YDREQ  (IDREQ),
  143.         .YADDR  (IADDR),
  144.         .YDATA  (IDATA),
  145.         .YDACK  (IDACK),
  146. `endif

  147. `ifdef SIMULATION
  148.         .ESIMREQ(ESIMREQ),
  149.         .ESIMACK(ESIMACK),
  150. `endif

  151.         .DEBUG  (KDEBUG)
  152.     );

  153.     // bram memory w/ CS==0

  154.     darkram bram0
  155.     (
  156.         .CLK    (CLK),
  157.         .RES    (RES),
  158.         .HLT    (HLT),
  159.         
  160.         .IDREQ  (IDREQ),
  161.         .IADDR  (IADDR),
  162.         .IDATA  (IDATA),
  163.         .IDACK  (IDACK),
  164.         
  165.         .XDREQ  (XDREQMUX[0]),
  166.         .XRD    (XRD),
  167.         .XWR    (XWR),
  168.         .XBE    (XBE),
  169.         .XADDR  (XADDR),
  170.         .XATAI  (XATAO),
  171.         .XATAO  (XATAIMUX[0]),
  172.         .XDACK  (XDACKMUX[0])
  173.     );

  174.     // io block w/ CS==1

  175.     wire [3:0] IODEBUG;

  176.     darkio io0
  177.     (
  178.         .CLK    (CLK),
  179.         .RES    (RES),
  180.         .HLT    (HLT),

  181. `ifdef __INTERRUPT__
  182.         .XIRQ    (XIRQ),
  183. `endif
  184.       
  185.         .XDREQ  (XDREQMUX[1]),
  186.         .XRD    (XRD),
  187.         .XWR    (XWR),
  188.         .XBE    (XBE),
  189.         .XADDR  (XADDR),
  190.         .XATAI  (XATAO),
  191.         .XATAO  (XATAIMUX[1]),
  192.         .XDACK  (XDACKMUX[1]),        
  193.         
  194.         .RXD    (UART_RXD),
  195.         .TXD    (UART_TXD),

  196.         .LED    (LED),

  197. `ifdef SIMULATION
  198.         .ESIMREQ(ESIMREQ),
  199.         .ESIMACK(ESIMACK),
  200. `endif

  201.         .DEBUG  (IODEBUG)
  202.     );

  203.     // sdram w/ CS==2
  204.    
  205. `ifdef __SDRAM__

  206.     // sdram interface, thanks to my good friend Hirosh Dabui!

  207.     wire READY,T_CLK;

  208.     mt48lc16m16a2_ctrl
  209.     #(
  210.         .SDRAM_CLK_FREQ(`BOARD_CK/1000000)
  211.     )
  212.     sdram0
  213.     (
  214.         .clk        (CLK),
  215.         .resetn     (!RES),
  216.         
  217.         .addr       (XADDR[24:0]),
  218.         .din        (XATAO),
  219.         .dout       (XATAIMUX[2]),
  220.         .wmask      (XWR ? XBE : 4'b0000),
  221.         .valid      (XDREQMUX[2]),
  222.         .ready      (READY),

  223.         .sdram_clk  (T_CLK),
  224.         .sdram_cke  (S_CKE),
  225.         .sdram_dqm  (S_DQM),
  226.         .sdram_addr (S_A),
  227.         .sdram_ba   (S_BA),
  228.         .sdram_csn  (S_NCS),
  229.         .sdram_wen  (S_NWE),
  230.         .sdram_rasn (S_NRAS),
  231.         .sdram_casn (S_NCAS),
  232.         .sdram_dq   (S_DB)
  233.     );

  234.     reg [1:0] TS_CLK = 2'b00;

  235.     always@(posedge CLK) TS_CLK[0] <= RES ? 0: !TS_CLK[0];
  236.     always@(negedge CLK) TS_CLK[1] <= RES ? 0: !TS_CLK[1];

  237.     assign S_CLK = ^TS_CLK;

  238.     assign XDACKMUX[2] = READY;

  239. `else

  240.     reg [3:0] DTACK2 = 0;

  241.     always@(posedge CLK)
  242.     begin
  243.         DTACK2 <= RES ? 0 : DTACK2 ? DTACK2-1 : XDREQMUX[2] ? 13 : 0;
  244.         if(XDREQMUX[2]) $display("sdram: unmapped addr=%x",XADDR);
  245.     end

  246.     assign XATAIMUX[2] = 32'hdeadbeef;
  247.     assign XDACKMUX[2] = DTACK2==1;

  248. `endif

  249.     // unmapped area w/ CS==3

  250.     reg [3:0] DTACK3 = 0;

  251.     always@(posedge CLK)
  252.     begin
  253.         DTACK3 <= RES ? 0 : DTACK3 ? DTACK3-1 : XDREQMUX[3] ? 1 : 0;
  254.         if(XDREQMUX[3]) $display("sdram: unmapped addr=%x",XADDR);
  255.     end

  256.     assign XATAIMUX[3] = 32'hdeadbeef;
  257.     assign XDACKMUX[3] = DTACK3==1;
  258.          
  259.     assign DEBUG = KDEBUG;

  260. endmodule


复制代码


设备上电内存模块就会把指令缓存的数据通过 IDATA 向外输出然后通过darkbridge模块的YDATA引脚输入darkbridge模块,之后通过L1缓存模块的XATAI缓存到L1指令缓存,然后核心模块通过给L1指令缓存发送地址来读取L1缓存的指令数据。数据通过L1指令缓存的DATAP引脚输入CPU核心模块。然后再时钟上沿时赋值给寄存器 IDATA2,在之后通过 wire[31:0] IDATAX = XRES ? 0 : HLT2 ? IDATA2 : IDATA;  赋值给IDATAX。之后就是时钟上沿时把指令解码出来,代码如下




  1. <blockquote>always@(posedge CLK)


复制代码
在一系列解码指令之后就是开始解码数据




  1.     wire [31:0] LDATA = FCT3[1:0]==0 ? { FCT3[2]==0&&DATAI[ 7] ? ALL1[31: 8]:ALL0[31: 8] , DATAI[ 7: 0] } :
  2.                         FCT3[1:0]==1 ? { FCT3[2]==0&&DATAI[15] ? ALL1[31:16]:ALL0[31:16] , DATAI[15: 0] } :
  3.                                         DATAI;


复制代码
之后就是寄存器重置或赋值





  1. `ifdef __RV32E__
  2.         REGS[DPTR] <=   XRES||DPTR[3:0]==0 ? 0  :        // reset x0
  3. `else
  4.         REGS[DPTR] <=   XRES||DPTR[4:0]==0 ? 0  :        // reset x0
  5. `endif
  6.                        HLT ? REGS[DPTR] :        // halt
  7.                        LCC ? LDATA :
  8.                      AUIPC ? PCSIMM :
  9.                       JAL||
  10.                       JALR ? NXPC :
  11.                        LUI ? SIMM :
  12.                   MCC||RCC ? RMDATA:


复制代码


在下一个时钟周期把通用寄存器分拆




  1.     // source-1 and source-1 register selection

  2.     wire          [31:0] U1REG = REGS[S1PTR];
  3.     wire          [31:0] U2REG = REGS[S2PTR];

  4.     wire signed   [31:0] S1REG = U1REG;
  5.     wire signed   [31:0] S2REG = U2REG;


复制代码
之后就是一系列的数据处理


 楼主| 发表于 2024-8-21 09:17:41 | 显示全部楼层


sogaside 发表于 2024-8-20 15:09
通用寄存器一般只是存储中间结果
还有另外一个方向:用专门的破解软件把汇编转成c语言代码 ...


感谢提供新思路~file:///C:\Users\CC\AppData\Local\Temp\SGPicFaceTpBq\8608\06728ED8.png
 楼主| 发表于 2024-8-21 09:22:16 | 显示全部楼层


daviehj 发表于 2024-8-20 17:06
访问的是通用寄存器还是特殊寄存器,通用寄存器就是暂存的,特殊功能寄存器得看手册了,抛开手册,单看汇编 ...


汇编指令中涉及通用寄存器和特殊功能寄存器,对于通用寄存器的操作,比如把R21[0]置1,并不理解硬件做这一步的目的,就不知道怎么根据汇编指令推测硬件功能,手册中有描述特殊功能寄存器,通用寄存器的内容几乎为0,目前卡在方法论上,不知道怎么根据汇编指令推测硬件功能,单条汇编指令都理解,但无法理解指令集具体在做什么,如果大佬有好的想法,希望不吝赐教~
 楼主| 发表于 2024-8-21 09:31:59 | 显示全部楼层


sogaside 发表于 2024-8-20 15:09
通用寄存器一般只是存储中间结果
还有另外一个方向:用专门的破解软件把汇编转成c语言代码 ...


感谢大佬提供新思路,我目前做的事情就是根据汇编指令集反推硬件功能,作为新人,对于这个方向经验为0,同事在这个方向也0经验,工作进度较慢,自己也没想出一个正确的方法推进工作,只能用笨办法,翻译全部指令集,画控制流程图,分析每个寄存器每一位的数据流,但也不确定这么做能不能成功推测出功能,如果您有好的方法,希望不吝赐教,万分感谢!!!
 楼主| 发表于 2024-8-21 10:03:48 | 显示全部楼层


轩辕志瑜 发表于 2024-8-20 19:04
找些开源cpu的rtl代码和讲解cpu芯片开发的视频看看。

用 https://github.com/darklife/darkriscv 这个项目 ...


感谢大佬在百忙之中抽出时间答疑解惑,步骤详细具体,file:///C:\Users\CC\AppData\Local\Temp\SGPicFaceTpBq\8608\0698441B.png,我目前手中只有汇编指令集和技术手册,您认为加深对CPU的工作原理,可以帮助我推进根据汇编指令集推测硬件功能的工作是吗?不知道我理解的是否正确,非常感谢您的宝贵意见~
发表于 2024-8-21 17:13:11 | 显示全部楼层


CC119 发表于 2024-8-21 09:31
感谢大佬提供新思路,我目前做的事情就是根据汇编指令集反推硬件功能,作为新人,对于这个方向经验为0, ...


当然可以啊,以前写汇编代码也是要一点一点理解逻辑的,多画流程图,多看几遍就好了
 楼主| 发表于 2024-8-22 09:02:53 | 显示全部楼层


sogaside 发表于 2024-8-21 17:13
当然可以啊,以前写汇编代码也是要一点一点理解逻辑的,多画流程图,多看几遍就好了
...


嗯嗯,好的,Thanks♪(・ω・)ノ~
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条


小黑屋| 手机版| 关于我们| 联系我们| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2025-1-20 21:51 , Processed in 0.054866 second(s), 18 queries , Gzip On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表