Compare commits

..

8 Commits
master ... bram

Author SHA1 Message Date
liangkangnan 5c87fc09ef tb: add jtag testbench
Signed-off-by: liangkangnan <liangkangnan@163.com>
2020-12-06 20:07:06 +08:00
liangkangnan fdc776ab5e rtl: debug: support reset cmd
Signed-off-by: liangkangnan <liangkangnan@163.com>
2020-12-06 20:06:12 +08:00
liangkangnan f03f42fc9b rtl: add reset ctrl module
Signed-off-by: liangkangnan <liangkangnan@163.com>
2020-11-18 22:15:08 +08:00
liangkangnan ceddc1af24 test:example: move C examples to sdk directory
Signed-off-by: liangkangnan <liangkangnan@163.com>
2020-11-08 22:09:38 +08:00
liangkangnan 5c9f1a140e rtl: add mem access misaligned exception
Signed-off-by: liangkangnan <liangkangnan@163.com>
2020-11-08 22:08:03 +08:00
Blue Liang 60a4f7d6df rtl: add generate block name
Signed-off-by: liangkangnan <liangkangnan@163.com>
2020-10-26 17:01:04 +08:00
liangkangnan eb5647915a python scripts: remove verison
Signed-off-by: liangkangnan <liangkangnan@163.com>
2020-10-25 12:02:26 +08:00
liangkangnan 2b44f1e8f3 first release
Signed-off-by: liangkangnan <liangkangnan@163.com>
2020-10-23 21:26:18 +08:00
178 changed files with 5350 additions and 5204 deletions

2
.gitignore vendored
View File

@ -2,3 +2,5 @@
*.o
*.ko
*.obj
*.bin
*.dump

251
README.md
View File

@ -1,251 +1,2 @@
本项目目前一共有3个分支分别是master、bram和verilator分别对应入门、进阶和高级三个级别大家可以根据自身情况选择。
**本项目是一直在更新的verilator分支持续开发中**,如果哪天不再更新了,我会特别说明的。
如果对本项目有疑问或者建议的话,优先通过邮件交流,谢谢。
配套的设计文档在doc目录下目前还没完成
# 1.初衷
本开源项目的初衷是本人想入门RISC-V熟悉RISC-V的指令内容和汇编语法。
本人对RISC-V很感兴趣很看好RISC-V的发展前景觉得RISC-V就是CPU中的Linux。由于RISC-V是这两年才开始迅速发展的因此关于RISC-V的学习参考资料目前还很少特别是适合入门的资料因此学习起来进度很缓慢于是萌生了自己从零开始写RISC-V处理器核的想法。
本人是一名FPGA小白为了快速入门、深入掌握RISC-V我开始了学习FPGA和verilog的&quot;艰难&quot;历程。我工作的内容是和嵌入式软件相关的平时根本不会接触到FPGA也不会用到RISC-V因此只能用业余时间来学习RISC-V。
网上有不少关于RISC-V的开源项目但是大多都写得很&quot;高深&quot;对于我这种小白来说学习起来是非常吃力的不太适合入门。本项目目前的代码量非常少是很简单易懂的对于想入门RISC-V的同学来说是一个很好的参考希望能够吸引更多的同学参与到RISC-V的学习中来促进RISC-V的发展如果能起到抛砖引玉的作用的话那就更好了也许说是砖的话就有点夸大了但哪怕是起到一颗沙子的作用也就足矣。
# 2.介绍
本项目实现的是一个单核32位的小型RISC-V处理器核(tinyriscv)采用verilog语言编写。设计目标是对标ARM Cortex-M3系列处理器。tinyriscv有以下特点
1. 支持RV32IM指令集通过RISC-V指令兼容性测试
3. 采用三级流水线,即取指,译码,执行;
4. 可以运行C语言程序
5. 支持JTAG可以通过openocd读写内存(在线更新程序)
6. 支持中断;
6. 支持总线;
7. 支持FreeRTOS
8. 支持通过串口更新程序;
9. 容易移植到任何FPGA平台(如果资源足够的话)
项目中的各目录说明:
**rtl**该目录包含tinyriscv的所有verilog源码
**sim**该目录包含仿真批处理bat文件和脚本
**tests**该目录包含测试程序源码其中example目录为C语言程序例程源码isa目录为RV32指令测试源码
**tools**该目录包含编译汇编和C语言程序所需GNU工具链和将二进制文件转成仿真所需的mem格式文件的脚本还有通过串口下载程序的脚本。
**pic**:存放图片;
**tb**该目录包含仿真的testbench文件
**fpga**存放FPGA相关文件比如约束文件
tinyriscv的整体框架如下
![tinyriscv整体框架](./pic/arch.jpg)
tinyriscv目前外挂了6个外设每个外设的空间大小为256MB地址空间分配如下图所示
<img src="./pic/addr_alloc.jpg" alt="地址空间分配" style="zoom:70%;" />
# 3.CoreMark测试
目前tinyriscv在Xilinx Artix-7 35T FPGA平台(时钟50MHz)上运行CoreMark跑分程序的结果如下图所示
![tinyriscv跑分](./pic/tinyriscv_coremark.png)
可知tinyriscv的跑分成绩为2.4。
选了几款其他MCU的跑分结果如下图所示
![其他MCU跑分结果](./pic/other_coremark.png)
更多MCU的跑分结果可以到[coremark](https://www.eembc.org/coremark/scores.php)官网查询。
# 4.如何使用
本项目可以运行在Windows和Linux平台(macOS平台理论上也是可以的)编译仿真工具使用的是iverilog和vpp波形查看工具使用的是gtkwave。
## 4.1Windows平台环境搭建
在使用之前需要安装以下工具:
1. 安装iverilog工具
可以在这里[http://bleyer.org/icarus/](http://bleyer.org/icarus/)下载安装过程中记得同意把iverilog添加到环境变量中当然也可以在安装完成后手动进行添加。安装完成后iverilog、vvp和gtkwave等工具也就安装好了。
2. 安装GNU工具链
可以通过百度网盘下载(链接: https://pan.baidu.com/s/1bYgslKxHMjtiZtIPsB2caQ 提取码: 9n3c),或者通过微云下载[https://share.weiyun.com/5bMOsu9](https://share.weiyun.com/5bMOsu9)下载完成后将压缩包解压到本项目的tools目录下。注意目录的层次结构解压后的工具路径应该如下所示
`tinyriscv\tools\gnu-mcu-eclipse-riscv-none-gcc-8.2.0-2.2-20190521-0004-win64\bin\riscv-none-embed-gcc`
3. 安装make工具
可以通过百度网盘下载(链接: https://pan.baidu.com/s/1nFaUIwv171PDXuF7TziDFg 提取码: 9ntc),或者通过微云下载[https://share.weiyun.com/59xtmWR](https://share.weiyun.com/59xtmWR)下载完成后直接解压然后将make所在的路径添加到环境变量里。
4. 安装python3
到[python官网](https://www.python.org/)下载win版本的python注意要下载python3版本的。网速慢的同学可以通过百度网盘下载(链接: https://pan.baidu.com/s/1gNC8L5dZTsN6E5TJD2rmnQ 提取码: 3b4t),或者通过微云下载[https://share.weiyun.com/XwzSQHND](https://share.weiyun.com/XwzSQHND)。安装完后将python添加到环境变量里。
5. 下载tinyriscv代码
**使用git clone命令下载不要使用zip方式下载**,否则有些文件会有格式问题。
`git clone https://gitee.com/liangkangnan/tinyriscv.git`
## 4.2Linux平台环境搭建
这里以Ubuntu系统为例进行说明。
1. 下载iverilog源码
`git clone https://github.com/steveicarus/iverilog.git`
2. 切换到v11分支(必须用V11或以上的版本)
`git checkout v11-branch`
3. 安装依赖
`sudo apt-get install autoconf gperf flex bison build-essential`
4. 编译、安装iverilog和vvp
```
sh autoconf.sh
./configure
make
make install
```
5. 创建python软链接
`sudo ln -s /usr/bin/python3.8 /usr/bin/python`
其中/usr/bin/python3.8对应你实际安装的python版本。
6. 安装gtkwave
`sudo apt-get install gtkwave`
7. 安装GNU工具链
可以从百度网盘下载(链接https://pan.baidu.com/s/10uLZYf_cgtH94kZI_N6JhQ
提取码uk0w)或者自行下载其他版本的下载后解压到tools目录下。
最后需要确认tests/example/common.mk文件里的这几行内容要与你安装的工具链对应得上。
![toolchain](./pic/toolchain.png)
## 4.3运行指令测试程序
这里以Windows平台为例进行说明Linux平台是类似的。
### 4.3.1 运行旧的指令测试程序
旧的指令测试程序属于比较早的指令兼容性测试方法虽然目前RISC-V官方已经不更新了但仍然是一个比较好的测试参考。
下面以add指令为例说明如何运行旧的指令测试程序。
打开CMD窗口进入到sim目录执行以下命令
```python .\sim_new_nowave.py ..\tests\isa\generated\rv32ui-p-add.bin inst.data```
如果运行成功的话就可以看到&quot;PASS&quot;的打印。其他指令使用方法类似。
![](./pic/test_output.png)
也可以一次性对所有指令进行测试,方法如下。
打开CMD窗口进入到sim目录下执行以下命令
`python .\test_all_isa.py`
### 4.3.2运行新的指令测试程序
新的指令兼容性([riscv-compliance](https://github.com/riscv/riscv-compliance))测试项相对于旧的指令兼容性测试项来说对指令的测试更加严谨可以精确到每一条指令的运行结果而且RISC-V官方一直在更新。
下面以add指令为例说明如何运行新的指令测试程序。
打开CMD窗口进入到sim/compliance_test目录执行以下命令
`python .\compliance_test.py ..\..\tests\riscv-compliance\build_generated\rv32i\I-ADD-01.elf.bin inst.data`
如果运行成功的话就可以看到&quot;PASS&quot;的打印。其他指令使用方法类似。
![new_test_output](./pic/new_test_output.png)
## 4.4运行C语言程序
C语言程序例程位于tests\example目录里。
下面以simple程序为例进行说明。
打开CMD窗口进入到tests\example\simple目录执行以下命令编译
`make`
编译成功之后进入到sim目录执行以下命令开始测试
` python .\sim_new_nowave.py ..\tests\example\simple\simple.bin inst.data`
# 5.移植到FPGA
详细的移植方法请查看本项目下的fpga目录中的README.md文件。
# 6.未来计划
1. 写设计文档;
2. 优化资源和功耗(主要是译码和执行部分)
3. 支持硬件中断嵌套和快速实时中断;
4. ......
# 7.更新记录
2020-10-25支持Linux平台编译、仿真。新建bram分支使用BRAM代替LUTRAM(DRAM)节省一半以上的LUT资源并且可以运行更大的程序。
2020-07-04支持通过UART烧写固件
2020-05-27增加新的指令兼容性(riscv-compliance)测试项。
2020-05-05支持spi master增加spi测试例程。
2020-04-25支持FreeRTOS(v10.3.1)。
2020-04-18适当添加代码注释优化中断管理模块。
2020-04-11增加CoreMark跑分例程和跑分成绩。
2020-04-05支持CSR指令。
2020-03-29重大更新主要更新如下
1. 支持RIB(RISC-V Internal Bus)总线;
2. 优化乘法代码节省了2/3的DSP资源
3. 优化除法代码解决了除法模块的BUG
4. 完善C语言例程、启动代码和链接脚本
5. 增加一次性对所有指令进行测试的脚本;
2020-03-08支持中断为此增加了timer模块来验证。
2020-03-01支持JTAG配合openocd可进行内存读写。JTAG文档参考[深入浅出RISC-V调试](https://liangkangnan.gitee.io/2020/03/21/深入浅出RISC-V调试/)。
2020-02-23支持在Xilinx Artix-7平台上运行。详见[tinyriscv_vivado](https://gitee.com/liangkangnan/tinyriscv_vivado)。
2020-01-13支持RV32M的除法指令。其C语言实现详见[div](https://gitee.com/liangkangnan/div)。
2020-01-02支持RV32M的乘法指令。
2019-12-06第一次发布。
# 8.其他
如有疑问或者建议,欢迎私信或者发邮件(liangkangnan@163.com)给我。
本分支(bram)是在master分支的基础上将指令和数据存储器由LUTRAM(DRAM)改为BRAM以便可以运行更大的(C语言)程序。

Binary file not shown.

BIN
doc/riscv-debug-release.pdf Normal file

Binary file not shown.

BIN
doc/riscv-privileged.pdf Normal file

Binary file not shown.

BIN
doc/riscv-spec.pdf Normal file

Binary file not shown.

View File

@ -156,7 +156,7 @@
打开一个CMD窗口然后cd进入到tinyriscv项目的tools/openocd目录执行命令
`openocd.exe -f tinyriscv.cfg`
`openocd.exe -f tinyriscv_cmsisdap.cfg`
如果执行成功的话则会如下图所示:
@ -182,22 +182,6 @@
**注意每次下载程序前记得先执行halt命令停住CPU。**
## 3.2通过UART方式下载
通过UART方式下载前需要先使能UART debug模块。在约束文件里指定的uart_debug_en引脚当其输入为高电平时表示使能UART debug模块输入为低电平时表示关闭UART debug模块。
当使能了UART debug模块后就可以通过tools/tinyriscv_fw_downloader.py脚本来下载程序。
tinyriscv_fw_downloader.py脚本使用方法
`python tinyriscv_fw_downloader.py 串口号 bin文件`
打开CMD窗口进入到tools目录比如输入以下命令
![uart_debug](./images/uart_debug.png)
即可下载freertos.bin程序到软核里。下载完后先关闭UART debug模块然后按板子上的复位(rst)按键即可让程序跑起来。
# 4.Vivado仿真设置
如果要在vivado里进行RTL仿真的话还需要添加tb目录里的tinyriscv_soc_tb.v文件具体方法和添加RTL源文件类似只是在源文件类型里选择simulation sources如下图所示
@ -213,7 +197,7 @@ tinyriscv_fw_downloader.py脚本使用方法
```
// read mem data
initial begin
$readmemh ("F://yourpath/inst.data", tinyriscv_soc_top_0.u_rom._rom);
$readmemh ("F://yourpath/inst.data", tinyriscv_soc_top_0.u_rom.u_gen_ram.ram);
end
```

View File

@ -7,25 +7,13 @@ set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property PACKAGE_PIN N14 [get_ports clk]
# 复位引脚
set_property IOSTANDARD LVCMOS33 [get_ports rst]
set_property PACKAGE_PIN L13 [get_ports rst]
# 程序执行完毕指示引脚
set_property IOSTANDARD LVCMOS33 [get_ports over]
set_property PACKAGE_PIN M16 [get_ports over]
# 程序执行成功指示引脚
set_property IOSTANDARD LVCMOS33 [get_ports succ]
set_property PACKAGE_PIN N16 [get_ports succ]
set_property IOSTANDARD LVCMOS33 [get_ports rst_ext_i]
set_property PACKAGE_PIN L13 [get_ports rst_ext_i]
# CPU停住指示引脚
set_property IOSTANDARD LVCMOS33 [get_ports halted_ind]
set_property PACKAGE_PIN P15 [get_ports halted_ind]
# 串口下载使能引脚
set_property IOSTANDARD LVCMOS33 [get_ports uart_debug_pin]
set_property PACKAGE_PIN K13 [get_ports uart_debug_pin]
# 串口发送引脚
set_property IOSTANDARD LVCMOS33 [get_ports uart_tx_pin]
set_property PACKAGE_PIN M6 [get_ports uart_tx_pin]
@ -60,22 +48,6 @@ set_property PACKAGE_PIN N2 [get_ports jtag_TDI]
set_property IOSTANDARD LVCMOS33 [get_ports jtag_TDO]
set_property PACKAGE_PIN M1 [get_ports jtag_TDO]
# SPI MISO引脚
set_property IOSTANDARD LVCMOS33 [get_ports spi_miso]
set_property PACKAGE_PIN P1 [get_ports spi_miso]
# SPI MOSI引脚
set_property IOSTANDARD LVCMOS33 [get_ports spi_mosi]
set_property PACKAGE_PIN N1 [get_ports spi_mosi]
# SPI SS引脚
set_property IOSTANDARD LVCMOS33 [get_ports spi_ss]
set_property PACKAGE_PIN M5 [get_ports spi_ss]
# SPI CLK引脚
set_property IOSTANDARD LVCMOS33 [get_ports spi_clk]
set_property PACKAGE_PIN N4 [get_ports spi_clk]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property CONFIG_MODE SPIx4 [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

View File

@ -16,53 +16,41 @@
`include "defines.v"
// core local interruptor module
//
module clint(
input wire clk,
input wire rst,
input wire rst_n,
// from core
input wire[`INT_BUS] int_flag_i, //
input wire[`INT_WIDTH-1:0] int_flag_i, //
// from id
input wire[`InstBus] inst_i, //
input wire[`InstAddrBus] inst_addr_i, //
// from ex
// from exu
input wire inst_ecall_i, // ecall
input wire inst_ebreak_i, // ebreak
input wire inst_mret_i, // mret
input wire[31:0] inst_addr_i, //
input wire jump_flag_i,
input wire[`InstAddrBus] jump_addr_i,
input wire div_started_i,
// from ctrl
input wire[`Hold_Flag_Bus] hold_flag_i, // 线
input wire mem_access_misaligned_i,
// from csr_reg
input wire[`RegBus] data_i, // CSR
input wire[`RegBus] csr_mtvec, // mtvec
input wire[`RegBus] csr_mepc, // mepc
input wire[`RegBus] csr_mstatus, // mstatus
input wire global_int_en_i, // 使
// to ctrl
output wire hold_flag_o, // 线
input wire[31:0] csr_mtvec_i, // mtvec
input wire[31:0] csr_mepc_i, // mepc
input wire[31:0] csr_mstatus_i, // mstatus
// to csr_reg
output reg we_o, // CSR
output reg[`MemAddrBus] waddr_o, // CSR
output reg[`MemAddrBus] raddr_o, // CSR
output reg[`RegBus] data_o, // CSR
output reg csr_we_o, // CSR
output reg[31:0] csr_waddr_o, // CSR
output reg[31:0] csr_wdata_o, // CSR
// to ex
output reg[`InstAddrBus] int_addr_o, //
output reg int_assert_o //
// to pipe_ctrl
output wire stall_flag_o, // 线
output wire[31:0] int_addr_o, //
output wire int_assert_o //
);
//
localparam S_INT_IDLE = 4'b0001;
localparam S_INT_SYNC_ASSERT = 4'b0010;
@ -78,81 +66,80 @@ module clint(
reg[3:0] int_state;
reg[4:0] csr_state;
reg[`InstAddrBus] inst_addr;
reg[31:0] inst_addr;
reg[31:0] cause;
wire global_int_en = csr_mstatus_i[3];
assign hold_flag_o = ((int_state != S_INT_IDLE) | (csr_state != S_CSR_IDLE))? `HoldEnable: `HoldDisable;
assign stall_flag_o = ((int_state != S_INT_IDLE) | (csr_state != S_CSR_IDLE))? 1'b1: 1'b0;
// 线
wire pc_state_jump_flag;
gen_rst_0_dff #(1) pc_state_dff(clk, rst_n, jump_flag_i, pc_state_jump_flag);
wire if_state_jump_flag;
gen_rst_0_dff #(1) if_state_dff(clk, rst_n, pc_state_jump_flag, if_state_jump_flag);
wire id_state_jump_flag;
gen_rst_0_dff #(1) id_state_dff(clk, rst_n, if_state_jump_flag, id_state_jump_flag);
wire ex_state_jump_flag;
gen_rst_0_dff #(1) ex_state_dff(clk, rst_n, id_state_jump_flag, ex_state_jump_flag);
wire[3:0] state_jump_flag = {pc_state_jump_flag, if_state_jump_flag, id_state_jump_flag, ex_state_jump_flag};
// 线
wire inst_addr_valid = (~(|state_jump_flag)) | ex_state_jump_flag;
//
always @ (*) begin
if (rst == `RstEnable) begin
int_state = S_INT_IDLE;
//
if (inst_ecall_i | inst_ebreak_i | mem_access_misaligned_i) begin
int_state = S_INT_SYNC_ASSERT;
//
end else if ((int_flag_i != `INT_NONE) & global_int_en & inst_addr_valid) begin
int_state = S_INT_ASYNC_ASSERT;
//
end else if (inst_mret_i) begin
int_state = S_INT_MRET;
//
end else begin
if (inst_i == `INST_ECALL || inst_i == `INST_EBREAK) begin
//
if (div_started_i == `DivStop) begin
int_state = S_INT_SYNC_ASSERT;
end else begin
int_state = S_INT_IDLE;
end
end else if (int_flag_i != `INT_NONE && global_int_en_i == `True) begin
int_state = S_INT_ASYNC_ASSERT;
end else if (inst_i == `INST_MRET) begin
int_state = S_INT_MRET;
end else begin
int_state = S_INT_IDLE;
end
int_state = S_INT_IDLE;
end
end
// CSR
always @ (posedge clk) begin
if (rst == `RstEnable) begin
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
csr_state <= S_CSR_IDLE;
cause <= `ZeroWord;
inst_addr <= `ZeroWord;
cause <= 32'h0;
inst_addr <= 32'h0;
end else begin
case (csr_state)
S_CSR_IDLE: begin
//
if (int_state == S_INT_SYNC_ASSERT) begin
csr_state <= S_CSR_MEPC;
// 4
if (jump_flag_i == `JumpEnable) begin
inst_addr <= jump_addr_i - 4'h4;
end else begin
case (int_state)
//
S_INT_SYNC_ASSERT: begin
csr_state <= S_CSR_MEPC;
// 4
inst_addr <= inst_addr_i;
cause <= inst_ebreak_i? 32'd3:
inst_ecall_i? 32'd11:
mem_access_misaligned_i? 32'd4:
32'd10;
end
case (inst_i)
`INST_ECALL: begin
cause <= 32'd11;
end
`INST_EBREAK: begin
cause <= 32'd3;
end
default: begin
cause <= 32'd10;
end
endcase
//
end else if (int_state == S_INT_ASYNC_ASSERT) begin
//
cause <= 32'h80000004;
csr_state <= S_CSR_MEPC;
if (jump_flag_i == `JumpEnable) begin
inst_addr <= jump_addr_i;
//
end else if (div_started_i == `DivStart) begin
inst_addr <= inst_addr_i - 4'h4;
end else begin
//
S_INT_ASYNC_ASSERT: begin
csr_state <= S_CSR_MEPC;
inst_addr <= inst_addr_i;
//
cause <= 32'h80000004;
end
//
end else if (int_state == S_INT_MRET) begin
csr_state <= S_CSR_MSTATUS_MRET;
end
//
S_INT_MRET: begin
csr_state <= S_CSR_MSTATUS_MRET;
end
endcase
end
S_CSR_MEPC: begin
csr_state <= S_CSR_MSTATUS;
@ -174,69 +161,63 @@ module clint(
end
// CSR
always @ (posedge clk) begin
if (rst == `RstEnable) begin
we_o <= `WriteDisable;
waddr_o <= `ZeroWord;
data_o <= `ZeroWord;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
csr_we_o <= 1'b0;
csr_waddr_o <= 32'h0;
csr_wdata_o <= 32'h0;
end else begin
case (csr_state)
// mepc
S_CSR_MEPC: begin
we_o <= `WriteEnable;
waddr_o <= {20'h0, `CSR_MEPC};
data_o <= inst_addr;
csr_we_o <= 1'b1;
csr_waddr_o <= {20'h0, `CSR_MEPC};
csr_wdata_o <= inst_addr;
end
//
S_CSR_MCAUSE: begin
we_o <= `WriteEnable;
waddr_o <= {20'h0, `CSR_MCAUSE};
data_o <= cause;
csr_we_o <= 1'b1;
csr_waddr_o <= {20'h0, `CSR_MCAUSE};
csr_wdata_o <= cause;
end
//
S_CSR_MSTATUS: begin
we_o <= `WriteEnable;
waddr_o <= {20'h0, `CSR_MSTATUS};
data_o <= {csr_mstatus[31:4], 1'b0, csr_mstatus[2:0]};
csr_we_o <= 1'b1;
csr_waddr_o <= {20'h0, `CSR_MSTATUS};
csr_wdata_o <= {csr_mstatus_i[31:4], 1'b0, csr_mstatus_i[2:0]};
end
//
S_CSR_MSTATUS_MRET: begin
we_o <= `WriteEnable;
waddr_o <= {20'h0, `CSR_MSTATUS};
data_o <= {csr_mstatus[31:4], csr_mstatus[7], csr_mstatus[2:0]};
csr_we_o <= 1'b1;
csr_waddr_o <= {20'h0, `CSR_MSTATUS};
csr_wdata_o <= {csr_mstatus_i[31:4], csr_mstatus_i[7], csr_mstatus_i[2:0]};
end
default: begin
we_o <= `WriteDisable;
waddr_o <= `ZeroWord;
data_o <= `ZeroWord;
csr_we_o <= 1'b0;
csr_waddr_o <= 32'h0;
csr_wdata_o <= 32'h0;
end
endcase
end
end
// ex
always @ (posedge clk) begin
if (rst == `RstEnable) begin
int_assert_o <= `INT_DEASSERT;
int_addr_o <= `ZeroWord;
reg in_int_context;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
in_int_context <= 1'b0;
end else begin
case (csr_state)
// .mcause
S_CSR_MCAUSE: begin
int_assert_o <= `INT_ASSERT;
int_addr_o <= csr_mtvec;
end
//
S_CSR_MSTATUS_MRET: begin
int_assert_o <= `INT_ASSERT;
int_addr_o <= csr_mepc;
end
default: begin
int_assert_o <= `INT_DEASSERT;
int_addr_o <= `ZeroWord;
end
endcase
if (csr_state == S_CSR_MSTATUS_MRET) begin
in_int_context <= 1'b0;
end else if (csr_state != S_CSR_IDLE) begin
in_int_context <= 1'b1;
end
end
end
assign int_assert_o = (csr_state == S_CSR_MCAUSE) | (csr_state == S_CSR_MSTATUS_MRET);
assign int_addr_o = (csr_state == S_CSR_MCAUSE)? csr_mtvec_i:
(csr_state == S_CSR_MSTATUS_MRET)? csr_mepc_i:
32'h0;
endmodule

View File

@ -20,196 +20,121 @@
module csr_reg(
input wire clk,
input wire rst,
input wire rst_n,
// form ex
input wire we_i, // ex
input wire[`MemAddrBus] raddr_i, // ex
input wire[`MemAddrBus] waddr_i, // ex
input wire[`RegBus] data_i, // ex
// exu
input wire exu_we_i, // exu
input wire[31:0] exu_waddr_i, // exu
input wire[31:0] exu_wdata_i, // exu
input wire[31:0] exu_raddr_i, // exu
output wire[31:0] exu_rdata_o, // exu
// from clint
// clint
input wire clint_we_i, // clint
input wire[`MemAddrBus] clint_raddr_i, // clint
input wire[`MemAddrBus] clint_waddr_i, // clint
input wire[`RegBus] clint_data_i, // clint
output wire global_int_en_o, // 使
// to clint
output reg[`RegBus] clint_data_o, // clint
output wire[`RegBus] clint_csr_mtvec, // mtvec
output wire[`RegBus] clint_csr_mepc, // mepc
output wire[`RegBus] clint_csr_mstatus, // mstatus
// to ex
output reg[`RegBus] data_o // ex
input wire[31:0] clint_waddr_i, // clint
input wire[31:0] clint_wdata_i, // clint
output wire[31:0] mtvec_o, // mtvec
output wire[31:0] mepc_o, // mepc
output wire[31:0] mstatus_o // mstatus
);
reg[`DoubleRegBus] cycle;
reg[`RegBus] mtvec;
reg[`RegBus] mcause;
reg[`RegBus] mepc;
reg[`RegBus] mie;
reg[`RegBus] mstatus;
reg[`RegBus] mscratch;
reg[63:0] cycle;
reg[31:0] mtvec;
reg[31:0] mcause;
reg[31:0] mepc;
reg[31:0] mie;
reg[31:0] mstatus;
reg[31:0] mscratch;
assign global_int_en_o = (mstatus[3] == 1'b1)? `True: `False;
assign clint_csr_mtvec = mtvec;
assign clint_csr_mepc = mepc;
assign clint_csr_mstatus = mstatus;
assign mtvec_o = mtvec;
assign mepc_o = mepc;
assign mstatus_o = mstatus;
// cycle counter
//
always @ (posedge clk) begin
if (rst == `RstEnable) begin
cycle <= {`ZeroWord, `ZeroWord};
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
cycle <= {32'h0, 32'h0};
end else begin
cycle <= cycle + 1'b1;
end
end
// write reg
//
always @ (posedge clk) begin
if (rst == `RstEnable) begin
mtvec <= `ZeroWord;
mcause <= `ZeroWord;
mepc <= `ZeroWord;
mie <= `ZeroWord;
mstatus <= `ZeroWord;
mscratch <= `ZeroWord;
wire we = exu_we_i | clint_we_i;
wire[31:0] waddr = exu_we_i? exu_waddr_i: clint_waddr_i;
wire[31:0] wdata = exu_we_i? exu_wdata_i: clint_wdata_i;
//
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
mtvec <= 32'h0;
mcause <= 32'h0;
mepc <= 32'h0;
mie <= 32'h0;
mstatus <= 32'h0;
mscratch <= 32'h0;
end else begin
// ex
if (we_i == `WriteEnable) begin
case (waddr_i[11:0])
if (we) begin
case (waddr[11:0])
`CSR_MTVEC: begin
mtvec <= data_i;
mtvec <= wdata;
end
`CSR_MCAUSE: begin
mcause <= data_i;
mcause <= wdata;
end
`CSR_MEPC: begin
mepc <= data_i;
mepc <= wdata;
end
`CSR_MIE: begin
mie <= data_i;
mie <= wdata;
end
`CSR_MSTATUS: begin
mstatus <= data_i;
mstatus <= wdata;
end
`CSR_MSCRATCH: begin
mscratch <= data_i;
end
default: begin
end
endcase
// clint
end else if (clint_we_i == `WriteEnable) begin
case (clint_waddr_i[11:0])
`CSR_MTVEC: begin
mtvec <= clint_data_i;
end
`CSR_MCAUSE: begin
mcause <= clint_data_i;
end
`CSR_MEPC: begin
mepc <= clint_data_i;
end
`CSR_MIE: begin
mie <= clint_data_i;
end
`CSR_MSTATUS: begin
mstatus <= clint_data_i;
end
`CSR_MSCRATCH: begin
mscratch <= clint_data_i;
end
default: begin
mscratch <= wdata;
end
endcase
end
end
end
// read reg
// exCSR
reg[31:0] exu_rdata;
// exuCSR
always @ (*) begin
if ((waddr_i[11:0] == raddr_i[11:0]) && (we_i == `WriteEnable)) begin
data_o = data_i;
end else begin
case (raddr_i[11:0])
`CSR_CYCLE: begin
data_o = cycle[31:0];
end
`CSR_CYCLEH: begin
data_o = cycle[63:32];
end
`CSR_MTVEC: begin
data_o = mtvec;
end
`CSR_MCAUSE: begin
data_o = mcause;
end
`CSR_MEPC: begin
data_o = mepc;
end
`CSR_MIE: begin
data_o = mie;
end
`CSR_MSTATUS: begin
data_o = mstatus;
end
`CSR_MSCRATCH: begin
data_o = mscratch;
end
default: begin
data_o = `ZeroWord;
end
endcase
end
case (exu_raddr_i[11:0])
`CSR_CYCLE: begin
exu_rdata = cycle[31:0];
end
`CSR_CYCLEH: begin
exu_rdata = cycle[63:32];
end
`CSR_MTVEC: begin
exu_rdata = mtvec;
end
`CSR_MCAUSE: begin
exu_rdata = mcause;
end
`CSR_MEPC: begin
exu_rdata = mepc;
end
`CSR_MIE: begin
exu_rdata = mie;
end
`CSR_MSTATUS: begin
exu_rdata = mstatus;
end
`CSR_MSCRATCH: begin
exu_rdata = mscratch;
end
default: begin
exu_rdata = 32'h0;
end
endcase
end
// read reg
// clintCSR
always @ (*) begin
if ((clint_waddr_i[11:0] == clint_raddr_i[11:0]) && (clint_we_i == `WriteEnable)) begin
clint_data_o = clint_data_i;
end else begin
case (clint_raddr_i[11:0])
`CSR_CYCLE: begin
clint_data_o = cycle[31:0];
end
`CSR_CYCLEH: begin
clint_data_o = cycle[63:32];
end
`CSR_MTVEC: begin
clint_data_o = mtvec;
end
`CSR_MCAUSE: begin
clint_data_o = mcause;
end
`CSR_MEPC: begin
clint_data_o = mepc;
end
`CSR_MIE: begin
clint_data_o = mie;
end
`CSR_MSTATUS: begin
clint_data_o = mstatus;
end
`CSR_MSCRATCH: begin
clint_data_o = mscratch;
end
default: begin
clint_data_o = `ZeroWord;
end
endcase
end
end
assign exu_rdata_o = exu_rdata;
endmodule

View File

@ -1,68 +0,0 @@
/*
Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
//
// 线
module ctrl(
input wire rst,
// from ex
input wire jump_flag_i,
input wire[`InstAddrBus] jump_addr_i,
input wire hold_flag_ex_i,
// from rib
input wire hold_flag_rib_i,
// from jtag
input wire jtag_halt_flag_i,
// from clint
input wire hold_flag_clint_i,
output reg[`Hold_Flag_Bus] hold_flag_o,
// to pc_reg
output reg jump_flag_o,
output reg[`InstAddrBus] jump_addr_o
);
always @ (*) begin
jump_addr_o = jump_addr_i;
jump_flag_o = jump_flag_i;
//
hold_flag_o = `Hold_None;
//
if (jump_flag_i == `JumpEnable || hold_flag_ex_i == `HoldEnable || hold_flag_clint_i == `HoldEnable) begin
// 线
hold_flag_o = `Hold_Id;
end else if (hold_flag_rib_i == `HoldEnable) begin
// PC
hold_flag_o = `Hold_Pc;
end else if (jtag_halt_flag_i == `HoldEnable) begin
// 线
hold_flag_o = `Hold_Id;
end else begin
hold_flag_o = `Hold_None;
end
end
endmodule

View File

@ -14,151 +14,109 @@
limitations under the License.
*/
`define CpuResetAddr 32'h0
`define CPU_RESET_ADDR 32'h0 // CPU
`define CPU_CLOCK_HZ 50000000 // CPU(50MHZ)
`define INST_MEM_START_ADDR 32'h0 //
`define INST_MEM_END_ADDR 32'h0fffffff //
`define JTAG_RESET_FF_LEVELS 5
`define RstEnable 1'b0
`define RstDisable 1'b1
`define ZeroWord 32'h0
`define ZeroReg 5'h0
`define WriteEnable 1'b1
`define WriteDisable 1'b0
`define ReadEnable 1'b1
`define ReadDisable 1'b0
`define True 1'b1
`define False 1'b0
`define ChipEnable 1'b1
`define ChipDisable 1'b0
`define JumpEnable 1'b1
`define JumpDisable 1'b0
`define DivResultNotReady 1'b0
`define DivResultReady 1'b1
`define DivStart 1'b1
`define DivStop 1'b0
`define HoldEnable 1'b1
`define HoldDisable 1'b0
`define Stop 1'b1
`define NoStop 1'b0
`define RIB_ACK 1'b1
`define RIB_NACK 1'b0
`define RIB_REQ 1'b1
`define RIB_NREQ 1'b0
`define INT_ASSERT 1'b1
`define INT_DEASSERT 1'b0
`define ROM_DEPTH 8192 // word(4)
`define RAM_DEPTH 4096 // word(4)
`define INT_BUS 7:0
`define INT_NONE 8'h0
`define INT_RET 8'hff
`define INT_TIMER0 8'b00000001
`define INT_TIMER0_ENTRY_ADDR 32'h4
`define INT_WIDTH 8
`define INT_NONE 8'h0
`define Hold_Flag_Bus 2:0
`define Hold_None 3'b000
`define Hold_Pc 3'b001
`define Hold_If 3'b010
`define Hold_Id 3'b011
`define STALL_WIDTH 4
`define STALL_PC 2'd0
`define STALL_IF 2'd1
`define STALL_ID 2'd2
`define STALL_EX 2'd3
// I type inst
`define INST_TYPE_I 7'b0010011
`define INST_ADDI 3'b000
`define INST_SLTI 3'b010
`define INST_SLTIU 3'b011
`define INST_XORI 3'b100
`define INST_ORI 3'b110
`define INST_ANDI 3'b111
`define INST_SLLI 3'b001
`define INST_SRI 3'b101
`define INST_NOP 32'h00000013
`define INST_MRET 32'h30200073
`define INST_ECALL 32'h00000073
`define INST_EBREAK 32'h00100073
// L type inst
`define INST_TYPE_L 7'b0000011
`define INST_LB 3'b000
`define INST_LH 3'b001
`define INST_LW 3'b010
`define INST_LBU 3'b100
`define INST_LHU 3'b101
//
`define DECINFO_GRP_BUS 2:0
`define DECINFO_GRP_WIDTH 3
`define DECINFO_GRP_ALU `DECINFO_GRP_WIDTH'd1
`define DECINFO_GRP_BJP `DECINFO_GRP_WIDTH'd2
`define DECINFO_GRP_MULDIV `DECINFO_GRP_WIDTH'd3
`define DECINFO_GRP_CSR `DECINFO_GRP_WIDTH'd4
`define DECINFO_GRP_MEM `DECINFO_GRP_WIDTH'd5
`define DECINFO_GRP_SYS `DECINFO_GRP_WIDTH'd6
// S type inst
`define INST_TYPE_S 7'b0100011
`define INST_SB 3'b000
`define INST_SH 3'b001
`define INST_SW 3'b010
`define DECINFO_ALU_BUS_WIDTH (`DECINFO_GRP_WIDTH+14)
`define DECINFO_ALU_LUI (`DECINFO_GRP_WIDTH+0)
`define DECINFO_ALU_AUIPC (`DECINFO_GRP_WIDTH+1)
`define DECINFO_ALU_ADD (`DECINFO_GRP_WIDTH+2)
`define DECINFO_ALU_SUB (`DECINFO_GRP_WIDTH+3)
`define DECINFO_ALU_SLL (`DECINFO_GRP_WIDTH+4)
`define DECINFO_ALU_SLT (`DECINFO_GRP_WIDTH+5)
`define DECINFO_ALU_SLTU (`DECINFO_GRP_WIDTH+6)
`define DECINFO_ALU_XOR (`DECINFO_GRP_WIDTH+7)
`define DECINFO_ALU_SRL (`DECINFO_GRP_WIDTH+8)
`define DECINFO_ALU_SRA (`DECINFO_GRP_WIDTH+9)
`define DECINFO_ALU_OR (`DECINFO_GRP_WIDTH+10)
`define DECINFO_ALU_AND (`DECINFO_GRP_WIDTH+11)
`define DECINFO_ALU_OP2IMM (`DECINFO_GRP_WIDTH+12)
`define DECINFO_ALU_OP1PC (`DECINFO_GRP_WIDTH+13)
// R and M type inst
`define INST_TYPE_R_M 7'b0110011
// R type inst
`define INST_ADD_SUB 3'b000
`define INST_SLL 3'b001
`define INST_SLT 3'b010
`define INST_SLTU 3'b011
`define INST_XOR 3'b100
`define INST_SR 3'b101
`define INST_OR 3'b110
`define INST_AND 3'b111
// M type inst
`define INST_MUL 3'b000
`define INST_MULH 3'b001
`define INST_MULHSU 3'b010
`define INST_MULHU 3'b011
`define INST_DIV 3'b100
`define INST_DIVU 3'b101
`define INST_REM 3'b110
`define INST_REMU 3'b111
`define DECINFO_BJP_BUS_WIDTH (`DECINFO_GRP_WIDTH+8)
`define DECINFO_BJP_JUMP (`DECINFO_GRP_WIDTH+0)
`define DECINFO_BJP_BEQ (`DECINFO_GRP_WIDTH+1)
`define DECINFO_BJP_BNE (`DECINFO_GRP_WIDTH+2)
`define DECINFO_BJP_BLT (`DECINFO_GRP_WIDTH+3)
`define DECINFO_BJP_BGE (`DECINFO_GRP_WIDTH+4)
`define DECINFO_BJP_BLTU (`DECINFO_GRP_WIDTH+5)
`define DECINFO_BJP_BGEU (`DECINFO_GRP_WIDTH+6)
`define DECINFO_BJP_OP1RS1 (`DECINFO_GRP_WIDTH+7)
// J type inst
`define INST_JAL 7'b1101111
`define INST_JALR 7'b1100111
`define DECINFO_MULDIV_BUS_WIDTH (`DECINFO_GRP_WIDTH+8)
`define DECINFO_MULDIV_MUL (`DECINFO_GRP_WIDTH+0)
`define DECINFO_MULDIV_MULH (`DECINFO_GRP_WIDTH+1)
`define DECINFO_MULDIV_MULHSU (`DECINFO_GRP_WIDTH+2)
`define DECINFO_MULDIV_MULHU (`DECINFO_GRP_WIDTH+3)
`define DECINFO_MULDIV_DIV (`DECINFO_GRP_WIDTH+4)
`define DECINFO_MULDIV_DIVU (`DECINFO_GRP_WIDTH+5)
`define DECINFO_MULDIV_REM (`DECINFO_GRP_WIDTH+6)
`define DECINFO_MULDIV_REMU (`DECINFO_GRP_WIDTH+7)
`define INST_LUI 7'b0110111
`define INST_AUIPC 7'b0010111
`define INST_NOP 32'h00000001
`define INST_NOP_OP 7'b0000001
`define INST_MRET 32'h30200073
`define INST_RET 32'h00008067
`define DECINFO_CSR_BUS_WIDTH (`DECINFO_GRP_WIDTH+16)
`define DECINFO_CSR_CSRRW (`DECINFO_GRP_WIDTH+0)
`define DECINFO_CSR_CSRRS (`DECINFO_GRP_WIDTH+1)
`define DECINFO_CSR_CSRRC (`DECINFO_GRP_WIDTH+2)
`define DECINFO_CSR_RS1IMM (`DECINFO_GRP_WIDTH+3)
`define DECINFO_CSR_CSRADDR `DECINFO_GRP_WIDTH+4+12-1:`DECINFO_GRP_WIDTH+4
`define INST_FENCE 7'b0001111
`define INST_ECALL 32'h73
`define INST_EBREAK 32'h00100073
`define DECINFO_MEM_BUS_WIDTH (`DECINFO_GRP_WIDTH+8)
`define DECINFO_MEM_LB (`DECINFO_GRP_WIDTH+0)
`define DECINFO_MEM_LH (`DECINFO_GRP_WIDTH+1)
`define DECINFO_MEM_LW (`DECINFO_GRP_WIDTH+2)
`define DECINFO_MEM_LBU (`DECINFO_GRP_WIDTH+3)
`define DECINFO_MEM_LHU (`DECINFO_GRP_WIDTH+4)
`define DECINFO_MEM_SB (`DECINFO_GRP_WIDTH+5)
`define DECINFO_MEM_SH (`DECINFO_GRP_WIDTH+6)
`define DECINFO_MEM_SW (`DECINFO_GRP_WIDTH+7)
// J type inst
`define INST_TYPE_B 7'b1100011
`define INST_BEQ 3'b000
`define INST_BNE 3'b001
`define INST_BLT 3'b100
`define INST_BGE 3'b101
`define INST_BLTU 3'b110
`define INST_BGEU 3'b111
`define DECINFO_SYS_BUS_WIDTH (`DECINFO_GRP_WIDTH+5)
`define DECINFO_SYS_ECALL (`DECINFO_GRP_WIDTH+0)
`define DECINFO_SYS_EBREAK (`DECINFO_GRP_WIDTH+1)
`define DECINFO_SYS_NOP (`DECINFO_GRP_WIDTH+2)
`define DECINFO_SYS_MRET (`DECINFO_GRP_WIDTH+3)
`define DECINFO_SYS_FENCE (`DECINFO_GRP_WIDTH+4)
// CSR inst
`define INST_CSR 7'b1110011
`define INST_CSRRW 3'b001
`define INST_CSRRS 3'b010
`define INST_CSRRC 3'b011
`define INST_CSRRWI 3'b101
`define INST_CSRRSI 3'b110
`define INST_CSRRCI 3'b111
//
`define DECINFO_WIDTH `DECINFO_CSR_BUS_WIDTH
// CSR reg addr
`define CSR_CYCLE 12'hc00
`define CSR_CYCLEH 12'hc80
`define CSR_MTVEC 12'h305
`define CSR_MCAUSE 12'h342
`define CSR_MEPC 12'h341
`define CSR_MIE 12'h304
`define CSR_MSTATUS 12'h300
`define CSR_MSCRATCH 12'h340
// CSR
`define CSR_CYCLE 12'hc00
`define CSR_CYCLEH 12'hc80
`define CSR_MTVEC 12'h305
`define CSR_MCAUSE 12'h342
`define CSR_MEPC 12'h341
`define CSR_MIE 12'h304
`define CSR_MSTATUS 12'h300
`define CSR_MSCRATCH 12'h340
`define RomNum 4096 // rom depth(how many words)
`define MemNum 4096 // memory depth(how many words)
`define MemBus 31:0
`define MemAddrBus 31:0
`define InstBus 31:0
`define InstAddrBus 31:0
// common regs
`define RegAddrBus 4:0
`define RegBus 31:0
`define DoubleRegBus 63:0
`define RegWidth 32
`define RegNum 32 // reg num
`define RegNumLog2 5

View File

@ -19,23 +19,18 @@
//
// 32
// 33
module div(
module divider(
input wire clk,
input wire rst,
input wire rst_n,
// from ex
input wire[`RegBus] dividend_i, //
input wire[`RegBus] divisor_i, //
input wire start_i, //
input wire[2:0] op_i, //
input wire[`RegAddrBus] reg_waddr_i, //
input wire[31:0] dividend_i, //
input wire[31:0] divisor_i, //
input wire start_i, //
input wire[3:0] op_i, //
// to ex
output reg[`RegBus] result_o, // 3232
output reg ready_o, //
output reg busy_o, //
output reg[`RegAddrBus] reg_waddr_o //
output reg[31:0] result_o, // 3232
output reg ready_o //
);
@ -45,20 +40,20 @@ module div(
localparam STATE_CALC = 4'b0100;
localparam STATE_END = 4'b1000;
reg[`RegBus] dividend_r;
reg[`RegBus] divisor_r;
reg[2:0] op_r;
reg[31:0] dividend_r;
reg[31:0] divisor_r;
reg[3:0] op_r;
reg[3:0] state;
reg[31:0] count;
reg[`RegBus] div_result;
reg[`RegBus] div_remain;
reg[`RegBus] minuend;
reg[31:0] div_result;
reg[31:0] div_remain;
reg[31:0] minuend;
reg invert_result;
wire op_div = (op_r == `INST_DIV);
wire op_divu = (op_r == `INST_DIVU);
wire op_rem = (op_r == `INST_REM);
wire op_remu = (op_r == `INST_REMU);
wire op_div = op_r[3];
wire op_divu = op_r[2];
wire op_rem = op_r[1];
wire op_remu = op_r[0];
wire[31:0] dividend_invert = (-dividend_r);
wire[31:0] divisor_invert = (-divisor_r);
@ -68,61 +63,53 @@ module div(
wire[31:0] minuend_tmp = minuend_ge_divisor? minuend_sub_res[30:0]: minuend[30:0];
//
always @ (posedge clk) begin
if (rst == `RstEnable) begin
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= STATE_IDLE;
ready_o <= `DivResultNotReady;
result_o <= `ZeroWord;
div_result <= `ZeroWord;
div_remain <= `ZeroWord;
ready_o <= 1'b0;
result_o <= 32'h0;
div_result <= 32'h0;
div_remain <= 32'h0;
op_r <= 3'h0;
reg_waddr_o <= `ZeroWord;
dividend_r <= `ZeroWord;
divisor_r <= `ZeroWord;
minuend <= `ZeroWord;
dividend_r <= 32'h0;
divisor_r <= 32'h0;
minuend <= 32'h0;
invert_result <= 1'b0;
busy_o <= `False;
count <= `ZeroWord;
count <= 32'h0;
end else begin
case (state)
STATE_IDLE: begin
if (start_i == `DivStart) begin
if (start_i) begin
op_r <= op_i;
dividend_r <= dividend_i;
divisor_r <= divisor_i;
reg_waddr_o <= reg_waddr_i;
state <= STATE_START;
busy_o <= `True;
end else begin
op_r <= 3'h0;
reg_waddr_o <= `ZeroWord;
dividend_r <= `ZeroWord;
divisor_r <= `ZeroWord;
ready_o <= `DivResultNotReady;
result_o <= `ZeroWord;
busy_o <= `False;
dividend_r <= 32'h0;
divisor_r <= 32'h0;
ready_o <= 1'b0;
result_o <= 32'h0;
end
end
STATE_START: begin
if (start_i == `DivStart) begin
if (start_i) begin
// 0
if (divisor_r == `ZeroWord) begin
if (divisor_r == 32'h0) begin
if (op_div | op_divu) begin
result_o <= 32'hffffffff;
end else begin
result_o <= dividend_r;
end
ready_o <= `DivResultReady;
ready_o <= 1'b1;
state <= STATE_IDLE;
busy_o <= `False;
// 0
end else begin
busy_o <= `True;
count <= 32'h40000000;
state <= STATE_CALC;
div_result <= `ZeroWord;
div_remain <= `ZeroWord;
div_result <= 32'h0;
div_remain <= 32'h0;
// DIVREM
if (op_div | op_rem) begin
@ -151,14 +138,13 @@ module div(
end
end else begin
state <= STATE_IDLE;
result_o <= `ZeroWord;
ready_o <= `DivResultNotReady;
busy_o <= `False;
result_o <= 32'h0;
ready_o <= 1'b0;
end
end
STATE_CALC: begin
if (start_i == `DivStart) begin
if (start_i) begin
dividend_r <= {dividend_r[30:0], 1'b0};
div_result <= div_result_tmp;
count <= {1'b0, count[31:1]};
@ -174,17 +160,15 @@ module div(
end
end else begin
state <= STATE_IDLE;
result_o <= `ZeroWord;
ready_o <= `DivResultNotReady;
busy_o <= `False;
result_o <= 32'h0;
ready_o <= 1'b0;
end
end
STATE_END: begin
if (start_i == `DivStart) begin
ready_o <= `DivResultReady;
if (start_i) begin
ready_o <= 1'b1;
state <= STATE_IDLE;
busy_o <= `False;
if (op_div | op_divu) begin
if (invert_result) begin
result_o <= (-div_result);
@ -200,9 +184,8 @@ module div(
end
end else begin
state <= STATE_IDLE;
result_o <= `ZeroWord;
ready_o <= `DivResultNotReady;
busy_o <= `False;
result_o <= 32'h0;
ready_o <= 1'b0;
end
end

View File

@ -1,875 +0,0 @@
/*
Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
//
//
module ex(
input wire rst,
// from id
input wire[`InstBus] inst_i, //
input wire[`InstAddrBus] inst_addr_i, //
input wire reg_we_i, //
input wire[`RegAddrBus] reg_waddr_i, //
input wire[`RegBus] reg1_rdata_i, // 1
input wire[`RegBus] reg2_rdata_i, // 2
input wire csr_we_i, // CSR
input wire[`MemAddrBus] csr_waddr_i, // CSR
input wire[`RegBus] csr_rdata_i, // CSR
input wire int_assert_i, //
input wire[`InstAddrBus] int_addr_i, //
input wire[`MemAddrBus] op1_i,
input wire[`MemAddrBus] op2_i,
input wire[`MemAddrBus] op1_jump_i,
input wire[`MemAddrBus] op2_jump_i,
// from mem
input wire[`MemBus] mem_rdata_i, //
// from div
input wire div_ready_i, //
input wire[`RegBus] div_result_i, //
input wire div_busy_i, //
input wire[`RegAddrBus] div_reg_waddr_i,//
// to mem
output reg[`MemBus] mem_wdata_o, //
output reg[`MemAddrBus] mem_raddr_o, //
output reg[`MemAddrBus] mem_waddr_o, //
output wire mem_we_o, //
output wire mem_req_o, // 访
// to regs
output wire[`RegBus] reg_wdata_o, //
output wire reg_we_o, //
output wire[`RegAddrBus] reg_waddr_o, //
// to csr reg
output reg[`RegBus] csr_wdata_o, // CSR
output wire csr_we_o, // CSR
output wire[`MemAddrBus] csr_waddr_o, // CSR
// to div
output wire div_start_o, //
output reg[`RegBus] div_dividend_o, //
output reg[`RegBus] div_divisor_o, //
output reg[2:0] div_op_o, //
output reg[`RegAddrBus] div_reg_waddr_o,//
// to ctrl
output wire hold_flag_o, //
output wire jump_flag_o, //
output wire[`InstAddrBus] jump_addr_o //
);
wire[1:0] mem_raddr_index;
wire[1:0] mem_waddr_index;
wire[`DoubleRegBus] mul_temp;
wire[`DoubleRegBus] mul_temp_invert;
wire[31:0] sr_shift;
wire[31:0] sri_shift;
wire[31:0] sr_shift_mask;
wire[31:0] sri_shift_mask;
wire[31:0] op1_add_op2_res;
wire[31:0] op1_jump_add_op2_jump_res;
wire[31:0] reg1_data_invert;
wire[31:0] reg2_data_invert;
wire op1_ge_op2_signed;
wire op1_ge_op2_unsigned;
wire op1_eq_op2;
reg[`RegBus] mul_op1;
reg[`RegBus] mul_op2;
wire[6:0] opcode;
wire[2:0] funct3;
wire[6:0] funct7;
wire[4:0] rd;
wire[4:0] uimm;
reg[`RegBus] reg_wdata;
reg reg_we;
reg[`RegAddrBus] reg_waddr;
reg[`RegBus] div_wdata;
reg div_we;
reg[`RegAddrBus] div_waddr;
reg div_hold_flag;
reg div_jump_flag;
reg[`InstAddrBus] div_jump_addr;
reg hold_flag;
reg jump_flag;
reg[`InstAddrBus] jump_addr;
reg mem_we;
reg mem_req;
reg div_start;
assign opcode = inst_i[6:0];
assign funct3 = inst_i[14:12];
assign funct7 = inst_i[31:25];
assign rd = inst_i[11:7];
assign uimm = inst_i[19:15];
assign sr_shift = reg1_rdata_i >> reg2_rdata_i[4:0];
assign sri_shift = reg1_rdata_i >> inst_i[24:20];
assign sr_shift_mask = 32'hffffffff >> reg2_rdata_i[4:0];
assign sri_shift_mask = 32'hffffffff >> inst_i[24:20];
assign op1_add_op2_res = op1_i + op2_i;
assign op1_jump_add_op2_jump_res = op1_jump_i + op2_jump_i;
assign reg1_data_invert = ~reg1_rdata_i + 1;
assign reg2_data_invert = ~reg2_rdata_i + 1;
//
assign op1_ge_op2_signed = $signed(op1_i) >= $signed(op2_i);
//
assign op1_ge_op2_unsigned = op1_i >= op2_i;
assign op1_eq_op2 = (op1_i == op2_i);
assign mul_temp = mul_op1 * mul_op2;
assign mul_temp_invert = ~mul_temp + 1;
assign mem_raddr_index = (reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:20]}) & 2'b11;
assign mem_waddr_index = (reg1_rdata_i + {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]}) & 2'b11;
assign div_start_o = (int_assert_i == `INT_ASSERT)? `DivStop: div_start;
assign reg_wdata_o = reg_wdata | div_wdata;
//
assign reg_we_o = (int_assert_i == `INT_ASSERT)? `WriteDisable: (reg_we || div_we);
assign reg_waddr_o = reg_waddr | div_waddr;
//
assign mem_we_o = (int_assert_i == `INT_ASSERT)? `WriteDisable: mem_we;
// 线访
assign mem_req_o = (int_assert_i == `INT_ASSERT)? `RIB_NREQ: mem_req;
assign hold_flag_o = hold_flag || div_hold_flag;
assign jump_flag_o = jump_flag || div_jump_flag || ((int_assert_i == `INT_ASSERT)? `JumpEnable: `JumpDisable);
assign jump_addr_o = (int_assert_i == `INT_ASSERT)? int_addr_i: (jump_addr | div_jump_addr);
// CSR
assign csr_we_o = (int_assert_i == `INT_ASSERT)? `WriteDisable: csr_we_i;
assign csr_waddr_o = csr_waddr_i;
//
always @ (*) begin
if ((opcode == `INST_TYPE_R_M) && (funct7 == 7'b0000001)) begin
case (funct3)
`INST_MUL, `INST_MULHU: begin
mul_op1 = reg1_rdata_i;
mul_op2 = reg2_rdata_i;
end
`INST_MULHSU: begin
mul_op1 = (reg1_rdata_i[31] == 1'b1)? (reg1_data_invert): reg1_rdata_i;
mul_op2 = reg2_rdata_i;
end
`INST_MULH: begin
mul_op1 = (reg1_rdata_i[31] == 1'b1)? (reg1_data_invert): reg1_rdata_i;
mul_op2 = (reg2_rdata_i[31] == 1'b1)? (reg2_data_invert): reg2_rdata_i;
end
default: begin
mul_op1 = reg1_rdata_i;
mul_op2 = reg2_rdata_i;
end
endcase
end else begin
mul_op1 = reg1_rdata_i;
mul_op2 = reg2_rdata_i;
end
end
//
always @ (*) begin
div_dividend_o = reg1_rdata_i;
div_divisor_o = reg2_rdata_i;
div_op_o = funct3;
div_reg_waddr_o = reg_waddr_i;
if ((opcode == `INST_TYPE_R_M) && (funct7 == 7'b0000001)) begin
div_we = `WriteDisable;
div_wdata = `ZeroWord;
div_waddr = `ZeroWord;
case (funct3)
`INST_DIV, `INST_DIVU, `INST_REM, `INST_REMU: begin
div_start = `DivStart;
div_jump_flag = `JumpEnable;
div_hold_flag = `HoldEnable;
div_jump_addr = op1_jump_add_op2_jump_res;
end
default: begin
div_start = `DivStop;
div_jump_flag = `JumpDisable;
div_hold_flag = `HoldDisable;
div_jump_addr = `ZeroWord;
end
endcase
end else begin
div_jump_flag = `JumpDisable;
div_jump_addr = `ZeroWord;
if (div_busy_i == `True) begin
div_start = `DivStart;
div_we = `WriteDisable;
div_wdata = `ZeroWord;
div_waddr = `ZeroWord;
div_hold_flag = `HoldEnable;
end else begin
div_start = `DivStop;
div_hold_flag = `HoldDisable;
if (div_ready_i == `DivResultReady) begin
div_wdata = div_result_i;
div_waddr = div_reg_waddr_i;
div_we = `WriteEnable;
end else begin
div_we = `WriteDisable;
div_wdata = `ZeroWord;
div_waddr = `ZeroWord;
end
end
end
end
//
always @ (*) begin
reg_we = reg_we_i;
reg_waddr = reg_waddr_i;
mem_req = `RIB_NREQ;
csr_wdata_o = `ZeroWord;
case (opcode)
`INST_TYPE_I: begin
case (funct3)
`INST_ADDI: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = op1_add_op2_res;
end
`INST_SLTI: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = {32{(~op1_ge_op2_signed)}} & 32'h1;
end
`INST_SLTIU: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = {32{(~op1_ge_op2_unsigned)}} & 32'h1;
end
`INST_XORI: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = op1_i ^ op2_i;
end
`INST_ORI: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = op1_i | op2_i;
end
`INST_ANDI: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = op1_i & op2_i;
end
`INST_SLLI: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = reg1_rdata_i << inst_i[24:20];
end
`INST_SRI: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
if (inst_i[30] == 1'b1) begin
reg_wdata = (sri_shift & sri_shift_mask) | ({32{reg1_rdata_i[31]}} & (~sri_shift_mask));
end else begin
reg_wdata = reg1_rdata_i >> inst_i[24:20];
end
end
default: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = `ZeroWord;
end
endcase
end
`INST_TYPE_R_M: begin
if ((funct7 == 7'b0000000) || (funct7 == 7'b0100000)) begin
case (funct3)
`INST_ADD_SUB: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
if (inst_i[30] == 1'b0) begin
reg_wdata = op1_add_op2_res;
end else begin
reg_wdata = op1_i - op2_i;
end
end
`INST_SLL: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = op1_i << op2_i[4:0];
end
`INST_SLT: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = {32{(~op1_ge_op2_signed)}} & 32'h1;
end
`INST_SLTU: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = {32{(~op1_ge_op2_unsigned)}} & 32'h1;
end
`INST_XOR: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = op1_i ^ op2_i;
end
`INST_SR: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
if (inst_i[30] == 1'b1) begin
reg_wdata = (sr_shift & sr_shift_mask) | ({32{reg1_rdata_i[31]}} & (~sr_shift_mask));
end else begin
reg_wdata = reg1_rdata_i >> reg2_rdata_i[4:0];
end
end
`INST_OR: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = op1_i | op2_i;
end
`INST_AND: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = op1_i & op2_i;
end
default: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = `ZeroWord;
end
endcase
end else if (funct7 == 7'b0000001) begin
case (funct3)
`INST_MUL: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = mul_temp[31:0];
end
`INST_MULHU: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = mul_temp[63:32];
end
`INST_MULH: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
case ({reg1_rdata_i[31], reg2_rdata_i[31]})
2'b00: begin
reg_wdata = mul_temp[63:32];
end
2'b11: begin
reg_wdata = mul_temp[63:32];
end
2'b10: begin
reg_wdata = mul_temp_invert[63:32];
end
default: begin
reg_wdata = mul_temp_invert[63:32];
end
endcase
end
`INST_MULHSU: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
if (reg1_rdata_i[31] == 1'b1) begin
reg_wdata = mul_temp_invert[63:32];
end else begin
reg_wdata = mul_temp[63:32];
end
end
default: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = `ZeroWord;
end
endcase
end else begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = `ZeroWord;
end
end
`INST_TYPE_L: begin
case (funct3)
`INST_LB: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
mem_req = `RIB_REQ;
mem_raddr_o = op1_add_op2_res;
case (mem_raddr_index)
2'b00: begin
reg_wdata = {{24{mem_rdata_i[7]}}, mem_rdata_i[7:0]};
end
2'b01: begin
reg_wdata = {{24{mem_rdata_i[15]}}, mem_rdata_i[15:8]};
end
2'b10: begin
reg_wdata = {{24{mem_rdata_i[23]}}, mem_rdata_i[23:16]};
end
default: begin
reg_wdata = {{24{mem_rdata_i[31]}}, mem_rdata_i[31:24]};
end
endcase
end
`INST_LH: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
mem_req = `RIB_REQ;
mem_raddr_o = op1_add_op2_res;
if (mem_raddr_index == 2'b0) begin
reg_wdata = {{16{mem_rdata_i[15]}}, mem_rdata_i[15:0]};
end else begin
reg_wdata = {{16{mem_rdata_i[31]}}, mem_rdata_i[31:16]};
end
end
`INST_LW: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
mem_req = `RIB_REQ;
mem_raddr_o = op1_add_op2_res;
reg_wdata = mem_rdata_i;
end
`INST_LBU: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
mem_req = `RIB_REQ;
mem_raddr_o = op1_add_op2_res;
case (mem_raddr_index)
2'b00: begin
reg_wdata = {24'h0, mem_rdata_i[7:0]};
end
2'b01: begin
reg_wdata = {24'h0, mem_rdata_i[15:8]};
end
2'b10: begin
reg_wdata = {24'h0, mem_rdata_i[23:16]};
end
default: begin
reg_wdata = {24'h0, mem_rdata_i[31:24]};
end
endcase
end
`INST_LHU: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
mem_req = `RIB_REQ;
mem_raddr_o = op1_add_op2_res;
if (mem_raddr_index == 2'b0) begin
reg_wdata = {16'h0, mem_rdata_i[15:0]};
end else begin
reg_wdata = {16'h0, mem_rdata_i[31:16]};
end
end
default: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = `ZeroWord;
end
endcase
end
`INST_TYPE_S: begin
case (funct3)
`INST_SB: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
reg_wdata = `ZeroWord;
mem_we = `WriteEnable;
mem_req = `RIB_REQ;
mem_waddr_o = op1_add_op2_res;
mem_raddr_o = op1_add_op2_res;
case (mem_waddr_index)
2'b00: begin
mem_wdata_o = {mem_rdata_i[31:8], reg2_rdata_i[7:0]};
end
2'b01: begin
mem_wdata_o = {mem_rdata_i[31:16], reg2_rdata_i[7:0], mem_rdata_i[7:0]};
end
2'b10: begin
mem_wdata_o = {mem_rdata_i[31:24], reg2_rdata_i[7:0], mem_rdata_i[15:0]};
end
default: begin
mem_wdata_o = {reg2_rdata_i[7:0], mem_rdata_i[23:0]};
end
endcase
end
`INST_SH: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
reg_wdata = `ZeroWord;
mem_we = `WriteEnable;
mem_req = `RIB_REQ;
mem_waddr_o = op1_add_op2_res;
mem_raddr_o = op1_add_op2_res;
if (mem_waddr_index == 2'b00) begin
mem_wdata_o = {mem_rdata_i[31:16], reg2_rdata_i[15:0]};
end else begin
mem_wdata_o = {reg2_rdata_i[15:0], mem_rdata_i[15:0]};
end
end
`INST_SW: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
reg_wdata = `ZeroWord;
mem_we = `WriteEnable;
mem_req = `RIB_REQ;
mem_waddr_o = op1_add_op2_res;
mem_raddr_o = op1_add_op2_res;
mem_wdata_o = reg2_rdata_i;
end
default: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = `ZeroWord;
end
endcase
end
`INST_TYPE_B: begin
case (funct3)
`INST_BEQ: begin
hold_flag = `HoldDisable;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = `ZeroWord;
jump_flag = op1_eq_op2 & `JumpEnable;
jump_addr = {32{op1_eq_op2}} & op1_jump_add_op2_jump_res;
end
`INST_BNE: begin
hold_flag = `HoldDisable;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = `ZeroWord;
jump_flag = (~op1_eq_op2) & `JumpEnable;
jump_addr = {32{(~op1_eq_op2)}} & op1_jump_add_op2_jump_res;
end
`INST_BLT: begin
hold_flag = `HoldDisable;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = `ZeroWord;
jump_flag = (~op1_ge_op2_signed) & `JumpEnable;
jump_addr = {32{(~op1_ge_op2_signed)}} & op1_jump_add_op2_jump_res;
end
`INST_BGE: begin
hold_flag = `HoldDisable;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = `ZeroWord;
jump_flag = (op1_ge_op2_signed) & `JumpEnable;
jump_addr = {32{(op1_ge_op2_signed)}} & op1_jump_add_op2_jump_res;
end
`INST_BLTU: begin
hold_flag = `HoldDisable;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = `ZeroWord;
jump_flag = (~op1_ge_op2_unsigned) & `JumpEnable;
jump_addr = {32{(~op1_ge_op2_unsigned)}} & op1_jump_add_op2_jump_res;
end
`INST_BGEU: begin
hold_flag = `HoldDisable;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = `ZeroWord;
jump_flag = (op1_ge_op2_unsigned) & `JumpEnable;
jump_addr = {32{(op1_ge_op2_unsigned)}} & op1_jump_add_op2_jump_res;
end
default: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = `ZeroWord;
end
endcase
end
`INST_JAL, `INST_JALR: begin
hold_flag = `HoldDisable;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
jump_flag = `JumpEnable;
jump_addr = op1_jump_add_op2_jump_res;
reg_wdata = op1_add_op2_res;
end
`INST_LUI, `INST_AUIPC: begin
hold_flag = `HoldDisable;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
jump_addr = `ZeroWord;
jump_flag = `JumpDisable;
reg_wdata = op1_add_op2_res;
end
`INST_NOP_OP: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = `ZeroWord;
end
`INST_FENCE: begin
hold_flag = `HoldDisable;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = `ZeroWord;
jump_flag = `JumpEnable;
jump_addr = op1_jump_add_op2_jump_res;
end
`INST_CSR: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
case (funct3)
`INST_CSRRW: begin
csr_wdata_o = reg1_rdata_i;
reg_wdata = csr_rdata_i;
end
`INST_CSRRS: begin
csr_wdata_o = reg1_rdata_i | csr_rdata_i;
reg_wdata = csr_rdata_i;
end
`INST_CSRRC: begin
csr_wdata_o = csr_rdata_i & (~reg1_rdata_i);
reg_wdata = csr_rdata_i;
end
`INST_CSRRWI: begin
csr_wdata_o = {27'h0, uimm};
reg_wdata = csr_rdata_i;
end
`INST_CSRRSI: begin
csr_wdata_o = {27'h0, uimm} | csr_rdata_i;
reg_wdata = csr_rdata_i;
end
`INST_CSRRCI: begin
csr_wdata_o = (~{27'h0, uimm}) & csr_rdata_i;
reg_wdata = csr_rdata_i;
end
default: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = `ZeroWord;
end
endcase
end
default: begin
jump_flag = `JumpDisable;
hold_flag = `HoldDisable;
jump_addr = `ZeroWord;
mem_wdata_o = `ZeroWord;
mem_raddr_o = `ZeroWord;
mem_waddr_o = `ZeroWord;
mem_we = `WriteDisable;
reg_wdata = `ZeroWord;
end
endcase
end
endmodule

378
rtl/core/exu.v Normal file
View File

@ -0,0 +1,378 @@
/*
Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
//
//
module exu(
input wire clk,
input wire rst_n,
// clint
input wire int_assert_i, //
input wire[31:0] int_addr_i, //
input wire int_stall_i, //
output wire inst_ecall_o, // ecall
output wire inst_ebreak_o, // ebreak
output wire inst_mret_o, // mret
// mem
input wire[31:0] mem_rdata_i, //
input wire mem_req_ready_i,
input wire mem_rsp_valid_i,
output wire[31:0] mem_wdata_o, //
output wire[31:0] mem_addr_o, //
output wire mem_we_o, //
output wire[3:0] mem_sel_o, //
output wire mem_req_valid_o,
output wire mem_rsp_ready_o,
output wire mem_access_misaligned_o,
// gpr_reg
output wire[31:0] reg_wdata_o, //
output wire reg_we_o, //
output wire[4:0] reg_waddr_o, //
// csr_reg
input wire[31:0] csr_rdata_i,
output wire[31:0] csr_raddr_o, // CSR
output wire[31:0] csr_wdata_o, // CSR
output wire csr_we_o, // CSR
output wire[31:0] csr_waddr_o, // CSR
// to pipe_ctrl
output wire hold_flag_o, //
output wire jump_flag_o, //
output wire[31:0] jump_addr_o, //
// from idu_exu
input wire[`DECINFO_WIDTH-1:0] dec_info_bus_i,
input wire[31:0] dec_imm_i,
input wire[31:0] dec_pc_i,
input wire[31:0] next_pc_i,
input wire[4:0] rd_waddr_i,
input wire[31:0] reg1_rdata_i, // 1
input wire[31:0] reg2_rdata_i, // 2
input wire rd_we_i
);
// dispatch to ALU
wire[31:0] alu_op1_o;
wire[31:0] alu_op2_o;
wire req_alu_o;
wire alu_op_lui_o;
wire alu_op_auipc_o;
wire alu_op_add_o;
wire alu_op_sub_o;
wire alu_op_sll_o;
wire alu_op_slt_o;
wire alu_op_sltu_o;
wire alu_op_xor_o;
wire alu_op_srl_o;
wire alu_op_sra_o;
wire alu_op_or_o;
wire alu_op_and_o;
// dispatch to BJP
wire[31:0] bjp_op1_o;
wire[31:0] bjp_op2_o;
wire[31:0] bjp_jump_op1_o;
wire[31:0] bjp_jump_op2_o;
wire req_bjp_o;
wire bjp_op_jump_o;
wire bjp_op_beq_o;
wire bjp_op_bne_o;
wire bjp_op_blt_o;
wire bjp_op_bltu_o;
wire bjp_op_bge_o;
wire bjp_op_bgeu_o;
// dispatch to MULDIV
wire req_muldiv_o;
wire[31:0] muldiv_op1_o;
wire[31:0] muldiv_op2_o;
wire muldiv_op_mul_o;
wire muldiv_op_mulh_o;
wire muldiv_op_mulhsu_o;
wire muldiv_op_mulhu_o;
wire muldiv_op_div_o;
wire muldiv_op_divu_o;
wire muldiv_op_rem_o;
wire muldiv_op_remu_o;
// dispatch to CSR
wire req_csr_o;
wire[31:0] csr_op1_o;
wire[31:0] csr_addr_o;
wire csr_csrrw_o;
wire csr_csrrs_o;
wire csr_csrrc_o;
// dispatch to MEM
wire req_mem_o;
wire[31:0] mem_op1_o;
wire[31:0] mem_op2_o;
wire[31:0] mem_rs2_data_o;
wire mem_op_lb_o;
wire mem_op_lh_o;
wire mem_op_lw_o;
wire mem_op_lbu_o;
wire mem_op_lhu_o;
wire mem_op_sb_o;
wire mem_op_sh_o;
wire mem_op_sw_o;
// dispatch to SYS
wire sys_op_nop_o;
wire sys_op_mret_o;
wire sys_op_ecall_o;
wire sys_op_ebreak_o;
wire sys_op_fence_o;
exu_dispatch u_exu_dispatch(
// input
.clk(clk),
.rst_n(rst_n),
.dec_info_bus_i(dec_info_bus_i),
.dec_imm_i(dec_imm_i),
.dec_pc_i(dec_pc_i),
.rs1_rdata_i(reg1_rdata_i),
.rs2_rdata_i(reg2_rdata_i),
// dispatch to ALU
.alu_op1_o(alu_op1_o),
.alu_op2_o(alu_op2_o),
.req_alu_o(req_alu_o),
.alu_op_lui_o(alu_op_lui_o),
.alu_op_auipc_o(alu_op_auipc_o),
.alu_op_add_o(alu_op_add_o),
.alu_op_sub_o(alu_op_sub_o),
.alu_op_sll_o(alu_op_sll_o),
.alu_op_slt_o(alu_op_slt_o),
.alu_op_sltu_o(alu_op_sltu_o),
.alu_op_xor_o(alu_op_xor_o),
.alu_op_srl_o(alu_op_srl_o),
.alu_op_sra_o(alu_op_sra_o),
.alu_op_or_o(alu_op_or_o),
.alu_op_and_o(alu_op_and_o),
// dispatch to BJP
.bjp_op1_o(bjp_op1_o),
.bjp_op2_o(bjp_op2_o),
.bjp_jump_op1_o(bjp_jump_op1_o),
.bjp_jump_op2_o(bjp_jump_op2_o),
.req_bjp_o(req_bjp_o),
.bjp_op_jump_o(bjp_op_jump_o),
.bjp_op_beq_o(bjp_op_beq_o),
.bjp_op_bne_o(bjp_op_bne_o),
.bjp_op_blt_o(bjp_op_blt_o),
.bjp_op_bltu_o(bjp_op_bltu_o),
.bjp_op_bge_o(bjp_op_bge_o),
.bjp_op_bgeu_o(bjp_op_bgeu_o),
// dispatch to MULDIV
.req_muldiv_o(req_muldiv_o),
.muldiv_op1_o(muldiv_op1_o),
.muldiv_op2_o(muldiv_op2_o),
.muldiv_op_mul_o(muldiv_op_mul_o),
.muldiv_op_mulh_o(muldiv_op_mulh_o),
.muldiv_op_mulhsu_o(muldiv_op_mulhsu_o),
.muldiv_op_mulhu_o(muldiv_op_mulhu_o),
.muldiv_op_div_o(muldiv_op_div_o),
.muldiv_op_divu_o(muldiv_op_divu_o),
.muldiv_op_rem_o(muldiv_op_rem_o),
.muldiv_op_remu_o(muldiv_op_remu_o),
// dispatch to CSR
.req_csr_o(req_csr_o),
.csr_op1_o(csr_op1_o),
.csr_addr_o(csr_addr_o),
.csr_csrrw_o(csr_csrrw_o),
.csr_csrrs_o(csr_csrrs_o),
.csr_csrrc_o(csr_csrrc_o),
// dispatch to MEM
.req_mem_o(req_mem_o),
.mem_op1_o(mem_op1_o),
.mem_op2_o(mem_op2_o),
.mem_rs2_data_o(mem_rs2_data_o),
.mem_op_lb_o(mem_op_lb_o),
.mem_op_lh_o(mem_op_lh_o),
.mem_op_lw_o(mem_op_lw_o),
.mem_op_lbu_o(mem_op_lbu_o),
.mem_op_lhu_o(mem_op_lhu_o),
.mem_op_sb_o(mem_op_sb_o),
.mem_op_sh_o(mem_op_sh_o),
.mem_op_sw_o(mem_op_sw_o),
// dispatch to SYS
.sys_op_nop_o(sys_op_nop_o),
.sys_op_mret_o(sys_op_mret_o),
.sys_op_ecall_o(sys_op_ecall_o),
.sys_op_ebreak_o(sys_op_ebreak_o),
.sys_op_fence_o(sys_op_fence_o)
);
assign inst_ecall_o = sys_op_ecall_o;
assign inst_ebreak_o = sys_op_ebreak_o;
assign inst_mret_o = sys_op_mret_o;
wire[31:0] alu_res_o;
wire[31:0] bjp_res_o;
wire bjp_cmp_res_o;
wire[31:0] csr_op1 = csr_csrrc_o? (~csr_op1_o): csr_op1_o;
wire[31:0] csr_op2 = csr_csrrw_o? (32'h0): csr_rdata_i;
exu_alu_datapath u_exu_alu_datapath(
.clk(clk),
.rst_n(rst_n),
// ALU
.req_alu_i(req_alu_o),
.alu_op1_i(alu_op1_o),
.alu_op2_i(alu_op2_o),
.alu_op_add_i(alu_op_add_o | alu_op_lui_o | alu_op_auipc_o),
.alu_op_sub_i(alu_op_sub_o),
.alu_op_sll_i(alu_op_sll_o),
.alu_op_slt_i(alu_op_slt_o),
.alu_op_sltu_i(alu_op_sltu_o),
.alu_op_xor_i(alu_op_xor_o),
.alu_op_srl_i(alu_op_srl_o),
.alu_op_sra_i(alu_op_sra_o),
.alu_op_or_i(alu_op_or_o),
.alu_op_and_i(alu_op_and_o),
// BJP
.req_bjp_i(req_bjp_o),
.bjp_op1_i(bjp_op1_o),
.bjp_op2_i(bjp_op2_o),
.bjp_op_beq_i(bjp_op_beq_o),
.bjp_op_bne_i(bjp_op_bne_o),
.bjp_op_blt_i(bjp_op_blt_o),
.bjp_op_bltu_i(bjp_op_bltu_o),
.bjp_op_bge_i(bjp_op_bge_o),
.bjp_op_bgeu_i(bjp_op_bgeu_o),
.bjp_op_jump_i(bjp_op_jump_o),
.bjp_jump_op1_i(bjp_jump_op1_o),
.bjp_jump_op2_i(bjp_jump_op2_o),
// MEM
.req_mem_i(req_mem_o),
.mem_op1_i(mem_op1_o),
.mem_op2_i(mem_op2_o),
// CSR
.req_csr_i(req_csr_o),
.csr_op1_i(csr_op1),
.csr_op2_i(csr_op2),
.csr_csrrw_i(csr_csrrw_o),
.csr_csrrs_i(csr_csrrs_o),
.csr_csrrc_i(csr_csrrc_o),
.alu_res_o(alu_res_o),
.bjp_res_o(bjp_res_o),
.bjp_cmp_res_o(bjp_cmp_res_o)
);
wire mem_reg_we_o;
wire mem_mem_we_o;
wire[31:0] mem_wdata;
wire mem_stall_o;
exu_mem u_exu_mem(
.clk(clk),
.rst_n(rst_n),
.req_mem_i(req_mem_o),
.mem_addr_i(alu_res_o),
.mem_rs2_data_i(mem_rs2_data_o),
.mem_req_ready_i(mem_req_ready_i),
.mem_rsp_valid_i(mem_rsp_valid_i),
.mem_rdata_i(mem_rdata_i),
.mem_op_lb_i(mem_op_lb_o),
.mem_op_lh_i(mem_op_lh_o),
.mem_op_lw_i(mem_op_lw_o),
.mem_op_lbu_i(mem_op_lbu_o),
.mem_op_lhu_i(mem_op_lhu_o),
.mem_op_sb_i(mem_op_sb_o),
.mem_op_sh_i(mem_op_sh_o),
.mem_op_sw_i(mem_op_sw_o),
.mem_access_misaligned_o(mem_access_misaligned_o),
.mem_stall_o(mem_stall_o),
.mem_addr_o(mem_addr_o),
.mem_wdata_o(mem_wdata),
.mem_reg_we_o(mem_reg_we_o),
.mem_mem_we_o(mem_mem_we_o),
.mem_sel_o(mem_sel_o),
.mem_req_valid_o(mem_req_valid_o),
.mem_rsp_ready_o(mem_rsp_ready_o)
);
wire[31:0] muldiv_reg_wdata_o;
wire muldiv_reg_we_o;
wire muldiv_stall_o;
exu_muldiv u_exu_muldiv(
.clk(clk),
.rst_n(rst_n),
.muldiv_op1_i(muldiv_op1_o),
.muldiv_op2_i(muldiv_op2_o),
.muldiv_op_mul_i(muldiv_op_mul_o),
.muldiv_op_mulh_i(muldiv_op_mulh_o),
.muldiv_op_mulhsu_i(muldiv_op_mulhsu_o),
.muldiv_op_mulhu_i(muldiv_op_mulhu_o),
.muldiv_op_div_i(muldiv_op_div_o),
.muldiv_op_divu_i(muldiv_op_divu_o),
.muldiv_op_rem_i(muldiv_op_rem_o),
.muldiv_op_remu_i(muldiv_op_remu_o),
.muldiv_reg_wdata_o(muldiv_reg_wdata_o),
.muldiv_reg_we_o(muldiv_reg_we_o),
.muldiv_stall_o(muldiv_stall_o)
);
wire commit_reg_we_o;
exu_commit u_exu_commit(
.clk(clk),
.rst_n(rst_n),
.req_muldiv_i(req_muldiv_o),
.muldiv_reg_we_i(muldiv_reg_we_o),
.muldiv_reg_waddr_i(rd_waddr_i),
.muldiv_reg_wdata_i(muldiv_reg_wdata_o),
.req_mem_i(req_mem_o),
.mem_reg_we_i(mem_reg_we_o),
.mem_reg_waddr_i(rd_waddr_i),
.mem_reg_wdata_i(mem_wdata),
.req_csr_i(req_csr_o),
.csr_reg_we_i(req_csr_o),
.csr_reg_waddr_i(rd_waddr_i),
.csr_reg_wdata_i(csr_rdata_i),
.req_bjp_i(req_bjp_o),
.bjp_reg_we_i(bjp_op_jump_o),
.bjp_reg_wdata_i(next_pc_i),
.bjp_reg_waddr_i(rd_waddr_i),
.rd_we_i(rd_we_i),
.rd_waddr_i(rd_waddr_i),
.alu_reg_wdata_i(alu_res_o),
.reg_we_o(commit_reg_we_o),
.reg_waddr_o(reg_waddr_o),
.reg_wdata_o(reg_wdata_o)
);
assign reg_we_o = commit_reg_we_o;
assign jump_flag_o = bjp_cmp_res_o | bjp_op_jump_o | sys_op_fence_o | int_assert_i;
assign jump_addr_o = int_assert_i? int_addr_i:
sys_op_fence_o? next_pc_i:
bjp_res_o;
assign hold_flag_o = muldiv_stall_o | mem_stall_o;
assign csr_raddr_o = csr_addr_o;
assign csr_waddr_o = csr_addr_o;
assign csr_we_o = req_csr_o;
assign csr_wdata_o = alu_res_o;
assign mem_we_o = mem_mem_we_o;
assign mem_wdata_o = mem_wdata;
endmodule

254
rtl/core/exu_alu_datapath.v Normal file
View File

@ -0,0 +1,254 @@
/*
Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
`define DATAPATH_MUX_WIDTH (32+32+16)
module exu_alu_datapath(
input wire clk,
input wire rst_n,
// ALU
input wire req_alu_i,
input wire[31:0] alu_op1_i,
input wire[31:0] alu_op2_i,
input wire alu_op_add_i,
input wire alu_op_sub_i,
input wire alu_op_sll_i,
input wire alu_op_slt_i,
input wire alu_op_sltu_i,
input wire alu_op_xor_i,
input wire alu_op_srl_i,
input wire alu_op_sra_i,
input wire alu_op_or_i,
input wire alu_op_and_i,
// BJP
input wire req_bjp_i,
input wire[31:0] bjp_op1_i,
input wire[31:0] bjp_op2_i,
input wire bjp_op_beq_i,
input wire bjp_op_bne_i,
input wire bjp_op_blt_i,
input wire bjp_op_bltu_i,
input wire bjp_op_bge_i,
input wire bjp_op_bgeu_i,
input wire bjp_op_jump_i,
input wire[31:0] bjp_jump_op1_i,
input wire[31:0] bjp_jump_op2_i,
// MEM
input wire req_mem_i,
input wire[31:0] mem_op1_i,
input wire[31:0] mem_op2_i,
// CSR
input wire req_csr_i,
input wire[31:0] csr_op1_i,
input wire[31:0] csr_op2_i,
input wire csr_csrrw_i,
input wire csr_csrrs_i,
input wire csr_csrrc_i,
output wire[31:0] alu_res_o,
output wire[31:0] bjp_res_o,
output wire bjp_cmp_res_o
);
wire[31:0] mux_op1;
wire[31:0] mux_op2;
wire op_add;
wire op_sub;
wire op_sll;
wire op_slt;
wire op_sltu;
wire op_xor;
wire op_srl;
wire op_sra;
wire op_or;
wire op_and;
wire op_beq;
wire op_bne;
wire op_blt;
wire op_bltu;
wire op_bge;
wire op_bgeu;
//
wire[31:0] xor_res = mux_op1 ^ mux_op2;
//
wire[31:0] or_res = mux_op1 | mux_op2;
//
wire[31:0] and_res = mux_op1 & mux_op2;
//
wire[31:0] add_op1 = req_bjp_i? bjp_jump_op1_i: mux_op1;
wire[31:0] add_op2 = req_bjp_i? bjp_jump_op2_i: mux_op2;
wire[31:0] add_sub_res = add_op1 + (op_sub? (-add_op2): add_op2);
//
wire[31:0] sll_res = mux_op1 << mux_op2[4:0];
//
wire[31:0] srl_res = mux_op1 >> mux_op2[4:0];
//
wire[31:0] sr_shift_mask = 32'hffffffff >> mux_op2[4:0];
wire[31:0] sra_res = (srl_res & sr_shift_mask) | ({32{mux_op1[31]}} & (~sr_shift_mask));
//
wire op1_ge_op2_signed = ($signed(mux_op1) >= $signed(mux_op2));
//
wire op1_ge_op2_unsigned = (mux_op1 >= mux_op2);
wire op1_neq_op2 = (|xor_res);
wire op1_eq_op2 = (~op1_neq_op2);
wire cmp_res_eq = op_beq & op1_eq_op2;
wire cmp_res_neq = op_bne & op1_neq_op2;
wire cmp_res_lt = op_blt & (~op1_ge_op2_signed);
wire cmp_res_ltu = op_bltu & (~op1_ge_op2_unsigned);
wire cmp_res_gt = op_bge & op1_ge_op2_signed;
wire cmp_res_gtu = op_bgeu & op1_ge_op2_unsigned;
wire[31:0] slt_res = (~op1_ge_op2_signed)? 32'h1: 32'h0;
wire[31:0] sltu_res = (~op1_ge_op2_unsigned)? 32'h1: 32'h0;
reg[31:0] alu_datapath_res;
always @ (*) begin
alu_datapath_res = 32'h0;
case (1'b1)
op_xor: alu_datapath_res = xor_res;
op_or: alu_datapath_res = or_res;
op_and: alu_datapath_res = and_res;
op_add: alu_datapath_res = add_sub_res;
op_sub: alu_datapath_res = add_sub_res;
op_sll: alu_datapath_res = sll_res;
op_srl: alu_datapath_res = srl_res;
op_sra: alu_datapath_res = sra_res;
op_slt: alu_datapath_res = slt_res;
op_sltu: alu_datapath_res = sltu_res;
endcase
end
assign alu_res_o = alu_datapath_res;
assign bjp_res_o = alu_datapath_res;
assign bjp_cmp_res_o = cmp_res_eq | cmp_res_neq | cmp_res_lt | cmp_res_ltu | cmp_res_gt | cmp_res_gtu;
assign {mux_op1,
mux_op2,
op_add,
op_sub,
op_sll,
op_slt,
op_sltu,
op_xor,
op_srl,
op_sra,
op_or,
op_and,
op_beq,
op_bne,
op_blt,
op_bltu,
op_bge,
op_bgeu
} = ({`DATAPATH_MUX_WIDTH{req_alu_i}} & {
alu_op1_i,
alu_op2_i,
alu_op_add_i,
alu_op_sub_i,
alu_op_sll_i,
alu_op_slt_i,
alu_op_sltu_i,
alu_op_xor_i,
alu_op_srl_i,
alu_op_sra_i,
alu_op_or_i,
alu_op_and_i,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0
}) |
({`DATAPATH_MUX_WIDTH{req_bjp_i}} & {
bjp_op1_i,
bjp_op2_i,
1'b1,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
bjp_op_beq_i,
bjp_op_bne_i,
bjp_op_blt_i,
bjp_op_bltu_i,
bjp_op_bge_i,
bjp_op_bgeu_i
}) |
({`DATAPATH_MUX_WIDTH{req_mem_i}} & {
mem_op1_i,
mem_op2_i,
1'b1,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0
}) |
({`DATAPATH_MUX_WIDTH{req_csr_i}} & {
csr_op1_i,
csr_op2_i,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
csr_csrrw_i | csr_csrrs_i,
csr_csrrc_i,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0,
1'b0
});
endmodule

92
rtl/core/exu_commit.v Normal file
View File

@ -0,0 +1,92 @@
/*
Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
module exu_commit(
input wire clk,
input wire rst_n,
input wire req_muldiv_i,
input wire muldiv_reg_we_i,
input wire[4:0] muldiv_reg_waddr_i,
input wire[31:0] muldiv_reg_wdata_i,
input wire req_mem_i,
input wire mem_reg_we_i,
input wire[4:0] mem_reg_waddr_i,
input wire[31:0] mem_reg_wdata_i,
input wire req_csr_i,
input wire csr_reg_we_i,
input wire[4:0] csr_reg_waddr_i,
input wire[31:0] csr_reg_wdata_i,
input wire req_bjp_i,
input wire bjp_reg_we_i,
input wire[31:0] bjp_reg_wdata_i,
input wire[4:0] bjp_reg_waddr_i,
input wire rd_we_i,
input wire[4:0] rd_waddr_i,
input wire[31:0] alu_reg_wdata_i,
output wire reg_we_o,
output wire[4:0] reg_waddr_o,
output wire[31:0] reg_wdata_o
);
wire use_alu_res = (~req_muldiv_i) &
(~req_mem_i) &
(~req_csr_i) &
(~req_bjp_i);
assign reg_we_o = muldiv_reg_we_i | mem_reg_we_i | csr_reg_we_i | use_alu_res | bjp_reg_we_i;
reg[4:0] reg_waddr;
always @ (*) begin
reg_waddr = 5'h0;
case (1'b1)
muldiv_reg_we_i: reg_waddr = muldiv_reg_waddr_i;
mem_reg_we_i: reg_waddr = mem_reg_waddr_i;
csr_reg_we_i: reg_waddr = csr_reg_waddr_i;
bjp_reg_we_i: reg_waddr = bjp_reg_waddr_i;
rd_we_i: reg_waddr = rd_waddr_i;
endcase
end
assign reg_waddr_o = reg_waddr;
reg[31:0] reg_wdata;
always @ (*) begin
reg_wdata = 32'h0;
case (1'b1)
muldiv_reg_we_i: reg_wdata = muldiv_reg_wdata_i;
mem_reg_we_i: reg_wdata = mem_reg_wdata_i;
csr_reg_we_i: reg_wdata = csr_reg_wdata_i;
bjp_reg_we_i: reg_wdata = bjp_reg_wdata_i;
use_alu_res: reg_wdata = alu_reg_wdata_i;
endcase
end
assign reg_wdata_o = reg_wdata;
endmodule

210
rtl/core/exu_dispatch.v Normal file
View File

@ -0,0 +1,210 @@
/*
Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
module exu_dispatch(
input wire clk,
input wire rst_n,
input wire[`DECINFO_WIDTH-1:0] dec_info_bus_i,
input wire[31:0] dec_imm_i,
input wire[31:0] dec_pc_i,
input wire[31:0] rs1_rdata_i,
input wire[31:0] rs2_rdata_i,
// dispatch to ALU
output wire req_alu_o,
output wire[31:0] alu_op1_o,
output wire[31:0] alu_op2_o,
output wire alu_op_lui_o,
output wire alu_op_auipc_o,
output wire alu_op_add_o,
output wire alu_op_sub_o,
output wire alu_op_sll_o,
output wire alu_op_slt_o,
output wire alu_op_sltu_o,
output wire alu_op_xor_o,
output wire alu_op_srl_o,
output wire alu_op_sra_o,
output wire alu_op_or_o,
output wire alu_op_and_o,
// dispatch to BJP
output wire req_bjp_o,
output wire[31:0] bjp_op1_o,
output wire[31:0] bjp_op2_o,
output wire[31:0] bjp_jump_op1_o,
output wire[31:0] bjp_jump_op2_o,
output wire bjp_op_jump_o,
output wire bjp_op_beq_o,
output wire bjp_op_bne_o,
output wire bjp_op_blt_o,
output wire bjp_op_bltu_o,
output wire bjp_op_bge_o,
output wire bjp_op_bgeu_o,
// dispatch to MULDIV
output wire req_muldiv_o,
output wire[31:0] muldiv_op1_o,
output wire[31:0] muldiv_op2_o,
output wire muldiv_op_mul_o,
output wire muldiv_op_mulh_o,
output wire muldiv_op_mulhsu_o,
output wire muldiv_op_mulhu_o,
output wire muldiv_op_div_o,
output wire muldiv_op_divu_o,
output wire muldiv_op_rem_o,
output wire muldiv_op_remu_o,
// dispatch to CSR
output wire req_csr_o,
output wire[31:0] csr_op1_o,
output wire[31:0] csr_addr_o,
output wire csr_csrrw_o,
output wire csr_csrrs_o,
output wire csr_csrrc_o,
// dispatch to MEM
output wire req_mem_o,
output wire[31:0] mem_op1_o,
output wire[31:0] mem_op2_o,
output wire[31:0] mem_rs2_data_o,
output wire mem_op_lb_o,
output wire mem_op_lh_o,
output wire mem_op_lw_o,
output wire mem_op_lbu_o,
output wire mem_op_lhu_o,
output wire mem_op_sb_o,
output wire mem_op_sh_o,
output wire mem_op_sw_o,
// dispatch to SYS
output wire sys_op_nop_o,
output wire sys_op_mret_o,
output wire sys_op_ecall_o,
output wire sys_op_ebreak_o,
output wire sys_op_fence_o
);
wire[`DECINFO_GRP_WIDTH-1:0] disp_info_grp = dec_info_bus_i[`DECINFO_GRP_BUS];
// ALU info
wire op_alu = (disp_info_grp == `DECINFO_GRP_ALU);
wire[`DECINFO_WIDTH-1:0] alu_info = {`DECINFO_WIDTH{op_alu}} & dec_info_bus_i;
// ALU op1
wire alu_op1_pc = alu_info[`DECINFO_ALU_OP1PC];
wire alu_op1_zero = alu_info[`DECINFO_ALU_LUI];
wire[31:0] alu_op1 = alu_op1_pc? dec_pc_i: alu_op1_zero? 32'h0: rs1_rdata_i;
assign alu_op1_o = op_alu? alu_op1: 32'h0;
// ALU op2
wire alu_op2_imm = alu_info[`DECINFO_ALU_OP2IMM];
wire[31:0] alu_op2 = alu_op2_imm? dec_imm_i: rs2_rdata_i;
assign alu_op2_o = op_alu? alu_op2: 32'h0;
assign alu_op_lui_o = alu_info[`DECINFO_ALU_LUI];
assign alu_op_auipc_o = alu_info[`DECINFO_ALU_AUIPC];
assign alu_op_add_o = alu_info[`DECINFO_ALU_ADD];
assign alu_op_sub_o = alu_info[`DECINFO_ALU_SUB];
assign alu_op_sll_o = alu_info[`DECINFO_ALU_SLL];
assign alu_op_slt_o = alu_info[`DECINFO_ALU_SLT];
assign alu_op_sltu_o = alu_info[`DECINFO_ALU_SLTU];
assign alu_op_xor_o = alu_info[`DECINFO_ALU_XOR];
assign alu_op_srl_o = alu_info[`DECINFO_ALU_SRL];
assign alu_op_sra_o = alu_info[`DECINFO_ALU_SRA];
assign alu_op_or_o = alu_info[`DECINFO_ALU_OR];
assign alu_op_and_o = alu_info[`DECINFO_ALU_AND];
assign req_alu_o = op_alu;
// BJP info
wire op_bjp = (disp_info_grp == `DECINFO_GRP_BJP);
wire[`DECINFO_WIDTH-1:0] bjp_info = {`DECINFO_WIDTH{op_bjp}} & dec_info_bus_i;
// BJP op1
wire bjp_op1_rs1 = bjp_info[`DECINFO_BJP_OP1RS1];
wire[31:0] bjp_op1 = bjp_op1_rs1? rs1_rdata_i: dec_pc_i;
assign bjp_jump_op1_o = op_bjp? bjp_op1: 32'h0;
// BJP op2
wire[31:0] bjp_op2 = dec_imm_i;
assign bjp_jump_op2_o = op_bjp? bjp_op2: 32'h0;
assign bjp_op1_o = op_bjp? rs1_rdata_i: 32'h0;
assign bjp_op2_o = op_bjp? rs2_rdata_i: 32'h0;
assign bjp_op_jump_o = bjp_info[`DECINFO_BJP_JUMP];
assign bjp_op_beq_o = bjp_info[`DECINFO_BJP_BEQ];
assign bjp_op_bne_o = bjp_info[`DECINFO_BJP_BNE];
assign bjp_op_blt_o = bjp_info[`DECINFO_BJP_BLT];
assign bjp_op_bltu_o = bjp_info[`DECINFO_BJP_BLTU];
assign bjp_op_bge_o = bjp_info[`DECINFO_BJP_BGE];
assign bjp_op_bgeu_o = bjp_info[`DECINFO_BJP_BGEU];
assign req_bjp_o = op_bjp;
// MULDIV info
wire op_muldiv = (disp_info_grp == `DECINFO_GRP_MULDIV);
wire[`DECINFO_WIDTH-1:0] muldiv_info = {`DECINFO_WIDTH{op_muldiv}} & dec_info_bus_i;
// MULDIV op1
assign muldiv_op1_o = op_muldiv? rs1_rdata_i: 32'h0;
// MULDIV op2
assign muldiv_op2_o = op_muldiv? rs2_rdata_i: 32'h0;
assign muldiv_op_mul_o = muldiv_info[`DECINFO_MULDIV_MUL];
assign muldiv_op_mulh_o = muldiv_info[`DECINFO_MULDIV_MULH];
assign muldiv_op_mulhu_o = muldiv_info[`DECINFO_MULDIV_MULHU];
assign muldiv_op_mulhsu_o = muldiv_info[`DECINFO_MULDIV_MULHSU];
assign muldiv_op_div_o = muldiv_info[`DECINFO_MULDIV_DIV];
assign muldiv_op_divu_o = muldiv_info[`DECINFO_MULDIV_DIVU];
assign muldiv_op_rem_o = muldiv_info[`DECINFO_MULDIV_REM];
assign muldiv_op_remu_o = muldiv_info[`DECINFO_MULDIV_REMU];
assign req_muldiv_o = op_muldiv;
// CSR info
wire op_csr = (disp_info_grp == `DECINFO_GRP_CSR);
wire[`DECINFO_WIDTH-1:0] csr_info = {`DECINFO_WIDTH{op_csr}} & dec_info_bus_i;
// CSR op1
wire csr_rs1imm = csr_info[`DECINFO_CSR_RS1IMM];
wire[31:0] csr_rs1 = csr_rs1imm? dec_imm_i: rs1_rdata_i;
assign csr_op1_o = op_csr? csr_rs1: 32'h0;
assign csr_addr_o = {{20{1'b0}}, csr_info[`DECINFO_CSR_CSRADDR]};
assign csr_csrrw_o = csr_info[`DECINFO_CSR_CSRRW];
assign csr_csrrs_o = csr_info[`DECINFO_CSR_CSRRS];
assign csr_csrrc_o = csr_info[`DECINFO_CSR_CSRRC];
assign req_csr_o = op_csr;
// MEM info
wire op_mem = (disp_info_grp == `DECINFO_GRP_MEM);
wire[`DECINFO_WIDTH-1:0] mem_info = {`DECINFO_WIDTH{op_mem}} & dec_info_bus_i;
assign mem_op_lb_o = mem_info[`DECINFO_MEM_LB];
assign mem_op_lh_o = mem_info[`DECINFO_MEM_LH];
assign mem_op_lw_o = mem_info[`DECINFO_MEM_LW];
assign mem_op_lbu_o = mem_info[`DECINFO_MEM_LBU];
assign mem_op_lhu_o = mem_info[`DECINFO_MEM_LHU];
assign mem_op_sb_o = mem_info[`DECINFO_MEM_SB];
assign mem_op_sh_o = mem_info[`DECINFO_MEM_SH];
assign mem_op_sw_o = mem_info[`DECINFO_MEM_SW];
assign mem_op1_o = op_mem? rs1_rdata_i: 32'h0;
assign mem_op2_o = op_mem? dec_imm_i: 32'h0;
assign mem_rs2_data_o = op_mem? rs2_rdata_i: 32'h0;
assign req_mem_o = op_mem;
// SYS info
wire op_sys = (disp_info_grp == `DECINFO_GRP_SYS);
wire[`DECINFO_WIDTH-1:0] sys_info = {`DECINFO_WIDTH{op_sys}} & dec_info_bus_i;
assign sys_op_nop_o = sys_info[`DECINFO_SYS_NOP];
assign sys_op_mret_o = sys_info[`DECINFO_SYS_MRET];
assign sys_op_ecall_o = sys_info[`DECINFO_SYS_ECALL];
assign sys_op_ebreak_o = sys_info[`DECINFO_SYS_EBREAK];
assign sys_op_fence_o = sys_info[`DECINFO_SYS_FENCE];
endmodule

162
rtl/core/exu_mem.v Normal file
View File

@ -0,0 +1,162 @@
/*
Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
module exu_mem(
input wire clk,
input wire rst_n,
input req_mem_i,
input wire[31:0] mem_addr_i,
input wire[31:0] mem_rs2_data_i,
input wire[31:0] mem_rdata_i,
input wire mem_req_ready_i,
input wire mem_rsp_valid_i,
input wire mem_op_lb_i,
input wire mem_op_lh_i,
input wire mem_op_lw_i,
input wire mem_op_lbu_i,
input wire mem_op_lhu_i,
input wire mem_op_sb_i,
input wire mem_op_sh_i,
input wire mem_op_sw_i,
output wire mem_access_misaligned_o,
output wire mem_stall_o,
output wire[31:0] mem_addr_o,
output wire[31:0] mem_wdata_o,
output wire mem_reg_we_o,
output wire mem_mem_we_o,
output wire[3:0] mem_sel_o,
output wire mem_req_valid_o,
output wire mem_rsp_ready_o
);
wire[1:0] mem_addr_index = mem_addr_i[1:0];
wire mem_addr_index00 = (mem_addr_index == 2'b00);
wire mem_addr_index01 = (mem_addr_index == 2'b01);
wire mem_addr_index10 = (mem_addr_index == 2'b10);
wire mem_addr_index11 = (mem_addr_index == 2'b11);
assign mem_sel_o[0] = mem_addr_index00 | mem_op_sw_i;
assign mem_sel_o[1] = mem_addr_index01 | (mem_op_sh_i & mem_addr_index00) | mem_op_sw_i;
assign mem_sel_o[2] = mem_addr_index10 | mem_op_sw_i;
assign mem_sel_o[3] = mem_addr_index11 | (mem_op_sh_i & mem_addr_index10) | mem_op_sw_i;
reg[31:0] sb_res;
always @ (*) begin
sb_res = 32'h0;
case (1'b1)
mem_addr_index00: sb_res = {24'h0, mem_rs2_data_i[7:0]};
mem_addr_index01: sb_res = {16'h0, mem_rs2_data_i[7:0], 8'h0};
mem_addr_index10: sb_res = {8'h0, mem_rs2_data_i[7:0], 16'h0};
mem_addr_index11: sb_res = {mem_rs2_data_i[7:0], 24'h0};
endcase
end
reg[31:0] sh_res;
always @ (*) begin
sh_res = 32'h0;
case (1'b1)
mem_addr_index00: sh_res = {16'h0, mem_rs2_data_i[15:0]};
mem_addr_index10: sh_res = {mem_rs2_data_i[15:0], 16'h0};
endcase
end
wire[31:0] sw_res = mem_rs2_data_i;
reg[31:0] lb_res;
always @ (*) begin
lb_res = 32'h0;
case (1'b1)
mem_addr_index00: lb_res = {{24{mem_op_lb_i & mem_rdata_i[7]}}, mem_rdata_i[7:0]};
mem_addr_index01: lb_res = {{24{mem_op_lb_i & mem_rdata_i[15]}}, mem_rdata_i[15:8]};
mem_addr_index10: lb_res = {{24{mem_op_lb_i & mem_rdata_i[23]}}, mem_rdata_i[23:16]};
mem_addr_index11: lb_res = {{24{mem_op_lb_i & mem_rdata_i[31]}}, mem_rdata_i[31:24]};
endcase
end
reg[31:0] lh_res;
always @ (*) begin
lh_res = 32'h0;
case (1'b1)
mem_addr_index00: lh_res = {{24{mem_op_lh_i & mem_rdata_i[15]}}, mem_rdata_i[15:0]};
mem_addr_index10: lh_res = {{24{mem_op_lh_i & mem_rdata_i[31]}}, mem_rdata_i[31:16]};
endcase
end
wire[31:0] lw_res = mem_rdata_i;
reg[31:0] mem_wdata;
always @ (*) begin
mem_wdata = 32'h0;
case (1'b1)
mem_op_sb_i: mem_wdata = sb_res;
mem_op_sh_i: mem_wdata = sh_res;
mem_op_sw_i: mem_wdata = sw_res;
mem_op_lb_i: mem_wdata = lb_res;
mem_op_lbu_i: mem_wdata = lb_res;
mem_op_lh_i: mem_wdata = lh_res;
mem_op_lhu_i: mem_wdata = lh_res;
mem_op_lw_i: mem_wdata = lw_res;
endcase
end
assign mem_wdata_o = mem_wdata;
wire mem_req_hsked = (mem_req_valid_o & mem_req_ready_i);
wire mem_rsp_hsked = (mem_rsp_valid_i & mem_rsp_ready_o);
reg mem_rsp_hsked_r;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
mem_rsp_hsked_r <= 1'b0;
end else begin
mem_rsp_hsked_r <= mem_rsp_hsked & (~mem_rsp_hsked_r);
end
end
assign mem_rsp_ready_o = 1'b1;
// 访线
assign mem_req_valid_o = req_mem_i;
// 线
assign mem_stall_o = req_mem_i & (~mem_rsp_hsked_r);
//
assign mem_addr_o = mem_addr_i;
// 使ack
assign mem_reg_we_o = (mem_op_lb_i | mem_op_lh_i | mem_op_lw_i | mem_op_lbu_i | mem_op_lhu_i) & mem_rsp_hsked_r;
// 使
assign mem_mem_we_o = (mem_op_sb_i | mem_op_sh_i | mem_op_sw_i) & mem_rsp_hsked_r;
assign mem_access_misaligned_o = (mem_op_sw_i | mem_op_lw_i)? (mem_addr_i[0] | mem_addr_i[1]):
(mem_op_sh_i | mem_op_lh_i | mem_op_lhu_i)? mem_addr_i[0]:
0;
endmodule

106
rtl/core/exu_muldiv.v Normal file
View File

@ -0,0 +1,106 @@
/*
Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
module exu_muldiv(
input wire clk,
input wire rst_n,
input wire[31:0] muldiv_op1_i,
input wire[31:0] muldiv_op2_i,
input wire muldiv_op_mul_i,
input wire muldiv_op_mulh_i,
input wire muldiv_op_mulhsu_i,
input wire muldiv_op_mulhu_i,
input wire muldiv_op_div_i,
input wire muldiv_op_divu_i,
input wire muldiv_op_rem_i,
input wire muldiv_op_remu_i,
output wire[31:0] muldiv_reg_wdata_o,
output wire muldiv_reg_we_o,
output wire muldiv_stall_o
);
//
wire op_div = muldiv_op_div_i | muldiv_op_divu_i | muldiv_op_rem_i | muldiv_op_remu_i;
wire div_start = op_div & (!div_ready);
wire[3:0] div_op = {muldiv_op_div_i, muldiv_op_divu_i, muldiv_op_rem_i, muldiv_op_remu_i};
wire[31:0] div_result;
wire div_ready;
divider u_divider(
.clk(clk),
.rst_n(rst_n),
.dividend_i(muldiv_op1_i),
.divisor_i(muldiv_op2_i),
.start_i(div_start),
.op_i(div_op),
.result_o(div_result),
.ready_o(div_ready)
);
//
wire op_mul = muldiv_op_mul_i | muldiv_op_mulh_i | muldiv_op_mulhsu_i | muldiv_op_mulhu_i;
wire[31:0] muldiv_op1_r;
gen_en_dff #(32) mul_op1_ff(clk, rst_n, op_mul, muldiv_op1_i, muldiv_op1_r);
wire[31:0] muldiv_op2_r;
gen_en_dff #(32) mul_op2_ff(clk, rst_n, op_mul, muldiv_op2_i, muldiv_op2_r);
wire mul_ready_r;
wire mul_ready = (~mul_ready_r) & op_mul;
gen_rst_0_dff #(1) mul_ready_ff(clk, rst_n, mul_ready, mul_ready_r);
wire mul_start = (~mul_ready_r) & op_mul;
wire op1_is_signed = muldiv_op1_r[31];
wire op2_is_signed = muldiv_op2_r[31];
wire[31:0] op1_complcode = op1_is_signed? (-muldiv_op1_r): muldiv_op1_r;
wire[31:0] op2_complcode = op2_is_signed? (-muldiv_op2_r): muldiv_op2_r;
wire[31:0] op1_mul = ({32{(muldiv_op_mul_i | muldiv_op_mulhu_i)}} & muldiv_op1_r) |
({32{(muldiv_op_mulh_i | muldiv_op_mulhsu_i)}} & op1_complcode);
wire[31:0] op2_mul = ({32{(muldiv_op_mul_i | muldiv_op_mulhu_i | muldiv_op_mulhsu_i)}} & muldiv_op2_r) |
({32{(muldiv_op_mulh_i)}} & op2_complcode);
wire[63:0] mul_res_tmp = op1_mul * op2_mul;
wire[63:0] mul_res_tmp_complcode = -mul_res_tmp;
wire[31:0] mul_res = mul_res_tmp[31:0];
wire[31:0] mulhu_res = mul_res_tmp[63:32];
wire[31:0] mulh_res = (op1_is_signed ^ op2_is_signed)? mul_res_tmp_complcode[63:32]: mul_res_tmp[63:32];
wire[31:0] mulhsu_res = (op1_is_signed)? mul_res_tmp_complcode[63:32]: mul_res_tmp[63:32];
reg[31:0] mul_op_res;
always @ (*) begin
mul_op_res = 32'h0;
case (1'b1)
muldiv_op_mul_i: mul_op_res = mul_res;
muldiv_op_mulhu_i: mul_op_res = mulhu_res;
muldiv_op_mulh_i: mul_op_res = mulh_res;
muldiv_op_mulhsu_i: mul_op_res = mulhsu_res;
endcase
end
//
assign muldiv_reg_wdata_o = div_result | mul_op_res;
assign muldiv_reg_we_o = div_ready | mul_ready_r;
assign muldiv_stall_o = div_start | mul_start;
endmodule

92
rtl/core/gpr_reg.v Normal file
View File

@ -0,0 +1,92 @@
/*
Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
//
module gpr_reg(
input wire clk,
input wire rst_n,
input wire we_i, // 使
input wire[4:0] waddr_i, //
input wire[31:0] wdata_i, //
input wire[4:0] raddr1_i, // 1
output wire[31:0] rdata1_o, // 1
input wire[4:0] raddr2_i, // 2
output wire[31:0] rdata2_o // 2
);
wire[32-1:0] regs[32-1:0];
wire[32-1:0] we;
genvar i;
generate
for (i = 0; i < 32; i = i + 1) begin: gpr_rw
// x0 cannot be wrote since it is constant-zeros
if (i == 0) begin: is_x0
assign we[i] = 1'b0;
assign regs[i] = 32'h0;
end else begin: not_x0
assign we[i] = we_i & (waddr_i == i);
gen_en_dffnr #(32) rf_dff(clk, we[i], wdata_i, regs[i]);
end
end
endgenerate
assign rdata1_o = (|raddr1_i)? ((we_i & (waddr_i == raddr1_i))? wdata_i: regs[raddr1_i]): 32'h0;
assign rdata2_o = (|raddr2_i)? ((we_i & (waddr_i == raddr2_i))? wdata_i: regs[raddr2_i]): 32'h0;
// for debug
wire[31:0] ra = regs[1];
wire[31:0] sp = regs[2];
wire[31:0] gp = regs[3];
wire[31:0] tp = regs[4];
wire[31:0] t0 = regs[5];
wire[31:0] t1 = regs[6];
wire[31:0] t2 = regs[7];
wire[31:0] s0 = regs[8];
wire[31:0] fp = regs[8];
wire[31:0] s1 = regs[9];
wire[31:0] a0 = regs[10];
wire[31:0] a1 = regs[11];
wire[31:0] a2 = regs[12];
wire[31:0] a3 = regs[13];
wire[31:0] a4 = regs[14];
wire[31:0] a5 = regs[15];
wire[31:0] a6 = regs[16];
wire[31:0] a7 = regs[17];
wire[31:0] s2 = regs[18];
wire[31:0] s3 = regs[19];
wire[31:0] s4 = regs[20];
wire[31:0] s5 = regs[21];
wire[31:0] s6 = regs[22];
wire[31:0] s7 = regs[23];
wire[31:0] s8 = regs[24];
wire[31:0] s9 = regs[25];
wire[31:0] s10 = regs[26];
wire[31:0] s11 = regs[27];
wire[31:0] t3 = regs[28];
wire[31:0] t4 = regs[29];
wire[31:0] t5 = regs[30];
wire[31:0] t6 = regs[31];
endmodule

View File

@ -1,302 +0,0 @@
/*
Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
//
//
module id(
input wire rst,
// from if_id
input wire[`InstBus] inst_i, //
input wire[`InstAddrBus] inst_addr_i, //
// from regs
input wire[`RegBus] reg1_rdata_i, // 1
input wire[`RegBus] reg2_rdata_i, // 2
// from csr reg
input wire[`RegBus] csr_rdata_i, // CSR
// from ex
input wire ex_jump_flag_i, //
// to regs
output reg[`RegAddrBus] reg1_raddr_o, // 1
output reg[`RegAddrBus] reg2_raddr_o, // 2
// to csr reg
output reg[`MemAddrBus] csr_raddr_o, // CSR
// to ex
output reg[`MemAddrBus] op1_o,
output reg[`MemAddrBus] op2_o,
output reg[`MemAddrBus] op1_jump_o,
output reg[`MemAddrBus] op2_jump_o,
output reg[`InstBus] inst_o, //
output reg[`InstAddrBus] inst_addr_o, //
output reg[`RegBus] reg1_rdata_o, // 1
output reg[`RegBus] reg2_rdata_o, // 2
output reg reg_we_o, //
output reg[`RegAddrBus] reg_waddr_o, //
output reg csr_we_o, // CSR
output reg[`RegBus] csr_rdata_o, // CSR
output reg[`MemAddrBus] csr_waddr_o // CSR
);
wire[6:0] opcode = inst_i[6:0];
wire[2:0] funct3 = inst_i[14:12];
wire[6:0] funct7 = inst_i[31:25];
wire[4:0] rd = inst_i[11:7];
wire[4:0] rs1 = inst_i[19:15];
wire[4:0] rs2 = inst_i[24:20];
always @ (*) begin
inst_o = inst_i;
inst_addr_o = inst_addr_i;
reg1_rdata_o = reg1_rdata_i;
reg2_rdata_o = reg2_rdata_i;
csr_rdata_o = csr_rdata_i;
csr_raddr_o = `ZeroWord;
csr_waddr_o = `ZeroWord;
csr_we_o = `WriteDisable;
op1_o = `ZeroWord;
op2_o = `ZeroWord;
op1_jump_o = `ZeroWord;
op2_jump_o = `ZeroWord;
case (opcode)
`INST_TYPE_I: begin
case (funct3)
`INST_ADDI, `INST_SLTI, `INST_SLTIU, `INST_XORI, `INST_ORI, `INST_ANDI, `INST_SLLI, `INST_SRI: begin
reg_we_o = `WriteEnable;
reg_waddr_o = rd;
reg1_raddr_o = rs1;
reg2_raddr_o = `ZeroReg;
op1_o = reg1_rdata_i;
op2_o = {{20{inst_i[31]}}, inst_i[31:20]};
end
default: begin
reg_we_o = `WriteDisable;
reg_waddr_o = `ZeroReg;
reg1_raddr_o = `ZeroReg;
reg2_raddr_o = `ZeroReg;
end
endcase
end
`INST_TYPE_R_M: begin
if ((funct7 == 7'b0000000) || (funct7 == 7'b0100000)) begin
case (funct3)
`INST_ADD_SUB, `INST_SLL, `INST_SLT, `INST_SLTU, `INST_XOR, `INST_SR, `INST_OR, `INST_AND: begin
reg_we_o = `WriteEnable;
reg_waddr_o = rd;
reg1_raddr_o = rs1;
reg2_raddr_o = rs2;
op1_o = reg1_rdata_i;
op2_o = reg2_rdata_i;
end
default: begin
reg_we_o = `WriteDisable;
reg_waddr_o = `ZeroReg;
reg1_raddr_o = `ZeroReg;
reg2_raddr_o = `ZeroReg;
end
endcase
end else if (funct7 == 7'b0000001) begin
case (funct3)
`INST_MUL, `INST_MULHU, `INST_MULH, `INST_MULHSU: begin
reg_we_o = `WriteEnable;
reg_waddr_o = rd;
reg1_raddr_o = rs1;
reg2_raddr_o = rs2;
op1_o = reg1_rdata_i;
op2_o = reg2_rdata_i;
end
`INST_DIV, `INST_DIVU, `INST_REM, `INST_REMU: begin
reg_we_o = `WriteDisable;
reg_waddr_o = rd;
reg1_raddr_o = rs1;
reg2_raddr_o = rs2;
op1_o = reg1_rdata_i;
op2_o = reg2_rdata_i;
op1_jump_o = inst_addr_i;
op2_jump_o = 32'h4;
end
default: begin
reg_we_o = `WriteDisable;
reg_waddr_o = `ZeroReg;
reg1_raddr_o = `ZeroReg;
reg2_raddr_o = `ZeroReg;
end
endcase
end else begin
reg_we_o = `WriteDisable;
reg_waddr_o = `ZeroReg;
reg1_raddr_o = `ZeroReg;
reg2_raddr_o = `ZeroReg;
end
end
`INST_TYPE_L: begin
case (funct3)
`INST_LB, `INST_LH, `INST_LW, `INST_LBU, `INST_LHU: begin
reg1_raddr_o = rs1;
reg2_raddr_o = `ZeroReg;
reg_we_o = `WriteEnable;
reg_waddr_o = rd;
op1_o = reg1_rdata_i;
op2_o = {{20{inst_i[31]}}, inst_i[31:20]};
end
default: begin
reg1_raddr_o = `ZeroReg;
reg2_raddr_o = `ZeroReg;
reg_we_o = `WriteDisable;
reg_waddr_o = `ZeroReg;
end
endcase
end
`INST_TYPE_S: begin
case (funct3)
`INST_SB, `INST_SW, `INST_SH: begin
reg1_raddr_o = rs1;
reg2_raddr_o = rs2;
reg_we_o = `WriteDisable;
reg_waddr_o = `ZeroReg;
op1_o = reg1_rdata_i;
op2_o = {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]};
end
default: begin
reg1_raddr_o = `ZeroReg;
reg2_raddr_o = `ZeroReg;
reg_we_o = `WriteDisable;
reg_waddr_o = `ZeroReg;
end
endcase
end
`INST_TYPE_B: begin
case (funct3)
`INST_BEQ, `INST_BNE, `INST_BLT, `INST_BGE, `INST_BLTU, `INST_BGEU: begin
reg1_raddr_o = rs1;
reg2_raddr_o = rs2;
reg_we_o = `WriteDisable;
reg_waddr_o = `ZeroReg;
op1_o = reg1_rdata_i;
op2_o = reg2_rdata_i;
op1_jump_o = inst_addr_i;
op2_jump_o = {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
end
default: begin
reg1_raddr_o = `ZeroReg;
reg2_raddr_o = `ZeroReg;
reg_we_o = `WriteDisable;
reg_waddr_o = `ZeroReg;
end
endcase
end
`INST_JAL: begin
reg_we_o = `WriteEnable;
reg_waddr_o = rd;
reg1_raddr_o = `ZeroReg;
reg2_raddr_o = `ZeroReg;
op1_o = inst_addr_i;
op2_o = 32'h4;
op1_jump_o = inst_addr_i;
op2_jump_o = {{12{inst_i[31]}}, inst_i[19:12], inst_i[20], inst_i[30:21], 1'b0};
end
`INST_JALR: begin
reg_we_o = `WriteEnable;
reg1_raddr_o = rs1;
reg2_raddr_o = `ZeroReg;
reg_waddr_o = rd;
op1_o = inst_addr_i;
op2_o = 32'h4;
op1_jump_o = reg1_rdata_i;
op2_jump_o = {{20{inst_i[31]}}, inst_i[31:20]};
end
`INST_LUI: begin
reg_we_o = `WriteEnable;
reg_waddr_o = rd;
reg1_raddr_o = `ZeroReg;
reg2_raddr_o = `ZeroReg;
op1_o = {inst_i[31:12], 12'b0};
op2_o = `ZeroWord;
end
`INST_AUIPC: begin
reg_we_o = `WriteEnable;
reg_waddr_o = rd;
reg1_raddr_o = `ZeroReg;
reg2_raddr_o = `ZeroReg;
op1_o = inst_addr_i;
op2_o = {inst_i[31:12], 12'b0};
end
`INST_NOP_OP: begin
reg_we_o = `WriteDisable;
reg_waddr_o = `ZeroReg;
reg1_raddr_o = `ZeroReg;
reg2_raddr_o = `ZeroReg;
end
`INST_FENCE: begin
reg_we_o = `WriteDisable;
reg_waddr_o = `ZeroReg;
reg1_raddr_o = `ZeroReg;
reg2_raddr_o = `ZeroReg;
op1_jump_o = inst_addr_i;
op2_jump_o = 32'h4;
end
`INST_CSR: begin
reg_we_o = `WriteDisable;
reg_waddr_o = `ZeroReg;
reg1_raddr_o = `ZeroReg;
reg2_raddr_o = `ZeroReg;
csr_raddr_o = {20'h0, inst_i[31:20]};
csr_waddr_o = {20'h0, inst_i[31:20]};
case (funct3)
`INST_CSRRW, `INST_CSRRS, `INST_CSRRC: begin
reg1_raddr_o = rs1;
reg2_raddr_o = `ZeroReg;
reg_we_o = `WriteEnable;
reg_waddr_o = rd;
csr_we_o = `WriteEnable;
end
`INST_CSRRWI, `INST_CSRRSI, `INST_CSRRCI: begin
reg1_raddr_o = `ZeroReg;
reg2_raddr_o = `ZeroReg;
reg_we_o = `WriteEnable;
reg_waddr_o = rd;
csr_we_o = `WriteEnable;
end
default: begin
reg_we_o = `WriteDisable;
reg_waddr_o = `ZeroReg;
reg1_raddr_o = `ZeroReg;
reg2_raddr_o = `ZeroReg;
csr_we_o = `WriteDisable;
end
endcase
end
default: begin
reg_we_o = `WriteDisable;
reg_waddr_o = `ZeroReg;
reg1_raddr_o = `ZeroReg;
reg2_raddr_o = `ZeroReg;
end
endcase
end
endmodule

View File

@ -1,111 +0,0 @@
/*
Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
//
module id_ex(
input wire clk,
input wire rst,
input wire[`InstBus] inst_i, //
input wire[`InstAddrBus] inst_addr_i, //
input wire reg_we_i, //
input wire[`RegAddrBus] reg_waddr_i, //
input wire[`RegBus] reg1_rdata_i, // 1
input wire[`RegBus] reg2_rdata_i, // 2
input wire csr_we_i, // CSR
input wire[`MemAddrBus] csr_waddr_i, // CSR
input wire[`RegBus] csr_rdata_i, // CSR
input wire[`MemAddrBus] op1_i,
input wire[`MemAddrBus] op2_i,
input wire[`MemAddrBus] op1_jump_i,
input wire[`MemAddrBus] op2_jump_i,
input wire[`Hold_Flag_Bus] hold_flag_i, // 线
output wire[`MemAddrBus] op1_o,
output wire[`MemAddrBus] op2_o,
output wire[`MemAddrBus] op1_jump_o,
output wire[`MemAddrBus] op2_jump_o,
output wire[`InstBus] inst_o, //
output wire[`InstAddrBus] inst_addr_o, //
output wire reg_we_o, //
output wire[`RegAddrBus] reg_waddr_o, //
output wire[`RegBus] reg1_rdata_o, // 1
output wire[`RegBus] reg2_rdata_o, // 2
output wire csr_we_o, // CSR
output wire[`MemAddrBus] csr_waddr_o, // CSR
output wire[`RegBus] csr_rdata_o // CSR
);
wire hold_en = (hold_flag_i >= `Hold_Id);
wire[`InstBus] inst;
gen_pipe_dff #(32) inst_ff(clk, rst, hold_en, `INST_NOP, inst_i, inst);
assign inst_o = inst;
wire[`InstAddrBus] inst_addr;
gen_pipe_dff #(32) inst_addr_ff(clk, rst, hold_en, `ZeroWord, inst_addr_i, inst_addr);
assign inst_addr_o = inst_addr;
wire reg_we;
gen_pipe_dff #(1) reg_we_ff(clk, rst, hold_en, `WriteDisable, reg_we_i, reg_we);
assign reg_we_o = reg_we;
wire[`RegAddrBus] reg_waddr;
gen_pipe_dff #(5) reg_waddr_ff(clk, rst, hold_en, `ZeroReg, reg_waddr_i, reg_waddr);
assign reg_waddr_o = reg_waddr;
wire[`RegBus] reg1_rdata;
gen_pipe_dff #(32) reg1_rdata_ff(clk, rst, hold_en, `ZeroWord, reg1_rdata_i, reg1_rdata);
assign reg1_rdata_o = reg1_rdata;
wire[`RegBus] reg2_rdata;
gen_pipe_dff #(32) reg2_rdata_ff(clk, rst, hold_en, `ZeroWord, reg2_rdata_i, reg2_rdata);
assign reg2_rdata_o = reg2_rdata;
wire csr_we;
gen_pipe_dff #(1) csr_we_ff(clk, rst, hold_en, `WriteDisable, csr_we_i, csr_we);
assign csr_we_o = csr_we;
wire[`MemAddrBus] csr_waddr;
gen_pipe_dff #(32) csr_waddr_ff(clk, rst, hold_en, `ZeroWord, csr_waddr_i, csr_waddr);
assign csr_waddr_o = csr_waddr;
wire[`RegBus] csr_rdata;
gen_pipe_dff #(32) csr_rdata_ff(clk, rst, hold_en, `ZeroWord, csr_rdata_i, csr_rdata);
assign csr_rdata_o = csr_rdata;
wire[`MemAddrBus] op1;
gen_pipe_dff #(32) op1_ff(clk, rst, hold_en, `ZeroWord, op1_i, op1);
assign op1_o = op1;
wire[`MemAddrBus] op2;
gen_pipe_dff #(32) op2_ff(clk, rst, hold_en, `ZeroWord, op2_i, op2);
assign op2_o = op2;
wire[`MemAddrBus] op1_jump;
gen_pipe_dff #(32) op1_jump_ff(clk, rst, hold_en, `ZeroWord, op1_jump_i, op1_jump);
assign op1_jump_o = op1_jump;
wire[`MemAddrBus] op2_jump;
gen_pipe_dff #(32) op2_jump_ff(clk, rst, hold_en, `ZeroWord, op2_jump_i, op2_jump);
assign op2_jump_o = op2_jump;
endmodule

303
rtl/core/idu.v Normal file
View File

@ -0,0 +1,303 @@
/*
Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
//
//
module idu(
input wire clk,
input wire rst_n,
// from if_id
input wire[31:0] inst_i, //
input wire[31:0] inst_addr_i, //
// from gpr_reg
input wire[31:0] rs1_rdata_i, // 1
input wire[31:0] rs2_rdata_i, // 2
output wire stall_o,
// to id_ex
output wire[31:0] inst_o,
output wire[`DECINFO_WIDTH-1:0] dec_info_bus_o,
output wire[31:0] dec_imm_o,
output wire[31:0] dec_pc_o,
output wire[4:0] rs1_raddr_o,
output wire[4:0] rs2_raddr_o,
output wire[31:0] rs1_rdata_o,
output wire[31:0] rs2_rdata_o,
output wire[4:0] rd_waddr_o,
output wire rd_we_o
);
assign inst_o = inst_i;
assign rs1_rdata_o = rs1_rdata_i;
assign rs2_rdata_o = rs2_rdata_i;
//
wire[6:0] opcode = inst_i[6:0];
wire[2:0] funct3 = inst_i[14:12];
wire[6:0] funct7 = inst_i[31:25];
wire[4:0] rd = inst_i[11:7];
wire[4:0] rs1 = inst_i[19:15];
wire[4:0] rs2 = inst_i[24:20];
wire[11:0] type_i_imm_11_0 = inst_i[31:20];
wire[6:0] type_s_imm_11_5 = inst_i[31:25];
wire[4:0] type_s_imm_4_0 = inst_i[11:7];
wire[6:0] type_b_imm_12_10_5 = inst_i[31:25];
wire[4:0] type_b_imm_4_1_11 = inst_i[11:7];
wire[19:0] type_u_imm_31_12 = inst_i[31:12];
wire[19:0] type_j_imm_31_12 = inst_i[31:12];
// opcode
wire opcode_0110111 = (opcode == 7'b0110111);
wire opcode_0010111 = (opcode == 7'b0010111);
wire opcode_1101111 = (opcode == 7'b1101111);
wire opcode_1100111 = (opcode == 7'b1100111);
wire opcode_1100011 = (opcode == 7'b1100011);
wire opcode_0000011 = (opcode == 7'b0000011);
wire opcode_0100011 = (opcode == 7'b0100011);
wire opcode_0010011 = (opcode == 7'b0010011);
wire opcode_0110011 = (opcode == 7'b0110011);
wire opcode_0001111 = (opcode == 7'b0001111);
wire opcode_1110011 = (opcode == 7'b1110011);
// funct3
wire funct3_000 = (funct3 == 3'b000);
wire funct3_001 = (funct3 == 3'b001);
wire funct3_010 = (funct3 == 3'b010);
wire funct3_011 = (funct3 == 3'b011);
wire funct3_100 = (funct3 == 3'b100);
wire funct3_101 = (funct3 == 3'b101);
wire funct3_110 = (funct3 == 3'b110);
wire funct3_111 = (funct3 == 3'b111);
// funct7
wire funct7_0000000 = (funct7 == 7'b0000000);
wire funct7_0100000 = (funct7 == 7'b0100000);
wire funct7_0000001 = (funct7 == 7'b0000001);
// Iimm
wire type_i_imm_000000000000 = (type_i_imm_11_0 == 12'b000000000000);
wire type_i_imm_000000000001 = (type_i_imm_11_0 == 12'b000000000001);
//
wire inst_lui = opcode_0110111;
wire inst_auipc = opcode_0010111;
wire inst_jal = opcode_1101111;
wire inst_jalr = opcode_1100111 & funct3_000;
wire inst_beq = opcode_1100011 & funct3_000;
wire inst_bne = opcode_1100011 & funct3_001;
wire inst_blt = opcode_1100011 & funct3_100;
wire inst_bge = opcode_1100011 & funct3_101;
wire inst_bltu = opcode_1100011 & funct3_110;
wire inst_bgeu = opcode_1100011 & funct3_111;
wire inst_lb = opcode_0000011 & funct3_000;
wire inst_lh = opcode_0000011 & funct3_001;
wire inst_lw = opcode_0000011 & funct3_010;
wire inst_lbu = opcode_0000011 & funct3_100;
wire inst_lhu = opcode_0000011 & funct3_101;
wire inst_sb = opcode_0100011 & funct3_000;
wire inst_sh = opcode_0100011 & funct3_001;
wire inst_sw = opcode_0100011 & funct3_010;
wire inst_addi = opcode_0010011 & funct3_000;
wire inst_slti = opcode_0010011 & funct3_010;
wire inst_sltiu = opcode_0010011 & funct3_011;
wire inst_xori = opcode_0010011 & funct3_100;
wire inst_ori = opcode_0010011 & funct3_110;
wire inst_andi = opcode_0010011 & funct3_111;
wire inst_slli = opcode_0010011 & funct3_001 & funct7_0000000;
wire inst_srli = opcode_0010011 & funct3_101 & funct7_0000000;
wire inst_srai = opcode_0010011 & funct3_101 & funct7_0100000;
wire inst_add = opcode_0110011 & funct3_000 & funct7_0000000;
wire inst_sub = opcode_0110011 & funct3_000 & funct7_0100000;
wire inst_sll = opcode_0110011 & funct3_001 & funct7_0000000;
wire inst_slt = opcode_0110011 & funct3_010 & funct7_0000000;
wire inst_sltu = opcode_0110011 & funct3_011 & funct7_0000000;
wire inst_xor = opcode_0110011 & funct3_100 & funct7_0000000;
wire inst_srl = opcode_0110011 & funct3_101 & funct7_0000000;
wire inst_sra = opcode_0110011 & funct3_101 & funct7_0100000;
wire inst_or = opcode_0110011 & funct3_110 & funct7_0000000;
wire inst_and = opcode_0110011 & funct3_111 & funct7_0000000;
wire inst_fence = opcode_0001111 & funct3_000;
wire inst_ecall = (inst_i == `INST_ECALL);
wire inst_ebreak = (inst_i == `INST_EBREAK);
wire inst_fence_i = opcode_0001111 & funct3_001;
wire inst_csrrw = opcode_1110011 & funct3_001;
wire inst_csrrs = opcode_1110011 & funct3_010;
wire inst_csrrc = opcode_1110011 & funct3_011;
wire inst_csrrwi = opcode_1110011 & funct3_101;
wire inst_csrrsi = opcode_1110011 & funct3_110;
wire inst_csrrci = opcode_1110011 & funct3_111;
wire inst_mul = opcode_0110011 & funct3_000 & funct7_0000001;
wire inst_mulh = opcode_0110011 & funct3_001 & funct7_0000001;
wire inst_mulhsu = opcode_0110011 & funct3_010 & funct7_0000001;
wire inst_mulhu = opcode_0110011 & funct3_011 & funct7_0000001;
wire inst_div = opcode_0110011 & funct3_100 & funct7_0000001;
wire inst_divu = opcode_0110011 & funct3_101 & funct7_0000001;
wire inst_rem = opcode_0110011 & funct3_110 & funct7_0000001;
wire inst_remu = opcode_0110011 & funct3_111 & funct7_0000001;
wire inst_nop = (inst_i == `INST_NOP);
wire inst_mret = (inst_i == `INST_MRET);
//
wire inst_type_load = opcode_0000011;
wire inst_type_store = opcode_0100011;
wire inst_type_branch = opcode_1100011;
wire inst_type_muldiv = inst_mul | inst_mulh | inst_mulhsu | inst_mulhu | inst_div | inst_divu | inst_rem | inst_remu;
wire inst_type_div = inst_div | inst_divu | inst_rem | inst_remu;
wire[`DECINFO_ALU_BUS_WIDTH-1:0] dec_alu_info_bus;
assign dec_alu_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_ALU;
assign dec_alu_info_bus[`DECINFO_ALU_LUI] = inst_lui;
assign dec_alu_info_bus[`DECINFO_ALU_AUIPC] = inst_auipc;
assign dec_alu_info_bus[`DECINFO_ALU_ADD] = inst_add | inst_addi;
assign dec_alu_info_bus[`DECINFO_ALU_SUB] = inst_sub;
assign dec_alu_info_bus[`DECINFO_ALU_SLL] = inst_sll | inst_slli;
assign dec_alu_info_bus[`DECINFO_ALU_SLT] = inst_slt | inst_slti;
assign dec_alu_info_bus[`DECINFO_ALU_SLTU] = inst_sltu | inst_sltiu;
assign dec_alu_info_bus[`DECINFO_ALU_XOR] = inst_xor | inst_xori;
assign dec_alu_info_bus[`DECINFO_ALU_SRL] = inst_srl | inst_srli;
assign dec_alu_info_bus[`DECINFO_ALU_SRA] = inst_sra | inst_srai;
assign dec_alu_info_bus[`DECINFO_ALU_OR] = inst_or | inst_ori;
assign dec_alu_info_bus[`DECINFO_ALU_AND] = inst_and | inst_andi;
assign dec_alu_info_bus[`DECINFO_ALU_OP2IMM] = opcode_0010011 | inst_lui | inst_auipc;
assign dec_alu_info_bus[`DECINFO_ALU_OP1PC] = inst_auipc;
wire[`DECINFO_BJP_BUS_WIDTH-1:0] dec_bjp_info_bus;
assign dec_bjp_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_BJP;
assign dec_bjp_info_bus[`DECINFO_BJP_JUMP] = inst_jal | inst_jalr;
assign dec_bjp_info_bus[`DECINFO_BJP_BEQ] = inst_beq;
assign dec_bjp_info_bus[`DECINFO_BJP_BNE] = inst_bne;
assign dec_bjp_info_bus[`DECINFO_BJP_BLT] = inst_blt;
assign dec_bjp_info_bus[`DECINFO_BJP_BGE] = inst_bge;
assign dec_bjp_info_bus[`DECINFO_BJP_BLTU] = inst_bltu;
assign dec_bjp_info_bus[`DECINFO_BJP_BGEU] = inst_bgeu;
assign dec_bjp_info_bus[`DECINFO_BJP_OP1RS1] = inst_jalr;
wire[`DECINFO_MULDIV_BUS_WIDTH-1:0] dec_muldiv_info_bus;
assign dec_muldiv_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_MULDIV;
assign dec_muldiv_info_bus[`DECINFO_MULDIV_MUL] = inst_mul;
assign dec_muldiv_info_bus[`DECINFO_MULDIV_MULH] = inst_mulh;
assign dec_muldiv_info_bus[`DECINFO_MULDIV_MULHSU] = inst_mulhsu;
assign dec_muldiv_info_bus[`DECINFO_MULDIV_MULHU] = inst_mulhu;
assign dec_muldiv_info_bus[`DECINFO_MULDIV_DIV] = inst_div;
assign dec_muldiv_info_bus[`DECINFO_MULDIV_DIVU] = inst_divu;
assign dec_muldiv_info_bus[`DECINFO_MULDIV_REM] = inst_rem;
assign dec_muldiv_info_bus[`DECINFO_MULDIV_REMU] = inst_remu;
wire[`DECINFO_CSR_BUS_WIDTH-1:0] dec_csr_info_bus;
assign dec_csr_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_CSR;
assign dec_csr_info_bus[`DECINFO_CSR_CSRRW] = inst_csrrw | inst_csrrwi;
assign dec_csr_info_bus[`DECINFO_CSR_CSRRS] = inst_csrrs | inst_csrrsi;
assign dec_csr_info_bus[`DECINFO_CSR_CSRRC] = inst_csrrc | inst_csrrci;
assign dec_csr_info_bus[`DECINFO_CSR_RS1IMM] = inst_csrrwi | inst_csrrsi | inst_csrrci;
assign dec_csr_info_bus[`DECINFO_CSR_CSRADDR] = inst_i[31:20];
wire[`DECINFO_MEM_BUS_WIDTH-1:0] dec_mem_info_bus;
assign dec_mem_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_MEM;
assign dec_mem_info_bus[`DECINFO_MEM_LB] = inst_lb;
assign dec_mem_info_bus[`DECINFO_MEM_LH] = inst_lh;
assign dec_mem_info_bus[`DECINFO_MEM_LW] = inst_lw;
assign dec_mem_info_bus[`DECINFO_MEM_LBU] = inst_lbu;
assign dec_mem_info_bus[`DECINFO_MEM_LHU] = inst_lhu;
assign dec_mem_info_bus[`DECINFO_MEM_SB] = inst_sb;
assign dec_mem_info_bus[`DECINFO_MEM_SH] = inst_sh;
assign dec_mem_info_bus[`DECINFO_MEM_SW] = inst_sw;
wire[`DECINFO_SYS_BUS_WIDTH-1:0] dec_sys_info_bus;
assign dec_sys_info_bus[`DECINFO_GRP_BUS] = `DECINFO_GRP_SYS;
assign dec_sys_info_bus[`DECINFO_SYS_ECALL] = inst_ecall;
assign dec_sys_info_bus[`DECINFO_SYS_EBREAK] = inst_ebreak;
assign dec_sys_info_bus[`DECINFO_SYS_NOP] = inst_nop;
assign dec_sys_info_bus[`DECINFO_SYS_MRET] = inst_mret;
assign dec_sys_info_bus[`DECINFO_SYS_FENCE] = inst_fence | inst_fence_i;
//
wire[31:0] inst_u_type_imm = {inst_i[31:12], 12'b0};
wire[31:0] inst_j_type_imm = {{12{inst_i[31]}}, inst_i[19:12], inst_i[20], inst_i[30:21], 1'b0};
wire[31:0] inst_b_type_imm = {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0};
wire[31:0] inst_s_type_imm = {{20{inst_i[31]}}, inst_i[31:25], inst_i[11:7]};
wire[31:0] inst_i_type_imm = {{20{inst_i[31]}}, inst_i[31:20]};
wire[31:0] inst_csr_type_imm = {27'h0, inst_i[19:15]};
wire[31:0] inst_shift_type_imm = {27'h0, inst_i[24:20]};
wire inst_sel_u_imm = inst_lui | inst_auipc;
wire inst_sel_j_imm = inst_jal;
wire inst_sel_b_imm = inst_type_branch;
wire inst_sel_s_imm = inst_type_store;
wire inst_sel_i_imm = inst_addi | inst_slti | inst_sltiu | inst_xori | inst_ori | inst_andi | inst_type_load | inst_jalr;
wire inst_sel_csr_imm = inst_csrrwi | inst_csrrsi | inst_csrrci;
wire inst_sel_shift_imm = inst_slli | inst_srli | inst_srai;
assign dec_imm_o = ({32{inst_sel_u_imm}} & inst_u_type_imm) |
({32{inst_sel_j_imm}} & inst_j_type_imm) |
({32{inst_sel_b_imm}} & inst_b_type_imm) |
({32{inst_sel_s_imm}} & inst_s_type_imm) |
({32{inst_sel_i_imm}} & inst_i_type_imm) |
({32{inst_sel_csr_imm}} & inst_csr_type_imm) |
({32{inst_sel_shift_imm}} & inst_shift_type_imm);
wire op_alu = inst_lui | inst_auipc | opcode_0010011 | (opcode_0110011 & (~inst_type_muldiv));
wire op_bjp = inst_jal | inst_jalr | inst_type_branch;
wire op_muldiv = inst_type_muldiv;
wire op_csr = inst_csrrw | inst_csrrwi | inst_csrrs | inst_csrrsi | inst_csrrc | inst_csrrci;
wire op_sys = inst_ebreak | inst_ecall | inst_nop | inst_mret | inst_fence | inst_fence_i;
wire op_mem = inst_type_load | inst_type_store;
assign dec_info_bus_o = ({`DECINFO_WIDTH{op_alu}} & {{`DECINFO_WIDTH-`DECINFO_ALU_BUS_WIDTH{1'b0}}, dec_alu_info_bus}) |
({`DECINFO_WIDTH{op_bjp}} & {{`DECINFO_WIDTH-`DECINFO_BJP_BUS_WIDTH{1'b0}}, dec_bjp_info_bus}) |
({`DECINFO_WIDTH{op_muldiv}} & {{`DECINFO_WIDTH-`DECINFO_MULDIV_BUS_WIDTH{1'b0}}, dec_muldiv_info_bus}) |
({`DECINFO_WIDTH{op_csr}} & {{`DECINFO_WIDTH-`DECINFO_CSR_BUS_WIDTH{1'b0}}, dec_csr_info_bus}) |
({`DECINFO_WIDTH{op_mem}} & {{`DECINFO_WIDTH-`DECINFO_MEM_BUS_WIDTH{1'b0}}, dec_mem_info_bus}) |
({`DECINFO_WIDTH{op_sys}} & {{`DECINFO_WIDTH-`DECINFO_SYS_BUS_WIDTH{1'b0}}, dec_sys_info_bus});
assign dec_pc_o = inst_addr_i;
// 访rs1
wire access_rs1 = (~inst_lui) &
(~inst_auipc) &
(~inst_jal) &
(~inst_ecall) &
(~inst_ebreak) &
(~inst_csrrwi) &
(~inst_csrrsi) &
(~inst_csrrci) &
(~inst_nop) &
(~inst_fence) &
(~inst_fence_i) &
(~inst_mret);
assign rs1_raddr_o = access_rs1? rs1: 5'h0;
// 访rs2
wire access_rs2 = opcode_0110011 | inst_type_store | inst_type_branch;
assign rs2_raddr_o = access_rs2? rs2: 5'h0;
// 访rd
wire access_rd = inst_lui | inst_auipc | inst_jal | inst_jalr | inst_type_load | opcode_0010011 | opcode_0110011 | op_csr;
assign rd_waddr_o = access_rd? rd: 5'h0;
assign rd_we_o = access_rd;
assign stall_o = 1'b0;
endmodule

90
rtl/core/idu_exu.v Normal file
View File

@ -0,0 +1,90 @@
/*
Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
//
module idu_exu(
input wire clk,
input wire rst_n,
input wire[`STALL_WIDTH-1:0] stall_i, // 线
input wire flush_i, // 线
input wire[31:0] inst_i,
input wire[`DECINFO_WIDTH-1:0] dec_info_bus_i,
input wire[31:0] dec_imm_i,
input wire[31:0] dec_pc_i,
input wire[31:0] rs1_rdata_i,
input wire[31:0] rs2_rdata_i,
input wire[4:0] rd_waddr_i,
input wire rd_we_i,
output wire[31:0] inst_o,
output wire[`DECINFO_WIDTH-1:0] dec_info_bus_o,
output wire[31:0] dec_imm_o,
output wire[31:0] dec_pc_o,
output wire[31:0] rs1_rdata_o,
output wire[31:0] rs2_rdata_o,
output wire[4:0] rd_waddr_o,
output wire rd_we_o
);
wire en = !stall_i[`STALL_EX] | flush_i;
wire[`DECINFO_WIDTH-1:0] i_dec_info_bus = flush_i? {`DECINFO_WIDTH{1'b0}}: dec_info_bus_i;
wire[`DECINFO_WIDTH-1:0] dec_info_bus;
gen_en_dff #(`DECINFO_WIDTH) info_bus_ff(clk, rst_n, en, i_dec_info_bus, dec_info_bus);
assign dec_info_bus_o = dec_info_bus;
wire[31:0] i_dec_imm = flush_i? 32'h0: dec_imm_i;
wire[31:0] dec_imm;
gen_en_dff #(32) imm_ff(clk, rst_n, en, i_dec_imm, dec_imm);
assign dec_imm_o = dec_imm;
wire[31:0] i_dec_pc = flush_i? 32'h0: dec_pc_i;
wire[31:0] dec_pc;
gen_en_dff #(32) pc_ff(clk, rst_n, en, i_dec_pc, dec_pc);
assign dec_pc_o = dec_pc;
wire[31:0] i_rs1_rdata = flush_i? 32'h0: rs1_rdata_i;
wire[31:0] rs1_rdata;
gen_en_dff #(32) rs1_rdata_ff(clk, rst_n, en, i_rs1_rdata, rs1_rdata);
assign rs1_rdata_o = rs1_rdata;
wire[31:0] i_rs2_rdata = flush_i? 32'h0: rs2_rdata_i;
wire[31:0] rs2_rdata;
gen_en_dff #(32) rs2_rdata_ff(clk, rst_n, en, i_rs2_rdata, rs2_rdata);
assign rs2_rdata_o = rs2_rdata;
wire[4:0] i_rd_waddr = flush_i? 5'h0: rd_waddr_i;
wire[4:0] rd_waddr;
gen_en_dff #(5) rd_waddr_ff(clk, rst_n, en, i_rd_waddr, rd_waddr);
assign rd_waddr_o = rd_waddr;
wire i_rd_we = flush_i? 1'b0: rd_we_i;
wire rd_we;
gen_en_dff #(1) rd_we_ff(clk, rst_n, en, i_rd_we, rd_we);
assign rd_we_o = rd_we;
wire[31:0] i_inst = flush_i? 32'h0: inst_i;
wire[31:0] inst;
gen_en_dff #(32) inst_ff(clk, rst_n, en, i_inst, inst);
assign inst_o = inst;
endmodule

125
rtl/core/ifu.v Normal file
View File

@ -0,0 +1,125 @@
/*
Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
//
module ifu(
input wire clk,
input wire rst_n,
input wire flush_i,
input wire[31:0] flush_addr_i, //
input wire[`STALL_WIDTH-1:0] stall_i, // 线
input wire jtag_halt_i,
output wire[31:0] inst_o,
output wire[31:0] pc_o,
output wire inst_valid_o,
output wire[31:0] ibus_addr_o,
input wire[31:0] ibus_data_i,
output wire[31:0] ibus_data_o,
output wire[3:0] ibus_sel_o,
output wire ibus_we_o,
output wire req_valid_o,
input wire req_ready_i,
input wire rsp_valid_i,
output wire rsp_ready_o
);
assign req_valid_o = (~rst_n)? 1'b0:
(flush_i)? 1'b0:
stall_i[`STALL_PC]? 1'b0:
jtag_halt_i? 1'b0:
1'b1;
assign rsp_ready_o = (~rst_n)? 1'b0: 1'b1;
wire ifu_req_hsked = (req_valid_o & req_ready_i);
wire ifu_rsp_hsked = (rsp_valid_i & rsp_ready_o);
// 线
wire stall = stall_i[`STALL_PC] | (~ifu_req_hsked);
reg[31:0] pc;
reg[31:0] pc_prev;
always @ (posedge clk or negedge rst_n) begin
//
if (!rst_n) begin
pc <= `CPU_RESET_ADDR;
pc_prev <= 32'h0;
//
end else if (flush_i) begin
pc <= flush_addr_i;
//
end else if (stall) begin
pc <= pc_prev;
//
end else begin
pc <= pc + 32'h4;
pc_prev <= pc;
end
end
wire[31:0] pc_r;
// PC
wire pc_ena = (~stall);
gen_en_dff #(32) pc_dff(clk, rst_n, pc_ena, pc, pc_r);
reg req_hasked_r;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
req_hasked_r <= 1'b1;
end else begin
req_hasked_r <= ifu_req_hsked;
end
end
wire req_switched = ifu_req_hsked & (~req_hasked_r);
reg rsp_hasked_r;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
rsp_hasked_r <= 1'b1;
end else begin
rsp_hasked_r <= ifu_rsp_hsked;
end
end
wire rsp_switched = ifu_rsp_hsked & (~rsp_hasked_r);
// 线
// 1.访访ifu_req_hskedifu_rsp_hsked01
// 2.访访ifu_req_hsked01ifu_rsp_hsked01
// 2
wire bus_switched = req_switched & rsp_switched;
//
assign ibus_addr_o = pc;
assign pc_o = pc_r;
wire inst_valid = ifu_rsp_hsked & (~flush_i) & (~bus_switched);
assign inst_o = inst_valid? ibus_data_i: `INST_NOP;
assign ibus_sel_o = 4'b1111;
assign ibus_we_o = 1'b0;
assign ibus_data_o = 32'h0;
endmodule

View File

@ -17,36 +17,32 @@
`include "defines.v"
//
module if_id(
module ifu_idu(
input wire clk,
input wire rst,
input wire rst_n,
input wire[`InstBus] inst_i, //
input wire[`InstAddrBus] inst_addr_i, //
input wire[31:0] inst_i, //
input wire[31:0] inst_addr_i, //
input wire[`STALL_WIDTH-1:0] stall_i, // 线
input wire flush_i, // 线
input wire inst_valid_i,
input wire[`Hold_Flag_Bus] hold_flag_i, // 线
input wire[`INT_BUS] int_flag_i, //
output wire[`INT_BUS] int_flag_o,
output wire[`InstBus] inst_o, //
output wire[`InstAddrBus] inst_addr_o //
output wire[31:0] inst_o, //
output wire[31:0] inst_addr_o //
);
wire hold_en = (hold_flag_i >= `Hold_If);
wire en = !stall_i[`STALL_ID] | flush_i;
wire[`InstBus] inst;
gen_pipe_dff #(32) inst_ff(clk, rst, hold_en, `INST_NOP, inst_i, inst);
wire[31:0] i_inst = (flush_i)? `INST_NOP: inst_i;
wire[31:0] inst;
gen_en_dff #(32) inst_ff(clk, rst_n, en, i_inst, inst);
assign inst_o = inst;
wire[`InstAddrBus] inst_addr;
gen_pipe_dff #(32) inst_addr_ff(clk, rst, hold_en, `ZeroWord, inst_addr_i, inst_addr);
wire[31:0] i_inst_addr = flush_i? 32'h0: inst_addr_i;
wire[31:0] inst_addr;
gen_en_dff #(32) inst_addr_ff(clk, rst_n, en, i_inst_addr, inst_addr);
assign inst_addr_o = inst_addr;
wire[`INT_BUS] int_flag;
gen_pipe_dff #(8) int_ff(clk, rst, hold_en, `INT_NONE, int_flag_i, int_flag);
assign int_flag_o = int_flag;
endmodule

65
rtl/core/pipe_ctrl.v Normal file
View File

@ -0,0 +1,65 @@
/*
Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
// 线
// 线
module pipe_ctrl(
input wire clk,
input wire rst_n,
input wire stall_from_id_i,
input wire stall_from_ex_i,
input wire stall_from_jtag_i,
input wire stall_from_clint_i,
input wire jump_assert_i,
input wire[31:0] jump_addr_i,
output wire flush_o,
output wire[`STALL_WIDTH-1:0] stall_o,
output wire[31:0] flush_addr_o
);
assign flush_addr_o = jump_addr_i;
assign flush_o = jump_assert_i | stall_from_clint_i;
reg[`STALL_WIDTH-1:0] stall;
always @ (*) begin
if (stall_from_ex_i | stall_from_clint_i) begin
stall[`STALL_EX] = 1'b1;
stall[`STALL_ID] = 1'b1;
stall[`STALL_IF] = 1'b1;
stall[`STALL_PC] = 1'b1;
end else if (stall_from_id_i) begin
stall[`STALL_EX] = 1'b0;
stall[`STALL_ID] = 1'b0;
stall[`STALL_IF] = 1'b1;
stall[`STALL_PC] = 1'b1;
end else begin
stall[`STALL_EX] = 1'b0;
stall[`STALL_ID] = 1'b0;
stall[`STALL_IF] = 1'b0;
stall[`STALL_PC] = 1'b0;
end
end
assign stall_o = stall;
endmodule

View File

@ -1,99 +0,0 @@
/*
Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
//
module regs(
input wire clk,
input wire rst,
// from ex
input wire we_i, //
input wire[`RegAddrBus] waddr_i, //
input wire[`RegBus] wdata_i, //
// from jtag
input wire jtag_we_i, //
input wire[`RegAddrBus] jtag_addr_i, //
input wire[`RegBus] jtag_data_i, //
// from id
input wire[`RegAddrBus] raddr1_i, // 1
// to id
output reg[`RegBus] rdata1_o, // 1
// from id
input wire[`RegAddrBus] raddr2_i, // 2
// to id
output reg[`RegBus] rdata2_o, // 2
// to jtag
output reg[`RegBus] jtag_data_o //
);
reg[`RegBus] regs[0:`RegNum - 1];
//
always @ (posedge clk) begin
if (rst == `RstDisable) begin
// ex
if ((we_i == `WriteEnable) && (waddr_i != `ZeroReg)) begin
regs[waddr_i] <= wdata_i;
end else if ((jtag_we_i == `WriteEnable) && (jtag_addr_i != `ZeroReg)) begin
regs[jtag_addr_i] <= jtag_data_i;
end
end
end
// 1
always @ (*) begin
if (raddr1_i == `ZeroReg) begin
rdata1_o = `ZeroWord;
//
end else if (raddr1_i == waddr_i && we_i == `WriteEnable) begin
rdata1_o = wdata_i;
end else begin
rdata1_o = regs[raddr1_i];
end
end
// 2
always @ (*) begin
if (raddr2_i == `ZeroReg) begin
rdata2_o = `ZeroWord;
//
end else if (raddr2_i == waddr_i && we_i == `WriteEnable) begin
rdata2_o = wdata_i;
end else begin
rdata2_o = regs[raddr2_i];
end
end
// jtag
always @ (*) begin
if (jtag_addr_i == `ZeroReg) begin
jtag_data_o = `ZeroWord;
end else begin
jtag_data_o = regs[jtag_addr_i];
end
end
endmodule

View File

@ -1,340 +0,0 @@
/*
Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
// RIB线
module rib(
input wire clk,
input wire rst,
// master 0 interface
input wire[`MemAddrBus] m0_addr_i, // 0
input wire[`MemBus] m0_data_i, // 0
output reg[`MemBus] m0_data_o, // 0
input wire m0_req_i, // 0访
input wire m0_we_i, // 0
// master 1 interface
input wire[`MemAddrBus] m1_addr_i, // 1
input wire[`MemBus] m1_data_i, // 1
output reg[`MemBus] m1_data_o, // 1
input wire m1_req_i, // 1访
input wire m1_we_i, // 1
// master 2 interface
input wire[`MemAddrBus] m2_addr_i, // 2
input wire[`MemBus] m2_data_i, // 2
output reg[`MemBus] m2_data_o, // 2
input wire m2_req_i, // 2访
input wire m2_we_i, // 2
// master 3 interface
input wire[`MemAddrBus] m3_addr_i, // 3
input wire[`MemBus] m3_data_i, // 3
output reg[`MemBus] m3_data_o, // 3
input wire m3_req_i, // 3访
input wire m3_we_i, // 3
// slave 0 interface
output reg[`MemAddrBus] s0_addr_o, // 0
output reg[`MemBus] s0_data_o, // 0
input wire[`MemBus] s0_data_i, // 0
output reg s0_we_o, // 0
// slave 1 interface
output reg[`MemAddrBus] s1_addr_o, // 1
output reg[`MemBus] s1_data_o, // 1
input wire[`MemBus] s1_data_i, // 1
output reg s1_we_o, // 1
// slave 2 interface
output reg[`MemAddrBus] s2_addr_o, // 2
output reg[`MemBus] s2_data_o, // 2
input wire[`MemBus] s2_data_i, // 2
output reg s2_we_o, // 2
// slave 3 interface
output reg[`MemAddrBus] s3_addr_o, // 3
output reg[`MemBus] s3_data_o, // 3
input wire[`MemBus] s3_data_i, // 3
output reg s3_we_o, // 3
// slave 4 interface
output reg[`MemAddrBus] s4_addr_o, // 4
output reg[`MemBus] s4_data_o, // 4
input wire[`MemBus] s4_data_i, // 4
output reg s4_we_o, // 4
// slave 5 interface
output reg[`MemAddrBus] s5_addr_o, // 5
output reg[`MemBus] s5_data_o, // 5
input wire[`MemBus] s5_data_i, // 5
output reg s5_we_o, // 5
output reg hold_flag_o // 线
);
// 访4访
// 16
parameter [3:0]slave_0 = 4'b0000;
parameter [3:0]slave_1 = 4'b0001;
parameter [3:0]slave_2 = 4'b0010;
parameter [3:0]slave_3 = 4'b0011;
parameter [3:0]slave_4 = 4'b0100;
parameter [3:0]slave_5 = 4'b0101;
parameter [1:0]grant0 = 2'h0;
parameter [1:0]grant1 = 2'h1;
parameter [1:0]grant2 = 2'h2;
parameter [1:0]grant3 = 2'h3;
wire[3:0] req;
reg[1:0] grant;
//
assign req = {m3_req_i, m2_req_i, m1_req_i, m0_req_i};
//
//
// 3021
always @ (*) begin
if (req[3]) begin
grant = grant3;
hold_flag_o = `HoldEnable;
end else if (req[0]) begin
grant = grant0;
hold_flag_o = `HoldEnable;
end else if (req[2]) begin
grant = grant2;
hold_flag_o = `HoldEnable;
end else begin
grant = grant1;
hold_flag_o = `HoldDisable;
end
end
// (访)
always @ (*) begin
m0_data_o = `ZeroWord;
m1_data_o = `INST_NOP;
m2_data_o = `ZeroWord;
m3_data_o = `ZeroWord;
s0_addr_o = `ZeroWord;
s1_addr_o = `ZeroWord;
s2_addr_o = `ZeroWord;
s3_addr_o = `ZeroWord;
s4_addr_o = `ZeroWord;
s5_addr_o = `ZeroWord;
s0_data_o = `ZeroWord;
s1_data_o = `ZeroWord;
s2_data_o = `ZeroWord;
s3_data_o = `ZeroWord;
s4_data_o = `ZeroWord;
s5_data_o = `ZeroWord;
s0_we_o = `WriteDisable;
s1_we_o = `WriteDisable;
s2_we_o = `WriteDisable;
s3_we_o = `WriteDisable;
s4_we_o = `WriteDisable;
s5_we_o = `WriteDisable;
case (grant)
grant0: begin
case (m0_addr_i[31:28])
slave_0: begin
s0_we_o = m0_we_i;
s0_addr_o = {{4'h0}, {m0_addr_i[27:0]}};
s0_data_o = m0_data_i;
m0_data_o = s0_data_i;
end
slave_1: begin
s1_we_o = m0_we_i;
s1_addr_o = {{4'h0}, {m0_addr_i[27:0]}};
s1_data_o = m0_data_i;
m0_data_o = s1_data_i;
end
slave_2: begin
s2_we_o = m0_we_i;
s2_addr_o = {{4'h0}, {m0_addr_i[27:0]}};
s2_data_o = m0_data_i;
m0_data_o = s2_data_i;
end
slave_3: begin
s3_we_o = m0_we_i;
s3_addr_o = {{4'h0}, {m0_addr_i[27:0]}};
s3_data_o = m0_data_i;
m0_data_o = s3_data_i;
end
slave_4: begin
s4_we_o = m0_we_i;
s4_addr_o = {{4'h0}, {m0_addr_i[27:0]}};
s4_data_o = m0_data_i;
m0_data_o = s4_data_i;
end
slave_5: begin
s5_we_o = m0_we_i;
s5_addr_o = {{4'h0}, {m0_addr_i[27:0]}};
s5_data_o = m0_data_i;
m0_data_o = s5_data_i;
end
default: begin
end
endcase
end
grant1: begin
case (m1_addr_i[31:28])
slave_0: begin
s0_we_o = m1_we_i;
s0_addr_o = {{4'h0}, {m1_addr_i[27:0]}};
s0_data_o = m1_data_i;
m1_data_o = s0_data_i;
end
slave_1: begin
s1_we_o = m1_we_i;
s1_addr_o = {{4'h0}, {m1_addr_i[27:0]}};
s1_data_o = m1_data_i;
m1_data_o = s1_data_i;
end
slave_2: begin
s2_we_o = m1_we_i;
s2_addr_o = {{4'h0}, {m1_addr_i[27:0]}};
s2_data_o = m1_data_i;
m1_data_o = s2_data_i;
end
slave_3: begin
s3_we_o = m1_we_i;
s3_addr_o = {{4'h0}, {m1_addr_i[27:0]}};
s3_data_o = m1_data_i;
m1_data_o = s3_data_i;
end
slave_4: begin
s4_we_o = m1_we_i;
s4_addr_o = {{4'h0}, {m1_addr_i[27:0]}};
s4_data_o = m1_data_i;
m1_data_o = s4_data_i;
end
slave_5: begin
s5_we_o = m1_we_i;
s5_addr_o = {{4'h0}, {m1_addr_i[27:0]}};
s5_data_o = m1_data_i;
m1_data_o = s5_data_i;
end
default: begin
end
endcase
end
grant2: begin
case (m2_addr_i[31:28])
slave_0: begin
s0_we_o = m2_we_i;
s0_addr_o = {{4'h0}, {m2_addr_i[27:0]}};
s0_data_o = m2_data_i;
m2_data_o = s0_data_i;
end
slave_1: begin
s1_we_o = m2_we_i;
s1_addr_o = {{4'h0}, {m2_addr_i[27:0]}};
s1_data_o = m2_data_i;
m2_data_o = s1_data_i;
end
slave_2: begin
s2_we_o = m2_we_i;
s2_addr_o = {{4'h0}, {m2_addr_i[27:0]}};
s2_data_o = m2_data_i;
m2_data_o = s2_data_i;
end
slave_3: begin
s3_we_o = m2_we_i;
s3_addr_o = {{4'h0}, {m2_addr_i[27:0]}};
s3_data_o = m2_data_i;
m2_data_o = s3_data_i;
end
slave_4: begin
s4_we_o = m2_we_i;
s4_addr_o = {{4'h0}, {m2_addr_i[27:0]}};
s4_data_o = m2_data_i;
m2_data_o = s4_data_i;
end
slave_5: begin
s5_we_o = m2_we_i;
s5_addr_o = {{4'h0}, {m2_addr_i[27:0]}};
s5_data_o = m2_data_i;
m2_data_o = s5_data_i;
end
default: begin
end
endcase
end
grant3: begin
case (m3_addr_i[31:28])
slave_0: begin
s0_we_o = m3_we_i;
s0_addr_o = {{4'h0}, {m3_addr_i[27:0]}};
s0_data_o = m3_data_i;
m3_data_o = s0_data_i;
end
slave_1: begin
s1_we_o = m3_we_i;
s1_addr_o = {{4'h0}, {m3_addr_i[27:0]}};
s1_data_o = m3_data_i;
m3_data_o = s1_data_i;
end
slave_2: begin
s2_we_o = m3_we_i;
s2_addr_o = {{4'h0}, {m3_addr_i[27:0]}};
s2_data_o = m3_data_i;
m3_data_o = s2_data_i;
end
slave_3: begin
s3_we_o = m3_we_i;
s3_addr_o = {{4'h0}, {m3_addr_i[27:0]}};
s3_data_o = m3_data_i;
m3_data_o = s3_data_i;
end
slave_4: begin
s4_we_o = m3_we_i;
s4_addr_o = {{4'h0}, {m3_addr_i[27:0]}};
s4_data_o = m3_data_i;
m3_data_o = s4_data_i;
end
slave_5: begin
s5_we_o = m3_we_i;
s5_addr_o = {{4'h0}, {m3_addr_i[27:0]}};
s5_data_o = m3_data_i;
m3_data_o = s5_data_i;
end
default: begin
end
endcase
end
default: begin
end
endcase
end
endmodule

View File

@ -1,5 +1,5 @@
/*
Copyright 2019 Blue Liang, liangkangnan@163.com
Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -16,36 +16,44 @@
`include "defines.v"
// PC
module pc_reg(
//
module rst_ctrl(
input wire clk,
input wire rst,
input wire jump_flag_i, //
input wire[`InstAddrBus] jump_addr_i, //
input wire[`Hold_Flag_Bus] hold_flag_i, // 线
input wire jtag_reset_flag_i, //
input wire rst_ext_i,
input wire rst_jtag_i,
output reg[`InstAddrBus] pc_o // PC
output wire core_rst_n_o,
output wire jtag_rst_n_o
);
wire ext_rst_r;
gen_ticks_sync #(
.DP(2),
.DW(1)
) ext_rst_sync(
.rst_n(rst_ext_i),
.clk(clk),
.din(1'b1),
.dout(ext_rst_r)
);
reg[`JTAG_RESET_FF_LEVELS-1:0] jtag_rst_r;
always @ (posedge clk) begin
//
if (rst == `RstEnable || jtag_reset_flag_i == 1'b1) begin
pc_o <= `CpuResetAddr;
//
end else if (jump_flag_i == `JumpEnable) begin
pc_o <= jump_addr_i;
//
end else if (hold_flag_i >= `Hold_Pc) begin
pc_o <= pc_o;
// 4
if (!rst_ext_i) begin
jtag_rst_r[`JTAG_RESET_FF_LEVELS-1:0] <= {`JTAG_RESET_FF_LEVELS{1'b1}};
end if (rst_jtag_i) begin
jtag_rst_r[`JTAG_RESET_FF_LEVELS-1:0] <= {`JTAG_RESET_FF_LEVELS{1'b0}};
end else begin
pc_o <= pc_o + 4'h4;
jtag_rst_r[`JTAG_RESET_FF_LEVELS-1:0] <= {jtag_rst_r[`JTAG_RESET_FF_LEVELS-2:0], 1'b1};
end
end
assign core_rst_n_o = ext_rst_r & jtag_rst_r[`JTAG_RESET_FF_LEVELS-1];
assign jtag_rst_n_o = ext_rst_r;
endmodule

View File

@ -1,369 +0,0 @@
/*
Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
// tinyriscv
module tinyriscv(
input wire clk,
input wire rst,
output wire[`MemAddrBus] rib_ex_addr_o, //
input wire[`MemBus] rib_ex_data_i, //
output wire[`MemBus] rib_ex_data_o, //
output wire rib_ex_req_o, // 访
output wire rib_ex_we_o, //
output wire[`MemAddrBus] rib_pc_addr_o, //
input wire[`MemBus] rib_pc_data_i, //
input wire[`RegAddrBus] jtag_reg_addr_i, // jtag
input wire[`RegBus] jtag_reg_data_i, // jtag
input wire jtag_reg_we_i, // jtag
output wire[`RegBus] jtag_reg_data_o, // jtag
input wire rib_hold_flag_i, // 线
input wire jtag_halt_flag_i, // jtag
input wire jtag_reset_flag_i, // jtagPC
input wire[`INT_BUS] int_i //
);
// pc_reg
wire[`InstAddrBus] pc_pc_o;
// if_id
wire[`InstBus] if_inst_o;
wire[`InstAddrBus] if_inst_addr_o;
wire[`INT_BUS] if_int_flag_o;
// id
wire[`RegAddrBus] id_reg1_raddr_o;
wire[`RegAddrBus] id_reg2_raddr_o;
wire[`InstBus] id_inst_o;
wire[`InstAddrBus] id_inst_addr_o;
wire[`RegBus] id_reg1_rdata_o;
wire[`RegBus] id_reg2_rdata_o;
wire id_reg_we_o;
wire[`RegAddrBus] id_reg_waddr_o;
wire[`MemAddrBus] id_csr_raddr_o;
wire id_csr_we_o;
wire[`RegBus] id_csr_rdata_o;
wire[`MemAddrBus] id_csr_waddr_o;
wire[`MemAddrBus] id_op1_o;
wire[`MemAddrBus] id_op2_o;
wire[`MemAddrBus] id_op1_jump_o;
wire[`MemAddrBus] id_op2_jump_o;
// id_ex
wire[`InstBus] ie_inst_o;
wire[`InstAddrBus] ie_inst_addr_o;
wire ie_reg_we_o;
wire[`RegAddrBus] ie_reg_waddr_o;
wire[`RegBus] ie_reg1_rdata_o;
wire[`RegBus] ie_reg2_rdata_o;
wire ie_csr_we_o;
wire[`MemAddrBus] ie_csr_waddr_o;
wire[`RegBus] ie_csr_rdata_o;
wire[`MemAddrBus] ie_op1_o;
wire[`MemAddrBus] ie_op2_o;
wire[`MemAddrBus] ie_op1_jump_o;
wire[`MemAddrBus] ie_op2_jump_o;
// ex
wire[`MemBus] ex_mem_wdata_o;
wire[`MemAddrBus] ex_mem_raddr_o;
wire[`MemAddrBus] ex_mem_waddr_o;
wire ex_mem_we_o;
wire ex_mem_req_o;
wire[`RegBus] ex_reg_wdata_o;
wire ex_reg_we_o;
wire[`RegAddrBus] ex_reg_waddr_o;
wire ex_hold_flag_o;
wire ex_jump_flag_o;
wire[`InstAddrBus] ex_jump_addr_o;
wire ex_div_start_o;
wire[`RegBus] ex_div_dividend_o;
wire[`RegBus] ex_div_divisor_o;
wire[2:0] ex_div_op_o;
wire[`RegAddrBus] ex_div_reg_waddr_o;
wire[`RegBus] ex_csr_wdata_o;
wire ex_csr_we_o;
wire[`MemAddrBus] ex_csr_waddr_o;
// regs
wire[`RegBus] regs_rdata1_o;
wire[`RegBus] regs_rdata2_o;
// csr_reg
wire[`RegBus] csr_data_o;
wire[`RegBus] csr_clint_data_o;
wire csr_global_int_en_o;
wire[`RegBus] csr_clint_csr_mtvec;
wire[`RegBus] csr_clint_csr_mepc;
wire[`RegBus] csr_clint_csr_mstatus;
// ctrl
wire[`Hold_Flag_Bus] ctrl_hold_flag_o;
wire ctrl_jump_flag_o;
wire[`InstAddrBus] ctrl_jump_addr_o;
// div
wire[`RegBus] div_result_o;
wire div_ready_o;
wire div_busy_o;
wire[`RegAddrBus] div_reg_waddr_o;
// clint
wire clint_we_o;
wire[`MemAddrBus] clint_waddr_o;
wire[`MemAddrBus] clint_raddr_o;
wire[`RegBus] clint_data_o;
wire[`InstAddrBus] clint_int_addr_o;
wire clint_int_assert_o;
wire clint_hold_flag_o;
assign rib_ex_addr_o = (ex_mem_we_o == `WriteEnable)? ex_mem_waddr_o: ex_mem_raddr_o;
assign rib_ex_data_o = ex_mem_wdata_o;
assign rib_ex_req_o = ex_mem_req_o;
assign rib_ex_we_o = ex_mem_we_o;
assign rib_pc_addr_o = pc_pc_o;
// pc_reg
pc_reg u_pc_reg(
.clk(clk),
.rst(rst),
.jtag_reset_flag_i(jtag_reset_flag_i),
.pc_o(pc_pc_o),
.hold_flag_i(ctrl_hold_flag_o),
.jump_flag_i(ctrl_jump_flag_o),
.jump_addr_i(ctrl_jump_addr_o)
);
// ctrl
ctrl u_ctrl(
.rst(rst),
.jump_flag_i(ex_jump_flag_o),
.jump_addr_i(ex_jump_addr_o),
.hold_flag_ex_i(ex_hold_flag_o),
.hold_flag_rib_i(rib_hold_flag_i),
.hold_flag_o(ctrl_hold_flag_o),
.hold_flag_clint_i(clint_hold_flag_o),
.jump_flag_o(ctrl_jump_flag_o),
.jump_addr_o(ctrl_jump_addr_o),
.jtag_halt_flag_i(jtag_halt_flag_i)
);
// regs
regs u_regs(
.clk(clk),
.rst(rst),
.we_i(ex_reg_we_o),
.waddr_i(ex_reg_waddr_o),
.wdata_i(ex_reg_wdata_o),
.raddr1_i(id_reg1_raddr_o),
.rdata1_o(regs_rdata1_o),
.raddr2_i(id_reg2_raddr_o),
.rdata2_o(regs_rdata2_o),
.jtag_we_i(jtag_reg_we_i),
.jtag_addr_i(jtag_reg_addr_i),
.jtag_data_i(jtag_reg_data_i),
.jtag_data_o(jtag_reg_data_o)
);
// csr_reg
csr_reg u_csr_reg(
.clk(clk),
.rst(rst),
.we_i(ex_csr_we_o),
.raddr_i(id_csr_raddr_o),
.waddr_i(ex_csr_waddr_o),
.data_i(ex_csr_wdata_o),
.data_o(csr_data_o),
.global_int_en_o(csr_global_int_en_o),
.clint_we_i(clint_we_o),
.clint_raddr_i(clint_raddr_o),
.clint_waddr_i(clint_waddr_o),
.clint_data_i(clint_data_o),
.clint_data_o(csr_clint_data_o),
.clint_csr_mtvec(csr_clint_csr_mtvec),
.clint_csr_mepc(csr_clint_csr_mepc),
.clint_csr_mstatus(csr_clint_csr_mstatus)
);
// if_id
if_id u_if_id(
.clk(clk),
.rst(rst),
.inst_i(rib_pc_data_i),
.inst_addr_i(pc_pc_o),
.int_flag_i(int_i),
.int_flag_o(if_int_flag_o),
.hold_flag_i(ctrl_hold_flag_o),
.inst_o(if_inst_o),
.inst_addr_o(if_inst_addr_o)
);
// id
id u_id(
.rst(rst),
.inst_i(if_inst_o),
.inst_addr_i(if_inst_addr_o),
.reg1_rdata_i(regs_rdata1_o),
.reg2_rdata_i(regs_rdata2_o),
.ex_jump_flag_i(ex_jump_flag_o),
.reg1_raddr_o(id_reg1_raddr_o),
.reg2_raddr_o(id_reg2_raddr_o),
.inst_o(id_inst_o),
.inst_addr_o(id_inst_addr_o),
.reg1_rdata_o(id_reg1_rdata_o),
.reg2_rdata_o(id_reg2_rdata_o),
.reg_we_o(id_reg_we_o),
.reg_waddr_o(id_reg_waddr_o),
.op1_o(id_op1_o),
.op2_o(id_op2_o),
.op1_jump_o(id_op1_jump_o),
.op2_jump_o(id_op2_jump_o),
.csr_rdata_i(csr_data_o),
.csr_raddr_o(id_csr_raddr_o),
.csr_we_o(id_csr_we_o),
.csr_rdata_o(id_csr_rdata_o),
.csr_waddr_o(id_csr_waddr_o)
);
// id_ex
id_ex u_id_ex(
.clk(clk),
.rst(rst),
.inst_i(id_inst_o),
.inst_addr_i(id_inst_addr_o),
.reg_we_i(id_reg_we_o),
.reg_waddr_i(id_reg_waddr_o),
.reg1_rdata_i(id_reg1_rdata_o),
.reg2_rdata_i(id_reg2_rdata_o),
.hold_flag_i(ctrl_hold_flag_o),
.inst_o(ie_inst_o),
.inst_addr_o(ie_inst_addr_o),
.reg_we_o(ie_reg_we_o),
.reg_waddr_o(ie_reg_waddr_o),
.reg1_rdata_o(ie_reg1_rdata_o),
.reg2_rdata_o(ie_reg2_rdata_o),
.op1_i(id_op1_o),
.op2_i(id_op2_o),
.op1_jump_i(id_op1_jump_o),
.op2_jump_i(id_op2_jump_o),
.op1_o(ie_op1_o),
.op2_o(ie_op2_o),
.op1_jump_o(ie_op1_jump_o),
.op2_jump_o(ie_op2_jump_o),
.csr_we_i(id_csr_we_o),
.csr_waddr_i(id_csr_waddr_o),
.csr_rdata_i(id_csr_rdata_o),
.csr_we_o(ie_csr_we_o),
.csr_waddr_o(ie_csr_waddr_o),
.csr_rdata_o(ie_csr_rdata_o)
);
// ex
ex u_ex(
.rst(rst),
.inst_i(ie_inst_o),
.inst_addr_i(ie_inst_addr_o),
.reg_we_i(ie_reg_we_o),
.reg_waddr_i(ie_reg_waddr_o),
.reg1_rdata_i(ie_reg1_rdata_o),
.reg2_rdata_i(ie_reg2_rdata_o),
.op1_i(ie_op1_o),
.op2_i(ie_op2_o),
.op1_jump_i(ie_op1_jump_o),
.op2_jump_i(ie_op2_jump_o),
.mem_rdata_i(rib_ex_data_i),
.mem_wdata_o(ex_mem_wdata_o),
.mem_raddr_o(ex_mem_raddr_o),
.mem_waddr_o(ex_mem_waddr_o),
.mem_we_o(ex_mem_we_o),
.mem_req_o(ex_mem_req_o),
.reg_wdata_o(ex_reg_wdata_o),
.reg_we_o(ex_reg_we_o),
.reg_waddr_o(ex_reg_waddr_o),
.hold_flag_o(ex_hold_flag_o),
.jump_flag_o(ex_jump_flag_o),
.jump_addr_o(ex_jump_addr_o),
.int_assert_i(clint_int_assert_o),
.int_addr_i(clint_int_addr_o),
.div_ready_i(div_ready_o),
.div_result_i(div_result_o),
.div_busy_i(div_busy_o),
.div_reg_waddr_i(div_reg_waddr_o),
.div_start_o(ex_div_start_o),
.div_dividend_o(ex_div_dividend_o),
.div_divisor_o(ex_div_divisor_o),
.div_op_o(ex_div_op_o),
.div_reg_waddr_o(ex_div_reg_waddr_o),
.csr_we_i(ie_csr_we_o),
.csr_waddr_i(ie_csr_waddr_o),
.csr_rdata_i(ie_csr_rdata_o),
.csr_wdata_o(ex_csr_wdata_o),
.csr_we_o(ex_csr_we_o),
.csr_waddr_o(ex_csr_waddr_o)
);
// div
div u_div(
.clk(clk),
.rst(rst),
.dividend_i(ex_div_dividend_o),
.divisor_i(ex_div_divisor_o),
.start_i(ex_div_start_o),
.op_i(ex_div_op_o),
.reg_waddr_i(ex_div_reg_waddr_o),
.result_o(div_result_o),
.ready_o(div_ready_o),
.busy_o(div_busy_o),
.reg_waddr_o(div_reg_waddr_o)
);
// clint
clint u_clint(
.clk(clk),
.rst(rst),
.int_flag_i(if_int_flag_o),
.inst_i(id_inst_o),
.inst_addr_i(id_inst_addr_o),
.jump_flag_i(ex_jump_flag_o),
.jump_addr_i(ex_jump_addr_o),
.hold_flag_i(ctrl_hold_flag_o),
.div_started_i(ex_div_start_o),
.data_i(csr_clint_data_o),
.csr_mtvec(csr_clint_csr_mtvec),
.csr_mepc(csr_clint_csr_mepc),
.csr_mstatus(csr_clint_csr_mstatus),
.we_o(clint_we_o),
.waddr_o(clint_waddr_o),
.raddr_o(clint_raddr_o),
.data_o(clint_data_o),
.hold_flag_o(clint_hold_flag_o),
.global_int_en_i(csr_global_int_en_o),
.int_addr_o(clint_int_addr_o),
.int_assert_o(clint_int_assert_o)
);
endmodule

318
rtl/core/tinyriscv_core.v Normal file
View File

@ -0,0 +1,318 @@
/*
Copyright 2019 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "defines.v"
// tinyriscv
module tinyriscv_core(
input wire clk,
input wire rst_n,
output wire[31:0] dbus_addr_o,
input wire[31:0] dbus_data_i,
output wire[31:0] dbus_data_o,
output wire[3:0] dbus_sel_o,
output wire dbus_we_o,
output wire dbus_req_valid_o,
input wire dbus_req_ready_i,
input wire dbus_rsp_valid_i,
output wire dbus_rsp_ready_o,
output wire[31:0] ibus_addr_o, //
input wire[31:0] ibus_data_i, //
output wire[31:0] ibus_data_o,
output wire[3:0] ibus_sel_o,
output wire ibus_we_o,
output wire ibus_req_valid_o,
input wire ibus_req_ready_i,
input wire ibus_rsp_valid_i,
output wire ibus_rsp_ready_o,
input wire jtag_halt_i,
input wire[`INT_WIDTH-1:0] int_i //
);
// ifu
wire[31:0] ifetch_inst_o;
wire[31:0] ifetch_pc_o;
wire ifetch_inst_valid_o;
// ifu_idu
wire[31:0] if_inst_o;
wire[31:0] if_inst_addr_o;
wire[`INT_WIDTH-1:0] if_int_flag_o;
// idu
wire[31:0] id_inst_o;
wire[31:0] id_inst_addr_o;
wire[`DECINFO_WIDTH-1:0] id_dec_info_bus_o;
wire[31:0] id_dec_imm_o;
wire[31:0] id_dec_pc_o;
wire[4:0] id_rs1_raddr_o;
wire[4:0] id_rs2_raddr_o;
wire[4:0] id_rd_waddr_o;
wire id_rd_we_o;
wire id_stall_o;
wire[31:0] id_rs1_rdata_o;
wire[31:0] id_rs2_rdata_o;
// idu_exu
wire[31:0] ie_inst_o;
wire[31:0] ie_inst_addr_o;
wire[`DECINFO_WIDTH-1:0] ie_dec_info_bus_o;
wire[31:0] ie_dec_imm_o;
wire[31:0] ie_dec_pc_o;
wire[31:0] ie_rs1_rdata_o;
wire[31:0] ie_rs2_rdata_o;
wire[4:0] ie_rd_waddr_o;
wire ie_rd_we_o;
// exu
wire[31:0] ex_mem_wdata_o;
wire[31:0] ex_mem_addr_o;
wire ex_mem_we_o;
wire[3:0] ex_mem_sel_o;
wire ex_mem_req_valid_o;
wire ex_mem_rsp_ready_o;
wire ex_mem_access_misaligned_o;
wire[31:0] ex_reg_wdata_o;
wire ex_reg_we_o;
wire[4:0] ex_reg_waddr_o;
wire ex_hold_flag_o;
wire ex_jump_flag_o;
wire[31:0] ex_jump_addr_o;
wire[31:0] ex_csr_wdata_o;
wire ex_csr_we_o;
wire[31:0] ex_csr_waddr_o;
wire[31:0] ex_csr_raddr_o;
wire ex_inst_ecall_o;
wire ex_inst_ebreak_o;
wire ex_inst_mret_o;
// gpr_reg
wire[31:0] regs_rdata1_o;
wire[31:0] regs_rdata2_o;
// csr_reg
wire[31:0] csr_ex_data_o;
wire[31:0] csr_clint_data_o;
wire[31:0] csr_mtvec_o;
wire[31:0] csr_mepc_o;
wire[31:0] csr_mstatus_o;
// pipe_ctrl
wire[31:0] ctrl_flush_addr_o;
wire ctrl_flush_o;
wire[`STALL_WIDTH-1:0] ctrl_stall_o;
// clint
wire clint_csr_we_o;
wire[31:0] clint_csr_waddr_o;
wire[31:0] clint_csr_wdata_o;
wire clint_stall_flag_o;
wire[31:0] clint_int_addr_o;
wire clint_int_assert_o;
assign dbus_addr_o = ex_mem_addr_o;
assign dbus_data_o = ex_mem_wdata_o;
assign dbus_we_o = ex_mem_we_o;
assign dbus_sel_o = ex_mem_sel_o;
assign dbus_req_valid_o = ex_mem_req_valid_o;
assign dbus_rsp_ready_o = ex_mem_rsp_ready_o;
ifu u_ifu(
.clk(clk),
.rst_n(rst_n),
.flush_addr_i(ctrl_flush_addr_o),
.stall_i(ctrl_stall_o),
.flush_i(ctrl_flush_o),
.jtag_halt_i(jtag_halt_i),
.inst_o(ifetch_inst_o),
.pc_o(ifetch_pc_o),
.inst_valid_o(ifetch_inst_valid_o),
.ibus_addr_o(ibus_addr_o),
.ibus_data_i(ibus_data_i),
.ibus_data_o(ibus_data_o),
.ibus_sel_o(ibus_sel_o),
.ibus_we_o(ibus_we_o),
.req_valid_o(ibus_req_valid_o),
.req_ready_i(ibus_req_ready_i),
.rsp_valid_i(ibus_rsp_valid_i),
.rsp_ready_o(ibus_rsp_ready_o)
);
pipe_ctrl u_pipe_ctrl(
.clk(clk),
.rst_n(rst_n),
.stall_from_id_i(id_stall_o),
.stall_from_ex_i(ex_hold_flag_o),
.stall_from_jtag_i(1'b0),
.stall_from_clint_i(clint_stall_flag_o),
.jump_assert_i(ex_jump_flag_o),
.jump_addr_i(ex_jump_addr_o),
.flush_o(ctrl_flush_o),
.stall_o(ctrl_stall_o),
.flush_addr_o(ctrl_flush_addr_o)
);
gpr_reg u_gpr_reg(
.clk(clk),
.rst_n(rst_n),
.we_i(ex_reg_we_o),
.waddr_i(ex_reg_waddr_o),
.wdata_i(ex_reg_wdata_o),
.raddr1_i(id_rs1_raddr_o),
.rdata1_o(regs_rdata1_o),
.raddr2_i(id_rs2_raddr_o),
.rdata2_o(regs_rdata2_o)
);
csr_reg u_csr_reg(
.clk(clk),
.rst_n(rst_n),
.exu_we_i(ex_csr_we_o),
.exu_raddr_i(ex_csr_raddr_o),
.exu_waddr_i(ex_csr_waddr_o),
.exu_wdata_i(ex_csr_wdata_o),
.exu_rdata_o(csr_ex_data_o),
.clint_we_i(clint_csr_we_o),
.clint_waddr_i(clint_csr_waddr_o),
.clint_wdata_i(clint_csr_wdata_o),
.mtvec_o(csr_mtvec_o),
.mepc_o(csr_mepc_o),
.mstatus_o(csr_mstatus_o)
);
ifu_idu u_ifu_idu(
.clk(clk),
.rst_n(rst_n),
.inst_i(ifetch_inst_o),
.inst_addr_i(ifetch_pc_o),
.stall_i(ctrl_stall_o),
.flush_i(ctrl_flush_o),
.inst_valid_i(ifetch_inst_valid_o),
.inst_o(if_inst_o),
.inst_addr_o(if_inst_addr_o)
);
idu u_idu(
.clk(clk),
.rst_n(rst_n),
.inst_i(if_inst_o),
.rs1_rdata_i(regs_rdata1_o),
.rs2_rdata_i(regs_rdata2_o),
.inst_o(id_inst_o),
.inst_addr_i(if_inst_addr_o),
.rs1_rdata_o(id_rs1_rdata_o),
.rs2_rdata_o(id_rs2_rdata_o),
.stall_o(id_stall_o),
.dec_info_bus_o(id_dec_info_bus_o),
.dec_imm_o(id_dec_imm_o),
.dec_pc_o(id_dec_pc_o),
.rs1_raddr_o(id_rs1_raddr_o),
.rs2_raddr_o(id_rs2_raddr_o),
.rd_waddr_o(id_rd_waddr_o),
.rd_we_o(id_rd_we_o)
);
idu_exu u_idu_exu(
.clk(clk),
.rst_n(rst_n),
.inst_i(id_inst_o),
.stall_i(ctrl_stall_o),
.flush_i(ctrl_flush_o),
.dec_info_bus_i(id_dec_info_bus_o),
.dec_imm_i(id_dec_imm_o),
.dec_pc_i(id_dec_pc_o),
.rs1_rdata_i(id_rs1_rdata_o),
.rs2_rdata_i(id_rs2_rdata_o),
.rd_waddr_i(id_rd_waddr_o),
.rd_we_i(id_rd_we_o),
.inst_o(ie_inst_o),
.dec_info_bus_o(ie_dec_info_bus_o),
.dec_imm_o(ie_dec_imm_o),
.dec_pc_o(ie_dec_pc_o),
.rs1_rdata_o(ie_rs1_rdata_o),
.rs2_rdata_o(ie_rs2_rdata_o),
.rd_waddr_o(ie_rd_waddr_o),
.rd_we_o(ie_rd_we_o)
);
exu u_exu(
.clk(clk),
.rst_n(rst_n),
.reg1_rdata_i(ie_rs1_rdata_o),
.reg2_rdata_i(ie_rs2_rdata_o),
.mem_rdata_i(dbus_data_i),
.mem_req_ready_i(dbus_req_ready_i),
.mem_rsp_valid_i(dbus_rsp_valid_i),
.mem_wdata_o(ex_mem_wdata_o),
.mem_addr_o(ex_mem_addr_o),
.mem_we_o(ex_mem_we_o),
.mem_sel_o(ex_mem_sel_o),
.mem_req_valid_o(ex_mem_req_valid_o),
.mem_rsp_ready_o(ex_mem_rsp_ready_o),
.mem_access_misaligned_o(ex_mem_access_misaligned_o),
.reg_wdata_o(ex_reg_wdata_o),
.reg_we_o(ex_reg_we_o),
.reg_waddr_o(ex_reg_waddr_o),
.hold_flag_o(ex_hold_flag_o),
.jump_flag_o(ex_jump_flag_o),
.jump_addr_o(ex_jump_addr_o),
.int_assert_i(clint_int_assert_o),
.int_addr_i(clint_int_addr_o),
.inst_ecall_o(ex_inst_ecall_o),
.inst_ebreak_o(ex_inst_ebreak_o),
.inst_mret_o(ex_inst_mret_o),
.int_stall_i(clint_stall_flag_o),
.csr_raddr_o(ex_csr_raddr_o),
.csr_rdata_i(csr_ex_data_o),
.csr_wdata_o(ex_csr_wdata_o),
.csr_we_o(ex_csr_we_o),
.csr_waddr_o(ex_csr_waddr_o),
.dec_info_bus_i(ie_dec_info_bus_o),
.dec_imm_i(ie_dec_imm_o),
.dec_pc_i(ie_dec_pc_o),
.next_pc_i(if_inst_addr_o),
.rd_waddr_i(ie_rd_waddr_o),
.rd_we_i(ie_rd_we_o)
);
clint u_clint(
.clk(clk),
.rst_n(rst_n),
.int_flag_i(int_i),
.inst_ecall_i(ex_inst_ecall_o),
.inst_ebreak_i(ex_inst_ebreak_o),
.inst_mret_i(ex_inst_mret_o),
.inst_addr_i(ie_dec_pc_o),
.jump_flag_i(ex_jump_flag_o),
.mem_access_misaligned_i(ex_mem_access_misaligned_o),
.csr_mtvec_i(csr_mtvec_o),
.csr_mepc_i(csr_mepc_o),
.csr_mstatus_i(csr_mstatus_o),
.csr_we_o(clint_csr_we_o),
.csr_waddr_o(clint_csr_waddr_o),
.csr_wdata_o(clint_csr_wdata_o),
.stall_flag_o(clint_stall_flag_o),
.int_addr_o(clint_int_addr_o),
.int_assert_o(clint_int_assert_o)
);
endmodule

View File

@ -14,11 +14,6 @@
limitations under the License.
*/
`define DM_RESP_VALID 1'b1
`define DM_RESP_INVALID 1'b0
`define DTM_REQ_VALID 1'b1
`define DTM_REQ_INVALID 1'b0
`define DTM_OP_NOP 2'b00
`define DTM_OP_READ 2'b01
`define DTM_OP_WRITE 2'b10
@ -50,8 +45,13 @@ module jtag_dm #(
dm_mem_addr_o,
dm_mem_wdata_o,
dm_mem_rdata_i,
dm_mem_sel_o,
req_valid_o,
req_ready_i,
rsp_valid_i,
rsp_ready_o,
dm_op_req_o,
dm_halt_req_o,
dm_reset_req_o
@ -78,7 +78,11 @@ module jtag_dm #(
output wire[31:0] dm_mem_addr_o;
output wire[31:0] dm_mem_wdata_o;
input wire[31:0] dm_mem_rdata_i;
output wire dm_op_req_o;
output wire[3:0] dm_mem_sel_o;
output wire req_valid_o;
input wire req_ready_i;
input wire rsp_valid_i;
output wire rsp_ready_o;
output wire dm_halt_req_o;
output wire dm_reset_req_o;
@ -107,8 +111,13 @@ module jtag_dm #(
localparam COMMAND = 6'h17;
localparam DPC = 16'h7b1;
localparam OP_SUCC = 2'b00;
localparam OP_SUCC = 2'b00;
localparam STATE_IDLE = 3'b001;
localparam STATE_EXE = 3'b010;
localparam STATE_END = 3'b100;
reg[2:0] state;
reg[31:0] read_data;
reg dm_reg_we;
reg[4:0] dm_reg_addr;
@ -116,21 +125,29 @@ module jtag_dm #(
reg dm_mem_we;
reg[31:0] dm_mem_addr;
reg[31:0] dm_mem_wdata;
reg[31:0] dm_mem_rdata;
reg dm_halt_req;
reg dm_reset_req;
reg need_resp;
reg is_read_reg;
wire rx_valid;
wire[DTM_REQ_BITS-1:0] rx_data;
wire[DTM_REQ_BITS-1:0] rx_data; // driver
reg[DTM_REQ_BITS-1:0] rx_data_r;
wire[31:0] sbaddress0_next = sbaddress0 + 4;
wire[3:0] dm_mem_sel = (sbcs[19:17] == 3'd0)? 4'b0001:
(sbcs[19:17] == 3'd1)? 4'b0011:
4'b1111;
wire[2:0] address_inc_step = (sbcs[19:17] == 3'd0)? 3'd1:
(sbcs[19:17] == 3'd1)? 3'd2:
3'd4;
wire[31:0] sbaddress0_next = sbaddress0 + {29'h0, address_inc_step};
wire[DM_RESP_BITS-1:0] dm_resp_data;
wire[DMI_OP_BITS-1:0] op = rx_data[DMI_OP_BITS-1:0];
wire[DMI_DATA_BITS-1:0] data = rx_data[DMI_DATA_BITS+DMI_OP_BITS-1:DMI_OP_BITS];
wire[DMI_ADDR_BITS-1:0] address = rx_data[DTM_REQ_BITS-1:DMI_DATA_BITS+DMI_OP_BITS];
wire[DMI_OP_BITS-1:0] op = rx_data_r[DMI_OP_BITS-1:0];
wire[DMI_DATA_BITS-1:0] data = rx_data_r[DMI_DATA_BITS+DMI_OP_BITS-1:DMI_OP_BITS];
wire[DMI_ADDR_BITS-1:0] address = rx_data_r[DTM_REQ_BITS-1:DMI_DATA_BITS+DMI_OP_BITS];
wire read_dmstatus = (op == `DTM_OP_READ) & (address == DMSTATUS);
wire req_sys_bus = ~(address == DMSTATUS);
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
@ -151,155 +168,177 @@ module jtag_dm #(
command <= 32'h0;
dm_reg_wdata <= 32'h0;
dm_mem_wdata <= 32'h0;
dm_mem_rdata <= 32'h0;
dmstatus <= 32'h430c82;
is_read_reg <= 1'b0;
read_data <= 32'h0;
need_resp <= 1'b0;
state <= STATE_IDLE;
end else begin
if (rx_valid) begin
need_resp <= 1'b1;
case (op)
`DTM_OP_READ: begin
case (address)
DMSTATUS: begin
read_data <= dmstatus;
end
DMCONTROL: begin
read_data <= dmcontrol;
end
HARTINFO: begin
read_data <= hartinfo;
end
SBCS: begin
read_data <= sbcs;
end
ABSTRACTCS: begin
read_data <= abstractcs;
end
DATA0: begin
if (is_read_reg == 1'b1) begin
read_data <= dm_reg_rdata_i;
end else begin
read_data <= data0;
end
is_read_reg <= 1'b0;
end
SBDATA0: begin
read_data <= dm_mem_rdata_i;
if (sbcs[16] == 1'b1) begin
sbaddress0 <= sbaddress0_next;
end
if (sbcs[15] == 1'b1) begin
dm_mem_addr <= sbaddress0_next;
end
end
default: begin
read_data <= {(DMI_DATA_BITS){1'b0}};
end
endcase
case (state)
STATE_IDLE: begin
// driver
if (rx_valid) begin
rx_data_r <= rx_data;
state <= STATE_EXE;
end
`DTM_OP_WRITE: begin
read_data <= {(DMI_DATA_BITS){1'b0}};
case (address)
DMCONTROL: begin
// reset DM module
if (data[0] == 1'b0) begin
dcsr <= 32'hc0;
dmstatus <= 32'h430c82; // not halted, all running
hartinfo <= 32'h0;
sbcs <= 32'h20040404;
abstractcs <= 32'h1000003;
dmcontrol <= data;
dm_halt_req <= 1'b0;
dm_reset_req <= 1'b0;
// DM is active
end else begin
// we have only one hart
dmcontrol <= (data & ~(32'h3fffc0)) | 32'h10000;
// halt
if (data[31] == 1'b1) begin
dm_halt_req <= 1'b1;
// clear ALLRUNNING ANYRUNNING and set ALLHALTED
dmstatus <= {dmstatus[31:12], 4'h3, dmstatus[7:0]};
// resume
end else if (dm_halt_req == 1'b1 && data[30] == 1'b1) begin
dm_halt_req <= 1'b0;
// set ALLRUNNING ANYRUNNING and clear ALLHALTED
dmstatus <= {dmstatus[31:12], 4'hc, dmstatus[7:0]};
end
STATE_EXE: begin
state <= STATE_END;
need_resp <= 1'b1;
case (op)
`DTM_OP_READ: begin
case (address)
DMSTATUS: begin
read_data <= dmstatus;
end
DMCONTROL: begin
read_data <= dmcontrol;
end
HARTINFO: begin
read_data <= hartinfo;
end
SBCS: begin
read_data <= sbcs;
end
ABSTRACTCS: begin
read_data <= abstractcs;
end
DATA0: begin
if (is_read_reg == 1'b1) begin
read_data <= dm_reg_rdata_i;
end else begin
read_data <= data0;
end
is_read_reg <= 1'b0;
end
SBDATA0: begin
read_data <= dm_mem_rdata;
if (sbcs[16] == 1'b1) begin
sbaddress0 <= sbaddress0_next;
end
if (sbcs[15] == 1'b1) begin
dm_mem_addr <= sbaddress0_next;
end
end
end
COMMAND: begin
// access reg
if (data[31:24] == 8'h0) begin
if (data[22:20] > 3'h2) begin
abstractcs <= abstractcs | (1'b1 << 9);
default: begin
read_data <= {(DMI_DATA_BITS){1'b0}};
end
endcase
end
`DTM_OP_WRITE: begin
read_data <= {(DMI_DATA_BITS){1'b0}};
case (address)
DMCONTROL: begin
// reset DM module
if (data[0] == 1'b0) begin
dcsr <= 32'hc0;
dmstatus <= 32'h430c82; // not halted, all running
hartinfo <= 32'h0;
sbcs <= 32'h20040404;
abstractcs <= 32'h1000003;
dmcontrol <= data;
dm_halt_req <= 1'b0;
dm_reset_req <= 1'b0;
// DM is active
end else begin
abstractcs <= abstractcs & (~(3'h7 << 8));
// read or write
if (data[18] == 1'b0) begin
dm_reg_addr <= data[15:0] - 16'h1000;
// read
if (data[16] == 1'b0) begin
if (data[15:0] == DCSR) begin
data0 <= dcsr;
end else if (data[15:0] < 16'h1020) begin
is_read_reg <= 1'b1;
end
// write
end else begin
// when write dpc, we reset cpu here
if (data[15:0] == DPC) begin
dm_reset_req <= 1'b1;
dm_halt_req <= 1'b0;
dmstatus <= {dmstatus[31:12], 4'hc, dmstatus[7:0]};
end else if (data[15:0] < 16'h1020) begin
dm_reg_we <= 1'b1;
dm_reg_wdata <= data0;
// we have only one hart
dmcontrol <= (data & ~(32'h3fffc0)) | 32'h10000;
// halt
if (data[31] == 1'b1) begin
dm_halt_req <= 1'b1;
// clear ALLRUNNING ANYRUNNING and set ALLHALTED
dmstatus <= {dmstatus[31:12], 4'h3, dmstatus[7:0]};
// reset
end else if (data[1] == 1'b1) begin
dm_reset_req <= 1'b1;
dm_halt_req <= 1'b0;
dmstatus <= {dmstatus[31:12], 4'hc, dmstatus[7:0]};
// resume
end else if (dm_halt_req == 1'b1 && data[30] == 1'b1) begin
dm_halt_req <= 1'b0;
// set ALLRUNNING ANYRUNNING and clear ALLHALTED
dmstatus <= {dmstatus[31:12], 4'hc, dmstatus[7:0]};
end
end
end
COMMAND: begin
// access reg
if (data[31:24] == 8'h0) begin
if (data[22:20] > 3'h2) begin
abstractcs <= abstractcs | (1'b1 << 9);
end else begin
abstractcs <= abstractcs & (~(3'h7 << 8));
// read or write
if (data[18] == 1'b0) begin
dm_reg_addr <= data[15:0] - 16'h1000;
// read
if (data[16] == 1'b0) begin
if (data[15:0] == DCSR) begin
data0 <= dcsr;
end else if (data[15:0] < 16'h1020) begin
is_read_reg <= 1'b1;
end
// write
end else begin
if (data[15:0] < 16'h1020) begin
dm_reg_we <= 1'b1;
dm_reg_wdata <= data0;
end
end
end
end
end
end
end
DATA0: begin
data0 <= data;
end
SBCS: begin
sbcs <= data;
end
SBADDRESS0: begin
sbaddress0 <= data;
if (sbcs[20] == 1'b1) begin
dm_mem_addr <= data;
DATA0: begin
data0 <= data;
end
end
SBDATA0: begin
sbdata0 <= data;
dm_mem_addr <= sbaddress0;
dm_mem_wdata <= data;
dm_mem_we <= 1'b1;
if (sbcs[16] == 1'b1) begin
sbaddress0 <= sbaddress0_next;
SBCS: begin
sbcs <= data;
end
end
endcase
end
SBADDRESS0: begin
sbaddress0 <= data;
if (sbcs[20] == 1'b1) begin
dm_mem_addr <= data;
end
end
SBDATA0: begin
sbdata0 <= data;
dm_mem_addr <= sbaddress0;
dm_mem_wdata <= data;
dm_mem_we <= 1'b1;
if (sbcs[16] == 1'b1) begin
sbaddress0 <= sbaddress0_next;
end
end
endcase
end
`DTM_OP_NOP: begin
read_data <= {(DMI_DATA_BITS){1'b0}};
end
endcase
end else begin
need_resp <= 1'b0;
dm_mem_we <= 1'b0;
dm_reg_we <= 1'b0;
dm_reset_req <= 1'b0;
end
`DTM_OP_NOP: begin
read_data <= {(DMI_DATA_BITS){1'b0}};
end
endcase
end
STATE_END: begin
state <= STATE_IDLE;
dm_mem_rdata <= dm_mem_rdata_i;
need_resp <= 1'b0;
dm_mem_we <= 1'b0;
dm_reg_we <= 1'b0;
dm_reset_req <= 1'b0;
end
endcase
end
end
wire jtag_req_hsked = (req_valid_o & req_ready_i);
wire jtag_rsp_hsked = (rsp_valid_i & rsp_ready_o);
assign rsp_ready_o = (~rst_n)? 1'b0: 1'b1;
assign dm_mem_sel_o = dm_mem_sel;
assign dm_reg_we_o = dm_reg_we;
assign dm_reg_addr_o = dm_reg_addr;
assign dm_reg_wdata_o = dm_reg_wdata;
@ -307,7 +346,7 @@ module jtag_dm #(
assign dm_mem_addr_o = dm_mem_addr;
assign dm_mem_wdata_o = dm_mem_wdata;
assign dm_op_req_o = (rx_valid & (~read_dmstatus)) | need_resp;
assign req_valid_o = (state != STATE_IDLE) & req_sys_bus;
assign dm_halt_req_o = dm_halt_req;
assign dm_reset_req_o = dm_reset_req;
@ -322,7 +361,7 @@ module jtag_dm #(
.ack_i(dtm_ack_i),
.req_i(need_resp),
.req_data_i(dm_resp_data),
.idle_o(tx_idle),
.idle_o(),
.req_o(dm_resp_valid_o),
.req_data_o(dm_resp_data_o)
);

View File

@ -14,11 +14,6 @@
limitations under the License.
*/
`define DM_RESP_VALID 1'b1
`define DM_RESP_INVALID 1'b0
`define DTM_REQ_VALID 1'b1
`define DTM_REQ_INVALID 1'b0
module jtag_driver #(
parameter DMI_ADDR_BITS = 6,
@ -186,19 +181,19 @@ module jtag_driver #(
// start access DM module
always @(posedge jtag_TCK or negedge rst_n) begin
if (!rst_n) begin
dtm_req_valid <= `DTM_REQ_INVALID;
dtm_req_valid <= 1'b0;
dtm_req_data <= {DTM_REQ_BITS{1'b0}};
end else begin
if (jtag_state == UPDATE_DR) begin
if (ir_reg == REG_DMI) begin
// if DM can be access
if (!is_busy & tx_idle) begin
dtm_req_valid <= `DTM_REQ_VALID;
dtm_req_valid <= 1'b1;
dtm_req_data <= shift_reg;
end
end
end else begin
dtm_req_valid <= `DTM_REQ_INVALID;
dtm_req_valid <= 1'b0;
end
end
end

View File

@ -34,11 +34,17 @@ module jtag_top #(
output wire[4:0] reg_addr_o,
output wire[31:0] reg_wdata_o,
input wire[31:0] reg_rdata_i,
output wire mem_we_o,
output wire[31:0] mem_addr_o,
output wire[31:0] mem_wdata_o,
input wire[31:0] mem_rdata_i,
output wire op_req_o,
output wire[3:0] mem_sel_o,
output wire req_valid_o,
input wire req_ready_i,
input wire rsp_valid_i,
output wire rsp_ready_o,
output wire halt_req_o,
output wire reset_req_o
@ -48,16 +54,15 @@ module jtag_top #(
parameter DM_RESP_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS;
parameter DTM_REQ_BITS = DMI_ADDR_BITS + DMI_DATA_BITS + DMI_OP_BITS;
// jtag_driver
// jtag_driver
wire dtm_ack_o;
wire dtm_req_valid_o;
wire[DTM_REQ_BITS - 1:0] dtm_req_data_o;
// jtag_dm
// jtag_dm
wire dm_ack_o;
wire[DM_RESP_BITS-1:0] dm_resp_data_o;
wire dm_resp_valid_o;
wire dm_op_req_o;
wire dm_halt_req_o;
wire dm_reset_req_o;
@ -100,7 +105,11 @@ module jtag_top #(
.dm_mem_addr_o(mem_addr_o),
.dm_mem_wdata_o(mem_wdata_o),
.dm_mem_rdata_i(mem_rdata_i),
.dm_op_req_o(op_req_o),
.dm_mem_sel_o(mem_sel_o),
.req_valid_o(req_valid_o),
.req_ready_i(req_ready_i),
.rsp_valid_i(rsp_valid_i),
.rsp_ready_o(rsp_ready_o),
.dm_halt_req_o(halt_req_o),
.dm_reset_req_o(reset_req_o)
);

View File

@ -1,436 +0,0 @@
/*
Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// clk = 50MHz
`define UART_BAUD_115200 32'h1B8
//
`define UART_CTRL_REG 32'h30000000
`define UART_STATUS_REG 32'h30000004
`define UART_BAUD_REG 32'h30000008
`define UART_TX_REG 32'h3000000c
`define UART_RX_REG 32'h30000010
`define UART_TX_BUSY_FLAG 32'h1
`define UART_RX_OVER_FLAG 32'h2
//
`define UART_FIRST_PACKET_LEN 8'd131
// ()
`define UART_REMAIN_PACKET_LEN 8'd131
`define UART_RESP_ACK 32'h6
`define UART_RESP_NAK 32'h15
//
`define ROM_START_ADDR 32'h0
//
module uart_debug(
input wire clk, //
input wire rst, //
input wire debug_en_i, // 使
output wire req_o,
output reg mem_we_o,
output reg[31:0] mem_addr_o,
output reg[31:0] mem_wdata_o,
input wire[31:0] mem_rdata_i
);
//
localparam S_IDLE = 14'h0001;
localparam S_INIT_UART_BAUD = 14'h0002;
localparam S_CLEAR_UART_RX_OVER_FLAG = 14'h0004;
localparam S_WAIT_BYTE = 14'h0008;
localparam S_WAIT_BYTE2 = 14'h0010;
localparam S_GET_BYTE = 14'h0020;
localparam S_REC_FIRST_PACKET = 14'h0040;
localparam S_REC_REMAIN_PACKET = 14'h0080;
localparam S_SEND_ACK = 14'h0100;
localparam S_SEND_NAK = 14'h0200;
localparam S_CRC_START = 14'h0400;
localparam S_CRC_CALC = 14'h0800;
localparam S_CRC_END = 14'h1000;
localparam S_WRITE_MEM = 14'h2000;
reg[13:0] state;
//
reg[7:0] rx_data[0:131];
reg[7:0] rec_bytes_index;
reg[7:0] need_to_rec_bytes;
reg[15:0] remain_packet_count;
reg[31:0] fw_file_size;
reg[31:0] write_mem_addr;
reg[31:0] write_mem_data;
reg[7:0] write_mem_byte_index0;
reg[7:0] write_mem_byte_index1;
reg[7:0] write_mem_byte_index2;
reg[7:0] write_mem_byte_index3;
reg[15:0] crc_result;
reg[3:0] crc_bit_index;
reg[7:0] crc_byte_index;
// 线
assign req_o = (rst == 1'b1 && debug_en_i == 1'b1)? 1'b1: 1'b0;
always @ (posedge clk) begin
if (rst == 1'b0 || debug_en_i == 1'b0) begin
mem_addr_o <= 32'h0;
mem_we_o <= 1'b0;
mem_wdata_o <= 32'h0;
state <= S_IDLE;
remain_packet_count <= 16'h0;
end else begin
case (state)
S_IDLE: begin
mem_addr_o <= `UART_CTRL_REG;
mem_wdata_o <= 32'h3;
mem_we_o <= 1'b1;
state <= S_INIT_UART_BAUD;
end
S_INIT_UART_BAUD: begin
mem_addr_o <= `UART_BAUD_REG;
mem_wdata_o <= `UART_BAUD_115200;
mem_we_o <= 1'b1;
state <= S_REC_FIRST_PACKET;
end
S_REC_FIRST_PACKET: begin
remain_packet_count <= 16'h0;
mem_addr_o <= 32'h0;
mem_we_o <= 1'b0;
mem_wdata_o <= 32'h0;
state <= S_CLEAR_UART_RX_OVER_FLAG;
end
S_REC_REMAIN_PACKET: begin
mem_addr_o <= 32'h0;
mem_we_o <= 1'b0;
mem_wdata_o <= 32'h0;
state <= S_CLEAR_UART_RX_OVER_FLAG;
end
S_CLEAR_UART_RX_OVER_FLAG: begin
mem_addr_o <= `UART_STATUS_REG;
mem_wdata_o <= 32'h0;
mem_we_o <= 1'b1;
state <= S_WAIT_BYTE;
end
S_WAIT_BYTE: begin
mem_addr_o <= `UART_STATUS_REG;
mem_wdata_o <= 32'h0;
mem_we_o <= 1'b0;
state <= S_WAIT_BYTE2;
end
S_WAIT_BYTE2: begin
if ((mem_rdata_i & `UART_RX_OVER_FLAG) == `UART_RX_OVER_FLAG) begin
mem_addr_o <= `UART_RX_REG;
mem_wdata_o <= 32'h0;
mem_we_o <= 1'b0;
state <= S_GET_BYTE;
end
end
S_GET_BYTE: begin
if (rec_bytes_index == (need_to_rec_bytes - 1'b1)) begin
state <= S_CRC_START;
end else begin
state <= S_CLEAR_UART_RX_OVER_FLAG;
end
end
S_CRC_START: begin
state <= S_CRC_CALC;
end
S_CRC_CALC: begin
if ((crc_byte_index == need_to_rec_bytes - 2) && crc_bit_index == 4'h8) begin
state <= S_CRC_END;
end
end
S_CRC_END: begin
if (crc_result == {rx_data[need_to_rec_bytes - 1], rx_data[need_to_rec_bytes - 2]}) begin
if (need_to_rec_bytes == `UART_FIRST_PACKET_LEN && remain_packet_count == 16'h0) begin
remain_packet_count <= {7'h0, fw_file_size[31:7]} + 1'b1;
state <= S_SEND_ACK;
end else begin
remain_packet_count <= remain_packet_count - 1'b1;
state <= S_WRITE_MEM;
end
end else begin
state <= S_SEND_NAK;
end
end
S_WRITE_MEM: begin
if (write_mem_byte_index0 == (need_to_rec_bytes + 2)) begin
state <= S_SEND_ACK;
end else begin
mem_addr_o <= write_mem_addr;
mem_wdata_o <= write_mem_data;
mem_we_o <= 1'b1;
end
end
S_SEND_ACK: begin
mem_addr_o <= `UART_TX_REG;
mem_wdata_o <= `UART_RESP_ACK;
mem_we_o <= 1'b1;
if (remain_packet_count > 0) begin
state <= S_REC_REMAIN_PACKET;
end else begin
state <= S_REC_FIRST_PACKET;
end
end
S_SEND_NAK: begin
mem_addr_o <= `UART_TX_REG;
mem_wdata_o <= `UART_RESP_NAK;
mem_we_o <= 1'b1;
if (remain_packet_count > 0) begin
state <= S_REC_REMAIN_PACKET;
end else begin
state <= S_REC_FIRST_PACKET;
end
end
endcase
end
end
//
always @ (posedge clk) begin
if (rst == 1'b0 || debug_en_i == 1'b0) begin
need_to_rec_bytes <= 8'h0;
end else begin
case (state)
S_REC_FIRST_PACKET: begin
need_to_rec_bytes <= `UART_FIRST_PACKET_LEN;
end
S_REC_REMAIN_PACKET: begin
need_to_rec_bytes <= `UART_REMAIN_PACKET_LEN;
end
endcase
end
end
//
always @ (posedge clk) begin
if (rst == 1'b0 || debug_en_i == 1'b0) begin
rec_bytes_index <= 8'h0;
end else begin
case (state)
S_GET_BYTE: begin
rx_data[rec_bytes_index] <= mem_rdata_i[7:0];
rec_bytes_index <= rec_bytes_index + 1'b1;
end
S_REC_FIRST_PACKET: begin
rec_bytes_index <= 8'h0;
end
S_REC_REMAIN_PACKET: begin
rec_bytes_index <= 8'h0;
end
endcase
end
end
//
always @ (posedge clk) begin
if (rst == 1'b0 || debug_en_i == 1'b0) begin
fw_file_size <= 32'h0;
end else begin
case (state)
S_CRC_START: begin
fw_file_size <= {rx_data[61], rx_data[62], rx_data[63], rx_data[64]};
end
endcase
end
end
//
always @ (posedge clk) begin
if (rst == 1'b0 || debug_en_i == 1'b0) begin
write_mem_addr <= 32'h0;
end else begin
case (state)
S_REC_FIRST_PACKET: begin
write_mem_addr <= `ROM_START_ADDR;
end
S_CRC_END: begin
if (write_mem_addr > 0)
write_mem_addr <= write_mem_addr - 4;
end
S_WRITE_MEM: begin
write_mem_addr <= write_mem_addr + 4;
end
endcase
end
end
always @ (posedge clk) begin
if (rst == 1'b0 || debug_en_i == 1'b0) begin
write_mem_data <= 32'h0;
end else begin
case (state)
S_REC_FIRST_PACKET: begin
write_mem_data <= 32'h0;
end
S_CRC_END: begin
write_mem_data <= {rx_data[4], rx_data[3], rx_data[2], rx_data[1]};
end
S_WRITE_MEM: begin
write_mem_data <= {rx_data[write_mem_byte_index3], rx_data[write_mem_byte_index2], rx_data[write_mem_byte_index1], rx_data[write_mem_byte_index0]};
end
endcase
end
end
always @ (posedge clk) begin
if (rst == 1'b0 || debug_en_i == 1'b0) begin
write_mem_byte_index0 <= 8'h0;
end else begin
case (state)
S_REC_FIRST_PACKET: begin
write_mem_byte_index0 <= 8'h0;
end
S_CRC_END: begin
write_mem_byte_index0 <= 8'h5;
end
S_WRITE_MEM: begin
write_mem_byte_index0 <= write_mem_byte_index0 + 4;
end
endcase
end
end
always @ (posedge clk) begin
if (rst == 1'b0 || debug_en_i == 1'b0) begin
write_mem_byte_index1 <= 8'h0;
end else begin
case (state)
S_REC_FIRST_PACKET: begin
write_mem_byte_index1 <= 8'h0;
end
S_CRC_END: begin
write_mem_byte_index1 <= 8'h6;
end
S_WRITE_MEM: begin
write_mem_byte_index1 <= write_mem_byte_index1 + 4;
end
endcase
end
end
always @ (posedge clk) begin
if (rst == 1'b0 || debug_en_i == 1'b0) begin
write_mem_byte_index2 <= 8'h0;
end else begin
case (state)
S_REC_FIRST_PACKET: begin
write_mem_byte_index2 <= 8'h0;
end
S_CRC_END: begin
write_mem_byte_index2 <= 8'h7;
end
S_WRITE_MEM: begin
write_mem_byte_index2 <= write_mem_byte_index2 + 4;
end
endcase
end
end
always @ (posedge clk) begin
if (rst == 1'b0 || debug_en_i == 1'b0) begin
write_mem_byte_index3 <= 8'h0;
end else begin
case (state)
S_REC_FIRST_PACKET: begin
write_mem_byte_index3 <= 8'h0;
end
S_CRC_END: begin
write_mem_byte_index3 <= 8'h8;
end
S_WRITE_MEM: begin
write_mem_byte_index3 <= write_mem_byte_index3 + 4;
end
endcase
end
end
// CRC
always @ (posedge clk) begin
if (rst == 1'b0 || debug_en_i == 1'b0) begin
crc_result <= 16'h0;
end else begin
case (state)
S_CRC_START: begin
crc_result <= 16'hffff;
end
S_CRC_CALC: begin
if (crc_bit_index == 4'h0) begin
crc_result <= crc_result ^ rx_data[crc_byte_index];
end else begin
if (crc_bit_index < 4'h9) begin
if (crc_result[0] == 1'b1) begin
crc_result <= {1'b0, crc_result[15:1]} ^ 16'ha001;
end else begin
crc_result <= {1'b0, crc_result[15:1]};
end
end
end
end
endcase
end
end
always @ (posedge clk) begin
if (rst == 1'b0 || debug_en_i == 1'b0) begin
crc_bit_index <= 4'h0;
end else begin
case (state)
S_CRC_START: begin
crc_bit_index <= 4'h0;
end
S_CRC_CALC: begin
if (crc_bit_index < 4'h9) begin
crc_bit_index <= crc_bit_index + 1'b1;
end else begin
crc_bit_index <= 4'h0;
end
end
endcase
end
end
always @ (posedge clk) begin
if (rst == 1'b0 || debug_en_i == 1'b0) begin
crc_byte_index <= 8'h0;
end else begin
case (state)
S_CRC_START: begin
crc_byte_index <= 8'h1;
end
S_CRC_CALC: begin
if (crc_bit_index == 4'h0) begin
crc_byte_index <= crc_byte_index + 1'b1;
end
end
endcase
end
end
endmodule

View File

@ -14,18 +14,21 @@
limitations under the License.
*/
// GPIO
module gpio(
input wire clk,
input wire rst,
input wire we_i,
input wire rst_n,
input wire[31:0] addr_i,
input wire[31:0] data_i,
input wire[3:0] sel_i,
input wire we_i,
output wire[31:0] data_o,
output reg[31:0] data_o,
input wire req_valid_i,
output wire req_ready_o,
output wire rsp_valid_o,
input wire rsp_ready_i,
input wire[1:0] io_pin_i,
output wire[31:0] reg_ctrl,
@ -33,38 +36,60 @@ module gpio(
);
// GPIO
// GPIO()
localparam GPIO_CTRL = 4'h0;
// GPIO
localparam GPIO_DATA = 4'h4;
// 21IO16IO
// GPIO
// 21IO16IO
// 0: 12
reg[31:0] gpio_ctrl;
//
reg[31:0] gpio_data;
// GPIO
reg[31:0] gpio_data;
assign reg_ctrl = gpio_ctrl;
assign reg_data = gpio_data;
wire wen = we_i & req_valid_i;
wire ren = (~we_i) & req_valid_i;
wire write_reg_ctrl_en = wen & (addr_i[3:0] == GPIO_CTRL);
wire write_reg_data_en = wen & (addr_i[3:0] == GPIO_DATA);
//
always @ (posedge clk) begin
if (rst == 1'b0) begin
gpio_data <= 32'h0;
// gpio_ctrl
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
gpio_ctrl <= 32'h0;
end else begin
if (we_i == 1'b1) begin
case (addr_i[3:0])
GPIO_CTRL: begin
gpio_ctrl <= data_i;
end
GPIO_DATA: begin
gpio_data <= data_i;
end
endcase
if (write_reg_ctrl_en) begin
if (sel_i[0]) begin
gpio_ctrl[7:0] <= data_i[7:0];
end
if (sel_i[1]) begin
gpio_ctrl[15:8] <= data_i[15:8];
end
if (sel_i[2]) begin
gpio_ctrl[23:16] <= data_i[23:16];
end
if (sel_i[3]) begin
gpio_ctrl[31:24] <= data_i[31:24];
end
end
end
end
// gpio_data
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
gpio_data <= 32'h0;
end else begin
if (write_reg_data_en) begin
if (sel_i[0]) begin
gpio_data[7:0] <= data_i[7:0];
end
if (sel_i[1]) begin
gpio_data[15:8] <= data_i[15:8];
end
end else begin
if (gpio_ctrl[1:0] == 2'b10) begin
gpio_data[0] <= io_pin_i[0];
@ -76,23 +101,36 @@ module gpio(
end
end
reg[31:0] data_r;
//
always @ (*) begin
if (rst == 1'b0) begin
data_o = 32'h0;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_r <= 32'h0;
end else begin
case (addr_i[3:0])
GPIO_CTRL: begin
data_o = gpio_ctrl;
end
GPIO_DATA: begin
data_o = gpio_data;
end
default: begin
data_o = 32'h0;
end
endcase
if (ren) begin
case (addr_i[3:0])
GPIO_CTRL: data_r <= gpio_ctrl;
GPIO_DATA: data_r <= gpio_data;
default: data_r <= 32'h0;
endcase
end else begin
data_r <= 32'h0;
end
end
end
assign data_o = data_r;
vld_rdy #(
.CUT_READY(0)
) u_vld_rdy(
.clk(clk),
.rst_n(rst_n),
.vld_i(req_valid_i),
.rdy_o(req_ready_o),
.rdy_i(rsp_ready_i),
.vld_o(rsp_valid_o)
);
endmodule

View File

@ -1,5 +1,5 @@
/*
Copyright 2019 Blue Liang, liangkangnan@163.com
Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -16,35 +16,50 @@
`include "../core/defines.v"
// ram module
module ram(
module ram #(
parameter DP = 4096)(
input wire clk,
input wire rst,
input wire rst_n,
input wire[31:0] addr_i,
input wire[31:0] data_i,
input wire[3:0] sel_i,
input wire we_i,
output wire[31:0] data_o,
input wire we_i, // write enable
input wire[`MemAddrBus] addr_i, // addr
input wire[`MemBus] data_i,
output reg[`MemBus] data_o // read data
input wire req_valid_i,
output wire req_ready_o,
output wire rsp_valid_o,
input wire rsp_ready_i
);
reg[`MemBus] _ram[0:`MemNum - 1];
wire[31:0] addr = addr_i[31:2];
gen_ram #(
.DP(DP),
.DW(32),
.MW(4),
.AW(32)
) u_gen_ram(
.clk(clk),
.addr_i(addr),
.data_i(data_i),
.sel_i(sel_i),
.we_i(we_i),
.data_o(data_o)
);
always @ (posedge clk) begin
if (we_i == `WriteEnable) begin
_ram[addr_i[31:2]] <= data_i;
end
end
always @ (*) begin
if (rst == `RstEnable) begin
data_o = `ZeroWord;
end else begin
data_o = _ram[addr_i[31:2]];
end
end
vld_rdy #(
.CUT_READY(0)
) u_vld_rdy(
.clk(clk),
.rst_n(rst_n),
.vld_i(req_valid_i),
.rdy_o(req_ready_o),
.rdy_i(rsp_ready_i),
.vld_o(rsp_valid_o)
);
endmodule

View File

@ -17,34 +17,49 @@
`include "../core/defines.v"
module rom(
module rom #(
parameter DP = 4096)(
input wire clk,
input wire rst,
input wire rst_n,
input wire[31:0] addr_i,
input wire[31:0] data_i,
input wire[3:0] sel_i,
input wire we_i,
output wire[31:0] data_o,
input wire we_i, // write enable
input wire[`MemAddrBus] addr_i, // addr
input wire[`MemBus] data_i,
output reg[`MemBus] data_o // read data
input wire req_valid_i,
output wire req_ready_o,
output wire rsp_valid_o,
input wire rsp_ready_i
);
reg[`MemBus] _rom[0:`RomNum - 1];
wire[31:0] addr = addr_i[31:2];
gen_ram #(
.DP(DP),
.DW(32),
.MW(4),
.AW(32)
) u_gen_ram(
.clk(clk),
.addr_i(addr),
.data_i(data_i),
.sel_i(sel_i),
.we_i(we_i),
.data_o(data_o)
);
always @ (posedge clk) begin
if (we_i == `WriteEnable) begin
_rom[addr_i[31:2]] <= data_i;
end
end
always @ (*) begin
if (rst == `RstEnable) begin
data_o = `ZeroWord;
end else begin
data_o = _rom[addr_i[31:2]];
end
end
vld_rdy #(
.CUT_READY(0)
) u_vld_rdy(
.clk(clk),
.rst_n(rst_n),
.vld_i(req_valid_i),
.rdy_o(req_ready_o),
.rdy_i(rsp_ready_i),
.vld_o(rsp_valid_o)
);
endmodule

View File

@ -1,244 +0,0 @@
/*
Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// spi master
module spi(
input wire clk,
input wire rst,
input wire[31:0] data_i,
input wire[31:0] addr_i,
input wire we_i,
output reg[31:0] data_o,
output reg spi_mosi, // spispi
input wire spi_miso, // spispi
output wire spi_ss, // spi
output reg spi_clk // spiclk
);
localparam SPI_CTRL = 4'h0; // spi_ctrl
localparam SPI_DATA = 4'h4; // spi_data
localparam SPI_STATUS = 4'h8; // spi_status
// spi
// addr: 0x00
// [0]: 1: enable, 0: disable
// [1]: CPOL
// [2]: CPHA
// [3]: select slave, 1: select, 0: deselect
// [15:8]: clk div
reg[31:0] spi_ctrl;
// spi
// addr: 0x04
// [7:0] cmd or inout data
reg[31:0] spi_data;
// spi
// addr: 0x08
// [0]: 1: busy, 0: idle
reg[31:0] spi_status;
reg[8:0] clk_cnt; //
reg en; // 使
reg[4:0] spi_clk_edge_cnt; // spi clk沿
reg spi_clk_edge_level; // spi clk沿
reg[7:0] rdata; // spi
reg done; //
reg[3:0] bit_index; // bit
wire[8:0] div_cnt;
assign spi_ss = ~spi_ctrl[3]; // SPI
assign div_cnt = spi_ctrl[15:8];// 0: 21428316432
// 使
//
always @ (posedge clk) begin
if (rst == 1'b0) begin
en <= 1'b0;
end else begin
if (spi_ctrl[0] == 1'b1) begin
en <= 1'b1;
end else if (done == 1'b1) begin
en <= 1'b0;
end else begin
en <= en;
end
end
end
//
always @ (posedge clk) begin
if (rst == 1'b0) begin
clk_cnt <= 9'h0;
end else if (en == 1'b1) begin
if (clk_cnt == div_cnt) begin
clk_cnt <= 9'h0;
end else begin
clk_cnt <= clk_cnt + 1'b1;
end
end else begin
clk_cnt <= 9'h0;
end
end
// spi clk沿
// 沿
always @ (posedge clk) begin
if (rst == 1'b0) begin
spi_clk_edge_cnt <= 5'h0;
spi_clk_edge_level <= 1'b0;
end else if (en == 1'b1) begin
//
if (clk_cnt == div_cnt) begin
if (spi_clk_edge_cnt == 5'd17) begin
spi_clk_edge_cnt <= 5'h0;
spi_clk_edge_level <= 1'b0;
end else begin
spi_clk_edge_cnt <= spi_clk_edge_cnt + 1'b1;
spi_clk_edge_level <= 1'b1;
end
end else begin
spi_clk_edge_level <= 1'b0;
end
end else begin
spi_clk_edge_cnt <= 5'h0;
spi_clk_edge_level <= 1'b0;
end
end
// bit
always @ (posedge clk) begin
if (rst == 1'b0) begin
spi_clk <= 1'b0;
rdata <= 8'h0;
spi_mosi <= 1'b0;
bit_index <= 4'h0;
end else begin
if (en) begin
if (spi_clk_edge_level == 1'b1) begin
case (spi_clk_edge_cnt)
// 沿
1, 3, 5, 7, 9, 11, 13, 15: begin
spi_clk <= ~spi_clk;
if (spi_ctrl[2] == 1'b1) begin
spi_mosi <= spi_data[bit_index]; // 1bit
bit_index <= bit_index - 1'b1;
end else begin
rdata <= {rdata[6:0], spi_miso}; // 1bit
end
end
// 沿
2, 4, 6, 8, 10, 12, 14, 16: begin
spi_clk <= ~spi_clk;
if (spi_ctrl[2] == 1'b1) begin
rdata <= {rdata[6:0], spi_miso}; // 1bit
end else begin
spi_mosi <= spi_data[bit_index]; // 1bit
bit_index <= bit_index - 1'b1;
end
end
17: begin
spi_clk <= spi_ctrl[1];
end
endcase
end
end else begin
//
spi_clk <= spi_ctrl[1];
if (spi_ctrl[2] == 1'b0) begin
spi_mosi <= spi_data[7]; //
bit_index <= 4'h6;
end else begin
bit_index <= 4'h7;
end
end
end
end
// ()
always @ (posedge clk) begin
if (rst == 1'b0) begin
done <= 1'b0;
end else begin
if (en && spi_clk_edge_cnt == 5'd17) begin
done <= 1'b1;
end else begin
done <= 1'b0;
end
end
end
// write reg
always @ (posedge clk) begin
if (rst == 1'b0) begin
spi_ctrl <= 32'h0;
spi_data <= 32'h0;
spi_status <= 32'h0;
end else begin
spi_status[0] <= en;
if (we_i == 1'b1) begin
case (addr_i[3:0])
SPI_CTRL: begin
spi_ctrl <= data_i;
end
SPI_DATA: begin
spi_data <= data_i;
end
default: begin
end
endcase
end else begin
spi_ctrl[0] <= 1'b0;
//
if (done == 1'b1) begin
spi_data <= {24'h0, rdata};
end
end
end
end
// read reg
always @ (*) begin
if (rst == 1'b0) begin
data_o = 32'h0;
end else begin
case (addr_i[3:0])
SPI_CTRL: begin
data_o = spi_ctrl;
end
SPI_DATA: begin
data_o = spi_data;
end
SPI_STATUS: begin
data_o = spi_status;
end
default: begin
data_o = 32'h0;
end
endcase
end
end
endmodule

View File

@ -16,103 +16,153 @@
`include "../core/defines.v"
// 32 bits count up timer module
// 32
module timer(
input wire clk,
input wire rst,
input wire[31:0] data_i,
input wire rst_n,
input wire[31:0] addr_i,
input wire[31:0] data_i,
input wire[3:0] sel_i,
input wire we_i,
output wire[31:0] data_o,
input wire req_valid_i,
output wire req_ready_o,
output wire rsp_valid_o,
input wire rsp_ready_i,
output reg[31:0] data_o,
output wire int_sig_o
);
localparam REG_CTRL = 4'h0;
// ()
localparam REG_CTRL = 4'h0;
localparam REG_COUNT = 4'h4;
localparam REG_VALUE = 4'h8;
// [0]: timer enable
// [1]: timer int enable
// [2]: timer int pending, write 1 to clear it
// addr offset: 0x00
//
// bit[0]: 使
// bit[1]: 使
// bit[2]: pending1
reg[31:0] timer_ctrl;
// timer current count, read only
// addr offset: 0x04
// ,
reg[31:0] timer_count;
// timer expired value
// addr offset: 0x08
// pending
reg[31:0] timer_value;
wire wen = we_i & req_valid_i;
wire ren = (~we_i) & req_valid_i;
wire timer_en = (timer_ctrl[0] == 1'b1);
wire timer_int_en = (timer_ctrl[1] == 1'b1);
wire timer_expired = (timer_count >= timer_value);
wire write_reg_ctrl_en = wen & (addr_i[3:0] == REG_CTRL);
wire write_reg_value_en = wen & (addr_i[3:0] == REG_VALUE);
assign int_sig_o = ((timer_ctrl[2] == 1'b1) && (timer_ctrl[1] == 1'b1))? `INT_ASSERT: `INT_DEASSERT;
// counter
always @ (posedge clk) begin
if (rst == `RstEnable) begin
timer_count <= `ZeroWord;
//
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
timer_count <= 32'h0;
end else begin
if (timer_ctrl[0] == 1'b1) begin
timer_count <= timer_count + 1'b1;
if (timer_count >= timer_value) begin
timer_count <= `ZeroWord;
if (timer_en) begin
if (timer_expired) begin
timer_count <= 32'h0;
end else begin
timer_count <= timer_count + 1'b1;
end
end else begin
timer_count <= `ZeroWord;
timer_count <= 32'h0;
end
end
end
// write regs
always @ (posedge clk) begin
if (rst == `RstEnable) begin
timer_ctrl <= `ZeroWord;
timer_value <= `ZeroWord;
reg int_sig_r;
//
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
int_sig_r <= 1'b0;
end else begin
if (we_i == `WriteEnable) begin
if (write_reg_ctrl_en & (data_i[2] == 1'b1)) begin
int_sig_r <= 1'b0;
end else if (timer_int_en & timer_en & timer_expired) begin
int_sig_r <= 1'b1;
end
end
end
assign int_sig_o = int_sig_r;
// timer_ctrl
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
timer_ctrl <= 32'h0;
end else begin
if (write_reg_ctrl_en) begin
if (sel_i[0]) begin
timer_ctrl[7:0] <= {data_i[7:3], timer_ctrl[2] & (~data_i[2]), data_i[1:0]};
end
end else begin
if (timer_expired) begin
timer_ctrl[0] <= 1'b0;
end
end
end
end
// timer_value
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
timer_value <= 32'h0;
end else begin
if (write_reg_value_en) begin
if (sel_i[0]) begin
timer_value[7:0] <= data_i[7:0];
end
if (sel_i[1]) begin
timer_value[15:8] <= data_i[15:8];
end
if (sel_i[2]) begin
timer_value[23:16] <= data_i[23:16];
end
if (sel_i[3]) begin
timer_value[31:24] <= data_i[31:24];
end
end
end
end
reg[31:0] data_r;
//
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_r <= 32'h0;
end else begin
if (ren) begin
case (addr_i[3:0])
REG_CTRL: begin
timer_ctrl <= {data_i[31:3], (timer_ctrl[2] & (~data_i[2])), data_i[1:0]};
end
REG_VALUE: begin
timer_value <= data_i;
end
REG_VALUE: data_r <= timer_value;
REG_CTRL: data_r <= timer_ctrl;
REG_COUNT: data_r <= timer_count;
default: data_r <= 32'h0;
endcase
end else begin
if ((timer_ctrl[0] == 1'b1) && (timer_count >= timer_value)) begin
timer_ctrl[0] <= 1'b0;
timer_ctrl[2] <= 1'b1;
end
data_r <= 32'h0;
end
end
end
// read regs
always @ (*) begin
if (rst == `RstEnable) begin
data_o = `ZeroWord;
end else begin
case (addr_i[3:0])
REG_VALUE: begin
data_o = timer_value;
end
REG_CTRL: begin
data_o = timer_ctrl;
end
REG_COUNT: begin
data_o = timer_count;
end
default: begin
data_o = `ZeroWord;
end
endcase
end
end
assign data_o = data_r;
vld_rdy #(
.CUT_READY(0)
) u_vld_rdy(
.clk(clk),
.rst_n(rst_n),
.vld_i(req_valid_i),
.rdy_o(req_ready_o),
.rdy_i(rsp_ready_i),
.vld_o(rsp_valid_o)
);
endmodule

View File

@ -14,46 +14,49 @@
limitations under the License.
*/
`include "../core/defines.v"
// (: 115200, 8 N 1)
// (: 115200, 8N1)
module uart(
input wire clk,
input wire rst,
input wire we_i,
input wire clk,
input wire rst_n,
input wire[31:0] addr_i,
input wire[31:0] data_i,
input wire[3:0] sel_i,
input wire we_i,
output wire[31:0] data_o,
input wire req_valid_i,
output wire req_ready_o,
output wire rsp_valid_o,
input wire rsp_ready_i,
output reg[31:0] data_o,
output wire tx_pin,
input wire rx_pin
);
// 50MHz115200bps
localparam BAUD_115200 = 32'h1B8;
// 115200bps
localparam BAUD_115200 = `CPU_CLOCK_HZ / 115200;
localparam S_IDLE = 4'b0001;
localparam S_START = 4'b0010;
localparam S_SEND_BYTE = 4'b0100;
localparam S_STOP = 4'b1000;
reg tx_data_valid;
reg tx_data_ready;
reg[3:0] state;
reg[3:0] next_state;
reg[15:0] cycle_cnt;
reg tx_bit;
reg[3:0] bit_cnt;
reg[7:0] tx_data;
reg tx_reg;
reg rx_q0;
reg rx_q1;
wire rx_negedge;
reg rx_start; // RX使
reg[3:0] rx_clk_edge_cnt; // clk沿
reg[3:0] rx_clk_edge_cnt; // clk沿
reg rx_clk_edge_level; // clk沿
reg rx_done;
reg[15:0] rx_clk_cnt;
@ -61,159 +64,246 @@ module uart(
reg[7:0] rx_data;
reg rx_over;
localparam UART_CTRL = 8'h0;
localparam UART_STATUS = 8'h4;
localparam UART_BAUD = 8'h8;
localparam UART_TXDATA = 8'hc;
localparam UART_RXDATA = 8'h10;
// ()
localparam UART_CTRL = 8'h0;
localparam UART_STATUS = 8'h4;
localparam UART_BAUD = 8'h8;
localparam UART_TXDATA = 8'hc;
localparam UART_RXDATA = 8'h10;
// addr: 0x00
// rw. bit[0]: tx enable, 1 = enable, 0 = disable
// rw. bit[1]: rx enable, 1 = enable, 0 = disable
// UART
// bit[0]: UART TX使, 1: enable, 0: disable
// bit[1]: UART RX使, 1: enable, 0: disable
reg[31:0] uart_ctrl;
// addr: 0x04
// ro. bit[0]: tx busy, 1 = busy, 0 = idle
// rw. bit[1]: rx over, 1 = over, 0 = receiving
// must check this bit before tx data
// UART
// bit[0]: TX, 1: busy, 0: idle
// bit[1]: RX, 1: over, 0: receiving
reg[31:0] uart_status;
// addr: 0x08
// rw. clk div
// UART()
reg[31:0] uart_baud;
// addr: 0x10
// ro. rx data
// UART
reg[31:0] uart_tx;
// UART
reg[31:0] uart_rx;
assign tx_pin = tx_reg;
wire wen = we_i & req_valid_i;
wire ren = (~we_i) & req_valid_i;
wire write_reg_ctrl_en = wen & (addr_i[7:0] == UART_CTRL);
wire write_reg_status_en = wen & (addr_i[7:0] == UART_STATUS);
wire write_reg_baud_en = wen & (addr_i[7:0] == UART_BAUD);
wire write_reg_txdata_en = wen & (addr_i[7:0] == UART_TXDATA);
wire tx_start = write_reg_txdata_en & sel_i[0] & uart_ctrl[0] & (~uart_status[0]);
wire rx_recv_over = uart_ctrl[1] & rx_over;
assign tx_pin = tx_bit;
//
always @ (posedge clk) begin
if (rst == 1'b0) begin
uart_ctrl <= 32'h0;
uart_status <= 32'h0;
// uart_rxdata
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
uart_rx <= 32'h0;
uart_baud <= BAUD_115200;
tx_data_valid <= 1'b0;
end else begin
if (we_i == 1'b1) begin
case (addr_i[7:0])
UART_CTRL: begin
uart_ctrl <= data_i;
end
UART_BAUD: begin
uart_baud <= data_i;
end
UART_STATUS: begin
uart_status[1] <= data_i[1];
end
UART_TXDATA: begin
if (uart_ctrl[0] == 1'b1 && uart_status[0] == 1'b0) begin
tx_data <= data_i[7:0];
uart_status[0] <= 1'b1;
tx_data_valid <= 1'b1;
end
end
endcase
//
if (rx_recv_over) begin
uart_rx[7:0] <= rx_data;
end
end
end
// uart_txdata
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
uart_tx <= 32'h0;
end else begin
//
if (tx_start) begin
uart_tx[7:0] <= data_i[7:0];
end
end
end
// uart_status
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
uart_status <= 32'h0;
end else begin
if (write_reg_status_en & sel_i[0]) begin
// RX
uart_status[1] <= data_i[1];
end else begin
tx_data_valid <= 1'b0;
if (tx_data_ready == 1'b1) begin
// TX
if (tx_start) begin
uart_status[0] <= 1'b1;
// TX
end else if ((state == S_STOP) & (cycle_cnt == uart_baud[15:0])) begin
uart_status[0] <= 1'b0;
//
end
if (uart_ctrl[1] == 1'b1) begin
if (rx_over == 1'b1) begin
uart_status[1] <= 1'b1;
uart_rx <= {24'h0, rx_data};
end
if (rx_recv_over) begin
uart_status[1] <= 1'b1;
end
end
end
end
//
always @ (*) begin
if (rst == 1'b0) begin
data_o = 32'h0;
// uart_ctrl
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
uart_ctrl <= 32'h0;
end else begin
case (addr_i[7:0])
UART_CTRL: begin
data_o = uart_ctrl;
if (write_reg_ctrl_en & sel_i[0]) begin
uart_ctrl[7:0] <= data_i[7:0];
end
end
end
// uart_baud
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
uart_baud <= BAUD_115200;
end else begin
if (write_reg_baud_en) begin
if (sel_i[0]) begin
uart_baud[7:0] <= data_i[7:0];
end
UART_STATUS: begin
data_o = uart_status;
if (sel_i[1]) begin
uart_baud[15:8] <= data_i[15:8];
end
UART_BAUD: begin
data_o = uart_baud;
end
end
end
reg[31:0] data_r;
//
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_r <= 32'h0;
end else begin
if (ren) begin
case (addr_i[7:0])
UART_CTRL: data_r <= uart_ctrl;
UART_STATUS: data_r <= uart_status;
UART_BAUD: data_r <= uart_baud;
UART_RXDATA: data_r <= uart_rx;
default: data_r <= 32'h0;
endcase
end else begin
data_r <= 32'h0;
end
end
end
assign data_o = data_r;
// *************************** TX ****************************
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= S_IDLE;
end else begin
state <= next_state;
end
end
always @ (*) begin
case (state)
S_IDLE: begin
if (tx_start) begin
next_state = S_START;
end else begin
next_state = S_IDLE;
end
UART_RXDATA: begin
data_o = uart_rx;
end
S_START: begin
if (cycle_cnt == uart_baud[15:0]) begin
next_state = S_SEND_BYTE;
end else begin
next_state = S_START;
end
default: begin
data_o = 32'h0;
end
S_SEND_BYTE: begin
if ((cycle_cnt == uart_baud[15:0]) & (bit_cnt == 4'd7)) begin
next_state = S_STOP;
end else begin
next_state = S_SEND_BYTE;
end
end
S_STOP: begin
if (cycle_cnt == uart_baud[15:0]) begin
next_state = S_IDLE;
end else begin
next_state = S_STOP;
end
end
default: begin
next_state = S_IDLE;
end
endcase
end
// cycle_cnt
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
cycle_cnt <= 16'h0;
end else begin
if (state == S_IDLE) begin
cycle_cnt <= 16'h0;
end else begin
if (cycle_cnt == uart_baud[15:0]) begin
cycle_cnt <= 16'h0;
end else begin
cycle_cnt <= cycle_cnt + 16'h1;
end
end
end
end
// bit_cnt
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
bit_cnt <= 4'h0;
end else begin
case (state)
S_IDLE: begin
bit_cnt <= 4'h0;
end
S_SEND_BYTE: begin
if (cycle_cnt == uart_baud[15:0]) begin
bit_cnt <= bit_cnt + 4'h1;
end
end
endcase
end
end
// *************************** TX ****************************
always @ (posedge clk) begin
if (rst == 1'b0) begin
state <= S_IDLE;
cycle_cnt <= 16'd0;
tx_reg <= 1'b0;
bit_cnt <= 4'd0;
tx_data_ready <= 1'b0;
// tx_bit
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
tx_bit <= 1'b0;
end else begin
if (state == S_IDLE) begin
tx_reg <= 1'b1;
tx_data_ready <= 1'b0;
if (tx_data_valid == 1'b1) begin
state <= S_START;
cycle_cnt <= 16'd0;
bit_cnt <= 4'd0;
tx_reg <= 1'b0;
case (state)
S_IDLE, S_STOP: begin
tx_bit <= 1'b1;
end
end else begin
cycle_cnt <= cycle_cnt + 16'd1;
if (cycle_cnt == uart_baud[15:0]) begin
cycle_cnt <= 16'd0;
case (state)
S_START: begin
tx_reg <= tx_data[bit_cnt];
state <= S_SEND_BYTE;
bit_cnt <= bit_cnt + 4'd1;
end
S_SEND_BYTE: begin
bit_cnt <= bit_cnt + 4'd1;
if (bit_cnt == 4'd8) begin
state <= S_STOP;
tx_reg <= 1'b1;
end else begin
tx_reg <= tx_data[bit_cnt];
end
end
S_STOP: begin
tx_reg <= 1'b1;
state <= S_IDLE;
tx_data_ready <= 1'b1;
end
endcase
S_START: begin
tx_bit <= 1'b0;
end
end
S_SEND_BYTE: begin
tx_bit <= uart_tx[bit_cnt];
end
endcase
end
end
// *************************** RX ****************************
// 沿()
assign rx_negedge = rx_q1 && ~rx_q0;
always @ (posedge clk) begin
if (rst == 1'b0) begin
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
rx_q0 <= 1'b0;
rx_q1 <= 1'b0;
end else begin
@ -222,9 +312,12 @@ module uart(
end
end
//
always @ (posedge clk) begin
if (rst == 1'b0) begin
// 沿()
assign rx_negedge = rx_q1 & (~rx_q0);
//
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
rx_start <= 1'b0;
end else begin
if (uart_ctrl[1]) begin
@ -239,8 +332,8 @@ module uart(
end
end
always @ (posedge clk) begin
if (rst == 1'b0) begin
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
rx_div_cnt <= 16'h0;
end else begin
// 沿
@ -253,15 +346,15 @@ module uart(
end
//
always @ (posedge clk) begin
if (rst == 1'b0) begin
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
rx_clk_cnt <= 16'h0;
end else if (rx_start == 1'b1) begin
//
if (rx_clk_cnt == rx_div_cnt) begin
rx_clk_cnt <= 16'h0;
end else begin
rx_clk_cnt <= rx_clk_cnt + 1'b1;
rx_clk_cnt <= rx_clk_cnt + 16'h1;
end
end else begin
rx_clk_cnt <= 16'h0;
@ -269,8 +362,8 @@ module uart(
end
// 沿
always @ (posedge clk) begin
if (rst == 1'b0) begin
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
rx_clk_edge_cnt <= 4'h0;
rx_clk_edge_level <= 1'b0;
end else if (rx_start == 1'b1) begin
@ -282,7 +375,7 @@ module uart(
rx_clk_edge_level <= 1'b0;
end else begin
// 沿1
rx_clk_edge_cnt <= rx_clk_edge_cnt + 1'b1;
rx_clk_edge_cnt <= rx_clk_edge_cnt + 4'h1;
// 沿
rx_clk_edge_level <= 1'b1;
end
@ -296,8 +389,8 @@ module uart(
end
// bit
always @ (posedge clk) begin
if (rst == 1'b0) begin
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
rx_data <= 8'h0;
rx_over <= 1'b0;
end else begin
@ -309,9 +402,17 @@ module uart(
1: begin
end
//
2, 3, 4, 5, 6, 7, 8, 9: begin
rx_data <= rx_data | (rx_pin << (rx_clk_edge_cnt - 2));
// 1
2: begin
if (rx_pin) begin
rx_data <= 8'h80;
end else begin
rx_data <= 8'h0;
end
end
//
3, 4, 5, 6, 7, 8, 9: begin
rx_data <= {rx_pin, rx_data[7:1]};
//
if (rx_clk_edge_cnt == 4'h9) begin
rx_over <= 1'b1;
@ -326,4 +427,15 @@ module uart(
end
end
vld_rdy #(
.CUT_READY(0)
) u_vld_rdy(
.clk(clk),
.rst_n(rst_n),
.vld_i(req_valid_i),
.rdy_o(req_ready_o),
.rdy_i(rsp_ready_i),
.vld_o(rsp_valid_o)
);
endmodule

View File

@ -1,363 +0,0 @@
/*
Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "../core/defines.v"
// tinyriscv soc
module tinyriscv_soc_top(
input wire clk,
input wire rst,
output reg over, //
output reg succ, //
output wire halted_ind, // jtaghaltCPU
input wire uart_debug_pin, // 使
output wire uart_tx_pin, // UART
input wire uart_rx_pin, // UART
inout wire[1:0] gpio, // GPIO
input wire jtag_TCK, // JTAG TCK
input wire jtag_TMS, // JTAG TMS
input wire jtag_TDI, // JTAG TDI
output wire jtag_TDO, // JTAG TDO
input wire spi_miso, // SPI MISO
output wire spi_mosi, // SPI MOSI
output wire spi_ss, // SPI SS
output wire spi_clk // SPI CLK
);
// master 0 interface
wire[`MemAddrBus] m0_addr_i;
wire[`MemBus] m0_data_i;
wire[`MemBus] m0_data_o;
wire m0_req_i;
wire m0_we_i;
// master 1 interface
wire[`MemAddrBus] m1_addr_i;
wire[`MemBus] m1_data_i;
wire[`MemBus] m1_data_o;
wire m1_req_i;
wire m1_we_i;
// master 2 interface
wire[`MemAddrBus] m2_addr_i;
wire[`MemBus] m2_data_i;
wire[`MemBus] m2_data_o;
wire m2_req_i;
wire m2_we_i;
// master 3 interface
wire[`MemAddrBus] m3_addr_i;
wire[`MemBus] m3_data_i;
wire[`MemBus] m3_data_o;
wire m3_req_i;
wire m3_we_i;
// slave 0 interface
wire[`MemAddrBus] s0_addr_o;
wire[`MemBus] s0_data_o;
wire[`MemBus] s0_data_i;
wire s0_we_o;
// slave 1 interface
wire[`MemAddrBus] s1_addr_o;
wire[`MemBus] s1_data_o;
wire[`MemBus] s1_data_i;
wire s1_we_o;
// slave 2 interface
wire[`MemAddrBus] s2_addr_o;
wire[`MemBus] s2_data_o;
wire[`MemBus] s2_data_i;
wire s2_we_o;
// slave 3 interface
wire[`MemAddrBus] s3_addr_o;
wire[`MemBus] s3_data_o;
wire[`MemBus] s3_data_i;
wire s3_we_o;
// slave 4 interface
wire[`MemAddrBus] s4_addr_o;
wire[`MemBus] s4_data_o;
wire[`MemBus] s4_data_i;
wire s4_we_o;
// slave 5 interface
wire[`MemAddrBus] s5_addr_o;
wire[`MemBus] s5_data_o;
wire[`MemBus] s5_data_i;
wire s5_we_o;
// rib
wire rib_hold_flag_o;
// jtag
wire jtag_halt_req_o;
wire jtag_reset_req_o;
wire[`RegAddrBus] jtag_reg_addr_o;
wire[`RegBus] jtag_reg_data_o;
wire jtag_reg_we_o;
wire[`RegBus] jtag_reg_data_i;
// tinyriscv
wire[`INT_BUS] int_flag;
// timer0
wire timer0_int;
// gpio
wire[1:0] io_in;
wire[31:0] gpio_ctrl;
wire[31:0] gpio_data;
assign int_flag = {7'h0, timer0_int};
// LED
// haltCPU
assign halted_ind = ~jtag_halt_req_o;
always @ (posedge clk) begin
if (rst == `RstEnable) begin
over <= 1'b1;
succ <= 1'b1;
end else begin
over <= ~u_tinyriscv.u_regs.regs[26]; // when = 1, run over
succ <= ~u_tinyriscv.u_regs.regs[27]; // when = 1, run succ, otherwise fail
end
end
// tinyriscv
tinyriscv u_tinyriscv(
.clk(clk),
.rst(rst),
.rib_ex_addr_o(m0_addr_i),
.rib_ex_data_i(m0_data_o),
.rib_ex_data_o(m0_data_i),
.rib_ex_req_o(m0_req_i),
.rib_ex_we_o(m0_we_i),
.rib_pc_addr_o(m1_addr_i),
.rib_pc_data_i(m1_data_o),
.jtag_reg_addr_i(jtag_reg_addr_o),
.jtag_reg_data_i(jtag_reg_data_o),
.jtag_reg_we_i(jtag_reg_we_o),
.jtag_reg_data_o(jtag_reg_data_i),
.rib_hold_flag_i(rib_hold_flag_o),
.jtag_halt_flag_i(jtag_halt_req_o),
.jtag_reset_flag_i(jtag_reset_req_o),
.int_i(int_flag)
);
// rom
rom u_rom(
.clk(clk),
.rst(rst),
.we_i(s0_we_o),
.addr_i(s0_addr_o),
.data_i(s0_data_o),
.data_o(s0_data_i)
);
// ram
ram u_ram(
.clk(clk),
.rst(rst),
.we_i(s1_we_o),
.addr_i(s1_addr_o),
.data_i(s1_data_o),
.data_o(s1_data_i)
);
// timer
timer timer_0(
.clk(clk),
.rst(rst),
.data_i(s2_data_o),
.addr_i(s2_addr_o),
.we_i(s2_we_o),
.data_o(s2_data_i),
.int_sig_o(timer0_int)
);
// uart
uart uart_0(
.clk(clk),
.rst(rst),
.we_i(s3_we_o),
.addr_i(s3_addr_o),
.data_i(s3_data_o),
.data_o(s3_data_i),
.tx_pin(uart_tx_pin),
.rx_pin(uart_rx_pin)
);
// io0
assign gpio[0] = (gpio_ctrl[1:0] == 2'b01)? gpio_data[0]: 1'bz;
assign io_in[0] = gpio[0];
// io1
assign gpio[1] = (gpio_ctrl[3:2] == 2'b01)? gpio_data[1]: 1'bz;
assign io_in[1] = gpio[1];
// gpio
gpio gpio_0(
.clk(clk),
.rst(rst),
.we_i(s4_we_o),
.addr_i(s4_addr_o),
.data_i(s4_data_o),
.data_o(s4_data_i),
.io_pin_i(io_in),
.reg_ctrl(gpio_ctrl),
.reg_data(gpio_data)
);
// spi
spi spi_0(
.clk(clk),
.rst(rst),
.data_i(s5_data_o),
.addr_i(s5_addr_o),
.we_i(s5_we_o),
.data_o(s5_data_i),
.spi_mosi(spi_mosi),
.spi_miso(spi_miso),
.spi_ss(spi_ss),
.spi_clk(spi_clk)
);
// rib
rib u_rib(
.clk(clk),
.rst(rst),
// master 0 interface
.m0_addr_i(m0_addr_i),
.m0_data_i(m0_data_i),
.m0_data_o(m0_data_o),
.m0_req_i(m0_req_i),
.m0_we_i(m0_we_i),
// master 1 interface
.m1_addr_i(m1_addr_i),
.m1_data_i(`ZeroWord),
.m1_data_o(m1_data_o),
.m1_req_i(`RIB_REQ),
.m1_we_i(`WriteDisable),
// master 2 interface
.m2_addr_i(m2_addr_i),
.m2_data_i(m2_data_i),
.m2_data_o(m2_data_o),
.m2_req_i(m2_req_i),
.m2_we_i(m2_we_i),
// master 3 interface
.m3_addr_i(m3_addr_i),
.m3_data_i(m3_data_i),
.m3_data_o(m3_data_o),
.m3_req_i(m3_req_i),
.m3_we_i(m3_we_i),
// slave 0 interface
.s0_addr_o(s0_addr_o),
.s0_data_o(s0_data_o),
.s0_data_i(s0_data_i),
.s0_we_o(s0_we_o),
// slave 1 interface
.s1_addr_o(s1_addr_o),
.s1_data_o(s1_data_o),
.s1_data_i(s1_data_i),
.s1_we_o(s1_we_o),
// slave 2 interface
.s2_addr_o(s2_addr_o),
.s2_data_o(s2_data_o),
.s2_data_i(s2_data_i),
.s2_we_o(s2_we_o),
// slave 3 interface
.s3_addr_o(s3_addr_o),
.s3_data_o(s3_data_o),
.s3_data_i(s3_data_i),
.s3_we_o(s3_we_o),
// slave 4 interface
.s4_addr_o(s4_addr_o),
.s4_data_o(s4_data_o),
.s4_data_i(s4_data_i),
.s4_we_o(s4_we_o),
// slave 5 interface
.s5_addr_o(s5_addr_o),
.s5_data_o(s5_data_o),
.s5_data_i(s5_data_i),
.s5_we_o(s5_we_o),
.hold_flag_o(rib_hold_flag_o)
);
//
uart_debug u_uart_debug(
.clk(clk),
.rst(rst),
.debug_en_i(uart_debug_pin),
.req_o(m3_req_i),
.mem_we_o(m3_we_i),
.mem_addr_o(m3_addr_i),
.mem_wdata_o(m3_data_i),
.mem_rdata_i(m3_data_o)
);
// jtag
jtag_top #(
.DMI_ADDR_BITS(6),
.DMI_DATA_BITS(32),
.DMI_OP_BITS(2)
) u_jtag_top(
.clk(clk),
.jtag_rst_n(rst),
.jtag_pin_TCK(jtag_TCK),
.jtag_pin_TMS(jtag_TMS),
.jtag_pin_TDI(jtag_TDI),
.jtag_pin_TDO(jtag_TDO),
.reg_we_o(jtag_reg_we_o),
.reg_addr_o(jtag_reg_addr_o),
.reg_wdata_o(jtag_reg_data_o),
.reg_rdata_i(jtag_reg_data_i),
.mem_we_o(m2_we_i),
.mem_addr_o(m2_addr_i),
.mem_wdata_o(m2_data_i),
.mem_rdata_i(m2_data_o),
.op_req_o(m2_req_i),
.halt_req_o(jtag_halt_req_o),
.reset_req_o(jtag_reset_req_o)
);
endmodule

373
rtl/sys_bus/rib.v Normal file
View File

@ -0,0 +1,373 @@
/*
Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// RIB线
module rib #(
parameter MASTER_NUM = 3,
parameter SLAVE_NUM = 2)(
input wire clk,
input wire rst_n,
// master 0 interface
input wire[31:0] m0_addr_i,
input wire[31:0] m0_data_i,
input wire[3:0] m0_sel_i,
input wire m0_req_vld_i,
input wire m0_rsp_rdy_i,
input wire m0_we_i,
output wire m0_req_rdy_o,
output wire m0_rsp_vld_o,
output wire[31:0] m0_data_o,
// master 1 interface
input wire[31:0] m1_addr_i,
input wire[31:0] m1_data_i,
input wire[3:0] m1_sel_i,
input wire m1_req_vld_i,
input wire m1_rsp_rdy_i,
input wire m1_we_i,
output wire m1_req_rdy_o,
output wire m1_rsp_vld_o,
output wire[31:0] m1_data_o,
// master 2 interface
input wire[31:0] m2_addr_i,
input wire[31:0] m2_data_i,
input wire[3:0] m2_sel_i,
input wire m2_req_vld_i,
input wire m2_rsp_rdy_i,
input wire m2_we_i,
output wire m2_req_rdy_o,
output wire m2_rsp_vld_o,
output wire[31:0] m2_data_o,
// master 3 interface
input wire[31:0] m3_addr_i,
input wire[31:0] m3_data_i,
input wire[3:0] m3_sel_i,
input wire m3_req_vld_i,
input wire m3_rsp_rdy_i,
input wire m3_we_i,
output wire m3_req_rdy_o,
output wire m3_rsp_vld_o,
output wire[31:0] m3_data_o,
// slave 0 interface
input wire[31:0] s0_data_i,
input wire s0_req_rdy_i,
input wire s0_rsp_vld_i,
output wire[31:0] s0_addr_o,
output wire[31:0] s0_data_o,
output wire[3:0] s0_sel_o,
output wire s0_req_vld_o,
output wire s0_rsp_rdy_o,
output wire s0_we_o,
// slave 1 interface
input wire[31:0] s1_data_i,
input wire s1_req_rdy_i,
input wire s1_rsp_vld_i,
output wire[31:0] s1_addr_o,
output wire[31:0] s1_data_o,
output wire[3:0] s1_sel_o,
output wire s1_req_vld_o,
output wire s1_rsp_rdy_o,
output wire s1_we_o,
// slave 2 interface
input wire[31:0] s2_data_i,
input wire s2_req_rdy_i,
input wire s2_rsp_vld_i,
output wire[31:0] s2_addr_o,
output wire[31:0] s2_data_o,
output wire[3:0] s2_sel_o,
output wire s2_req_vld_o,
output wire s2_rsp_rdy_o,
output wire s2_we_o,
// slave 3 interface
input wire[31:0] s3_data_i,
input wire s3_req_rdy_i,
input wire s3_rsp_vld_i,
output wire[31:0] s3_addr_o,
output wire[31:0] s3_data_o,
output wire[3:0] s3_sel_o,
output wire s3_req_vld_o,
output wire s3_rsp_rdy_o,
output wire s3_we_o,
// slave 4 interface
input wire[31:0] s4_data_i,
input wire s4_req_rdy_i,
input wire s4_rsp_vld_i,
output wire[31:0] s4_addr_o,
output wire[31:0] s4_data_o,
output wire[3:0] s4_sel_o,
output wire s4_req_vld_o,
output wire s4_rsp_rdy_o,
output wire s4_we_o
);
/////////////////////////////// mux master //////////////////////////////
wire[MASTER_NUM-1:0] master_req;
wire[31:0] master_addr[MASTER_NUM-1:0];
wire[31:0] master_data[MASTER_NUM-1:0];
wire[3:0] master_sel[MASTER_NUM-1:0];
wire[MASTER_NUM-1:0] master_rsp_rdy;
wire[MASTER_NUM-1:0] master_we;
genvar i;
generate
if (MASTER_NUM == 2) begin: if_m_num_2
assign master_req = {m0_req_vld_i, m1_req_vld_i};
assign master_rsp_rdy = {m0_rsp_rdy_i, m1_rsp_rdy_i};
assign master_we = {m0_we_i, m1_we_i};
wire[32*MASTER_NUM-1:0] m_addr = {m0_addr_i, m1_addr_i};
wire[32*MASTER_NUM-1:0] m_data = {m0_data_i, m1_data_i};
wire[4*MASTER_NUM-1:0] m_sel = {m0_sel_i, m1_sel_i};
for (i = 0; i < MASTER_NUM; i = i + 1) begin: for_m_num_2
assign master_addr[i] = m_addr[(i+1)*32-1:32*i];
assign master_data[i] = m_data[(i+1)*32-1:32*i];
assign master_sel[i] = m_sel[(i+1)*4-1:4*i];
end
end
if (MASTER_NUM == 3) begin: if_m_num_3
assign master_req = {m0_req_vld_i, m1_req_vld_i, m2_req_vld_i};
assign master_rsp_rdy = {m0_rsp_rdy_i, m1_rsp_rdy_i, m2_rsp_rdy_i};
assign master_we = {m0_we_i, m1_we_i, m2_we_i};
wire[32*MASTER_NUM-1:0] m_addr = {m0_addr_i, m1_addr_i, m2_addr_i};
wire[32*MASTER_NUM-1:0] m_data = {m0_data_i, m1_data_i, m2_data_i};
wire[4*MASTER_NUM-1:0] m_sel = {m0_sel_i, m1_sel_i, m2_sel_i};
for (i = 0; i < MASTER_NUM; i = i + 1) begin: for_m_num_3
assign master_addr[i] = m_addr[(i+1)*32-1:32*i];
assign master_data[i] = m_data[(i+1)*32-1:32*i];
assign master_sel[i] = m_sel[(i+1)*4-1:4*i];
end
end
if (MASTER_NUM == 4) begin: if_m_num_4
assign master_req = {m0_req_vld_i, m1_req_vld_i, m2_req_vld_i, m3_req_vld_i};
assign master_rsp_rdy = {m0_rsp_rdy_i, m1_rsp_rdy_i, m2_rsp_rdy_i, m3_rsp_rdy_i};
assign master_we = {m0_we_i, m1_we_i, m2_we_i, m3_we_i};
wire[32*MASTER_NUM-1:0] m_addr = {m0_addr_i, m1_addr_i, m2_addr_i, m3_addr_i};
wire[32*MASTER_NUM-1:0] m_data = {m0_data_i, m1_data_i, m2_data_i, m3_data_i};
wire[4*MASTER_NUM-1:0] m_sel = {m0_sel_i, m1_sel_i, m2_sel_i, m3_sel_i};
for (i = 0; i < MASTER_NUM; i = i + 1) begin: for_m_num_4
assign master_addr[i] = m_addr[(i+1)*32-1:32*i];
assign master_data[i] = m_data[(i+1)*32-1:32*i];
assign master_sel[i] = m_sel[(i+1)*4-1:4*i];
end
end
wire[MASTER_NUM-1:0] master_req_vec;
wire[MASTER_NUM-1:0] master_sel_vec;
// LSBMSB
for (i = 0; i < MASTER_NUM; i = i + 1) begin: m_arb
if (i == 0) begin: m_is_0
assign master_req_vec[i] = 1'b1;
end else begin: m_is_not_0
assign master_req_vec[i] = ~(|master_req[i-1:0]);
end
assign master_sel_vec[i] = master_req_vec[i] & master_req[i];
end
reg[31:0] mux_m_addr;
reg[31:0] mux_m_data;
reg[3:0] mux_m_sel;
reg mux_m_req_vld;
reg mux_m_rsp_rdy;
reg mux_m_we;
integer j;
always @ (*) begin: m_out
mux_m_addr = 32'h0;
mux_m_data = 32'h0;
mux_m_sel = 4'h0;
mux_m_req_vld = 1'b0;
mux_m_rsp_rdy = 1'b0;
mux_m_we = 1'b0;
for (j = 0; j < MASTER_NUM; j = j + 1) begin: m_sig_out
mux_m_addr = mux_m_addr | ({32{master_sel_vec[j]}} & master_addr[j]);
mux_m_data = mux_m_data | ({32{master_sel_vec[j]}} & master_data[j]);
mux_m_sel = mux_m_sel | ({4 {master_sel_vec[j]}} & master_sel[j]);
mux_m_req_vld = mux_m_req_vld | ({1 {master_sel_vec[j]}} & master_req[j]);
mux_m_rsp_rdy = mux_m_rsp_rdy | ({1 {master_sel_vec[j]}} & master_rsp_rdy[j]);
mux_m_we = mux_m_we | ({1 {master_sel_vec[j]}} & master_we[j]);
end
end
/////////////////////////////// mux slave /////////////////////////////////
wire[SLAVE_NUM-1:0] slave_sel;
// 访4访
// 16
for (i = 0; i < SLAVE_NUM; i = i + 1) begin: s_sel
assign slave_sel[i] = (mux_m_addr[31:28] == i);
end
wire[SLAVE_NUM-1:0] slave_req_rdy;
wire[SLAVE_NUM-1:0] slave_rsp_vld;
wire[31:0] slave_data[SLAVE_NUM-1:0];
if (SLAVE_NUM == 2) begin: if_s_num_2
assign slave_req_rdy = {s1_req_rdy_i, s0_req_rdy_i};
assign slave_rsp_vld = {s1_rsp_vld_i, s0_rsp_vld_i};
wire[32*SLAVE_NUM-1:0] s_data = {s1_data_i, s0_data_i};
for (i = 0; i < SLAVE_NUM; i = i + 1) begin: for_s_num_2
assign slave_data[i] = s_data[(i+1)*32-1:32*i];
end
end
if (SLAVE_NUM == 3) begin: if_s_num_3
assign slave_req_rdy = {s2_req_rdy_i, s1_req_rdy_i, s0_req_rdy_i};
assign slave_rsp_vld = {s2_rsp_vld_i, s1_rsp_vld_i, s0_rsp_vld_i};
wire[32*SLAVE_NUM-1:0] s_data = {s2_data_i, s1_data_i, s0_data_i};
for (i = 0; i < SLAVE_NUM; i = i + 1) begin: for_s_num_3
assign slave_data[i] = s_data[(i+1)*32-1:32*i];
end
end
if (SLAVE_NUM == 4) begin: if_s_num_4
assign slave_req_rdy = {s3_req_rdy_i, s2_req_rdy_i, s1_req_rdy_i, s0_req_rdy_i};
assign slave_rsp_vld = {s3_rsp_vld_i, s2_rsp_vld_i, s1_rsp_vld_i, s0_rsp_vld_i};
wire[32*SLAVE_NUM-1:0] s_data = {s3_data_i, s2_data_i, s1_data_i, s0_data_i};
for (i = 0; i < SLAVE_NUM; i = i + 1) begin: for_s_num_4
assign slave_data[i] = s_data[(i+1)*32-1:32*i];
end
end
if (SLAVE_NUM == 5) begin: if_s_num_5
assign slave_req_rdy = {s4_req_rdy_i, s3_req_rdy_i, s2_req_rdy_i, s1_req_rdy_i, s0_req_rdy_i};
assign slave_rsp_vld = {s4_rsp_vld_i, s3_rsp_vld_i, s2_rsp_vld_i, s1_rsp_vld_i, s0_rsp_vld_i};
wire[32*SLAVE_NUM-1:0] s_data = {s4_data_i, s3_data_i, s2_data_i, s1_data_i, s0_data_i};
for (i = 0; i < SLAVE_NUM; i = i + 1) begin: for_s_num_5
assign slave_data[i] = s_data[(i+1)*32-1:32*i];
end
end
reg[31:0] mux_s_data;
reg mux_s_req_rdy;
reg mux_s_rsp_vld;
always @ (*) begin: s_out
mux_s_data = 32'h0;
mux_s_req_rdy = 1'b0;
mux_s_rsp_vld = 1'b0;
for (j = 0; j < SLAVE_NUM; j = j + 1) begin: s_sig_out
mux_s_data = mux_s_data | ({32{slave_sel[j]}} & slave_data[j]);
mux_s_req_rdy = mux_s_req_rdy | ({1 {slave_sel[j]}} & slave_req_rdy[j]);
mux_s_rsp_vld = mux_s_rsp_vld | ({1 {slave_sel[j]}} & slave_rsp_vld[j]);
end
end
/////////////////////////////// demux master //////////////////////////////
wire[MASTER_NUM-1:0] demux_m_req_rdy;
wire[MASTER_NUM-1:0] demux_m_rsp_vld;
wire[32*MASTER_NUM-1:0] demux_m_data;
for (i = 0; i < MASTER_NUM; i = i + 1) begin: demux_m_sig
assign demux_m_req_rdy[i] = {1 {master_sel_vec[i]}} & mux_s_req_rdy;
assign demux_m_rsp_vld[i] = {1 {master_sel_vec[i]}} & mux_s_rsp_vld;
assign demux_m_data[(i+1)*32-1:32*i] = {32{master_sel_vec[i]}} & mux_s_data;
end
if (MASTER_NUM == 2) begin: demux_m_sig_2
assign {m0_req_rdy_o, m1_req_rdy_o} = demux_m_req_rdy;
assign {m0_rsp_vld_o, m1_rsp_vld_o} = demux_m_rsp_vld;
assign {m0_data_o, m1_data_o} = demux_m_data;
end
if (MASTER_NUM == 3) begin: demux_m_sig_3
assign {m0_req_rdy_o, m1_req_rdy_o, m2_req_rdy_o} = demux_m_req_rdy;
assign {m0_rsp_vld_o, m1_rsp_vld_o, m2_rsp_vld_o} = demux_m_rsp_vld;
assign {m0_data_o, m1_data_o, m2_data_o} = demux_m_data;
end
if (MASTER_NUM == 4) begin: demux_m_sig_4
assign {m0_req_rdy_o, m1_req_rdy_o, m2_req_rdy_o, m3_req_rdy_o} = demux_m_req_rdy;
assign {m0_rsp_vld_o, m1_rsp_vld_o, m2_rsp_vld_o, m3_rsp_vld_o} = demux_m_rsp_vld;
assign {m0_data_o, m1_data_o, m2_data_o, m3_data_o} = demux_m_data;
end
/////////////////////////////// demux slave //////////////////////////////
wire[32*SLAVE_NUM-1:0] demux_s_addr;
wire[32*SLAVE_NUM-1:0] demux_s_data;
wire[4*SLAVE_NUM-1:0] demux_s_sel;
wire[SLAVE_NUM-1:0] demux_s_req_vld;
wire[SLAVE_NUM-1:0] demux_s_rsp_rdy;
wire[SLAVE_NUM-1:0] demux_s_we;
for (i = 0; i < SLAVE_NUM; i = i + 1) begin: demux_s_sig
// offset
assign demux_s_addr[(i+1)*32-1:32*i] = {32{slave_sel[i]}} & {4'h0, mux_m_addr[27:0]};
assign demux_s_data[(i+1)*32-1:32*i] = {32{slave_sel[i]}} & mux_m_data;
assign demux_s_sel[(i+1)*4-1:4*i] = {4 {slave_sel[i]}} & mux_m_sel;
assign demux_s_req_vld[i] = {1 {slave_sel[i]}} & mux_m_req_vld;
assign demux_s_rsp_rdy[i] = {1 {slave_sel[i]}} & mux_m_rsp_rdy;
assign demux_s_we[i] = {1 {slave_sel[i]}} & mux_m_we;
end
if (SLAVE_NUM == 2) begin: demux_s_sig_2
assign {s1_addr_o, s0_addr_o} = demux_s_addr;
assign {s1_data_o, s0_data_o} = demux_s_data;
assign {s1_sel_o, s0_sel_o} = demux_s_sel;
assign {s1_req_vld_o, s0_req_vld_o} = demux_s_req_vld;
assign {s1_rsp_rdy_o, s0_rsp_rdy_o} = demux_s_rsp_rdy;
assign {s1_we_o, s0_we_o} = demux_s_we;
end
if (SLAVE_NUM == 3) begin: demux_s_sig_3
assign {s2_addr_o, s1_addr_o, s0_addr_o} = demux_s_addr;
assign {s2_data_o, s1_data_o, s0_data_o} = demux_s_data;
assign {s2_sel_o, s1_sel_o, s0_sel_o} = demux_s_sel;
assign {s2_req_vld_o, s1_req_vld_o, s0_req_vld_o} = demux_s_req_vld;
assign {s2_rsp_rdy_o, s1_rsp_rdy_o, s0_rsp_rdy_o} = demux_s_rsp_rdy;
assign {s2_we_o, s1_we_o, s0_we_o} = demux_s_we;
end
if (SLAVE_NUM == 4) begin: demux_s_sig_4
assign {s3_addr_o, s2_addr_o, s1_addr_o, s0_addr_o} = demux_s_addr;
assign {s3_data_o, s2_data_o, s1_data_o, s0_data_o} = demux_s_data;
assign {s3_sel_o, s2_sel_o, s1_sel_o, s0_sel_o} = demux_s_sel;
assign {s3_req_vld_o, s2_req_vld_o, s1_req_vld_o, s0_req_vld_o} = demux_s_req_vld;
assign {s3_rsp_rdy_o, s2_rsp_rdy_o, s1_rsp_rdy_o, s0_rsp_rdy_o} = demux_s_rsp_rdy;
assign {s3_we_o, s2_we_o, s1_we_o, s0_we_o} = demux_s_we;
end
if (SLAVE_NUM == 5) begin: demux_s_sig_5
assign {s4_addr_o, s3_addr_o, s2_addr_o, s1_addr_o, s0_addr_o} = demux_s_addr;
assign {s4_data_o, s3_data_o, s2_data_o, s1_data_o, s0_data_o} = demux_s_data;
assign {s4_sel_o, s3_sel_o, s2_sel_o, s1_sel_o, s0_sel_o} = demux_s_sel;
assign {s4_req_vld_o, s3_req_vld_o, s2_req_vld_o, s1_req_vld_o, s0_req_vld_o} = demux_s_req_vld;
assign {s4_rsp_rdy_o, s3_rsp_rdy_o, s2_rsp_rdy_o, s1_rsp_rdy_o, s0_rsp_rdy_o} = demux_s_rsp_rdy;
assign {s4_we_o, s3_we_o, s2_we_o, s1_we_o, s0_we_o} = demux_s_we;
end
endgenerate
endmodule

434
rtl/top/tinyriscv_soc_top.v Normal file
View File

@ -0,0 +1,434 @@
/*
Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "../core/defines.v"
// tinyriscv soc
module tinyriscv_soc_top(
input wire clk,
input wire rst_ext_i,
output wire halted_ind, // jtaghaltCPU
output wire uart_tx_pin, // UART
input wire uart_rx_pin, // UART
inout wire[1:0] gpio, // GPIO
input wire jtag_TCK, // JTAG TCK
input wire jtag_TMS, // JTAG TMS
input wire jtag_TDI, // JTAG TDI
output wire jtag_TDO // JTAG TDO
);
// master 0 interface
wire[31:0] m0_addr_i;
wire[31:0] m0_data_i;
wire[3:0] m0_sel_i;
wire m0_req_vld_i;
wire m0_rsp_rdy_i;
wire m0_we_i;
wire m0_req_rdy_o;
wire m0_rsp_vld_o;
wire[31:0] m0_data_o;
// master 1 interface
wire[31:0] m1_addr_i;
wire[31:0] m1_data_i;
wire[3:0] m1_sel_i;
wire m1_req_vld_i;
wire m1_rsp_rdy_i;
wire m1_we_i;
wire m1_req_rdy_o;
wire m1_rsp_vld_o;
wire[31:0] m1_data_o;
// master 2 interface
wire[31:0] m2_addr_i;
wire[31:0] m2_data_i;
wire[3:0] m2_sel_i;
wire m2_req_vld_i;
wire m2_rsp_rdy_i;
wire m2_we_i;
wire m2_req_rdy_o;
wire m2_rsp_vld_o;
wire[31:0] m2_data_o;
// master 3 interface
wire[31:0] m3_addr_i;
wire[31:0] m3_data_i;
wire[3:0] m3_sel_i;
wire m3_req_vld_i;
wire m3_rsp_rdy_i;
wire m3_we_i;
wire m3_req_rdy_o;
wire m3_rsp_vld_o;
wire[31:0] m3_data_o;
// slave 0 interface
wire[31:0] s0_data_i;
wire s0_req_rdy_i;
wire s0_rsp_vld_i;
wire[31:0] s0_addr_o;
wire[31:0] s0_data_o;
wire[3:0] s0_sel_o;
wire s0_req_vld_o;
wire s0_rsp_rdy_o;
wire s0_we_o;
// slave 1 interface
wire[31:0] s1_data_i;
wire s1_req_rdy_i;
wire s1_rsp_vld_i;
wire[31:0] s1_addr_o;
wire[31:0] s1_data_o;
wire[3:0] s1_sel_o;
wire s1_req_vld_o;
wire s1_rsp_rdy_o;
wire s1_we_o;
// slave 2 interface
wire[31:0] s2_data_i;
wire s2_req_rdy_i;
wire s2_rsp_vld_i;
wire[31:0] s2_addr_o;
wire[31:0] s2_data_o;
wire[3:0] s2_sel_o;
wire s2_req_vld_o;
wire s2_rsp_rdy_o;
wire s2_we_o;
// slave 3 interface
wire[31:0] s3_data_i;
wire s3_req_rdy_i;
wire s3_rsp_vld_i;
wire[31:0] s3_addr_o;
wire[31:0] s3_data_o;
wire[3:0] s3_sel_o;
wire s3_req_vld_o;
wire s3_rsp_rdy_o;
wire s3_we_o;
// slave 4 interface
wire[31:0] s4_data_i;
wire s4_req_rdy_i;
wire s4_rsp_vld_i;
wire[31:0] s4_addr_o;
wire[31:0] s4_data_o;
wire[3:0] s4_sel_o;
wire s4_req_vld_o;
wire s4_rsp_rdy_o;
wire s4_we_o;
// jtag
wire jtag_halt_req_o;
wire jtag_reset_req_o;
wire[4:0] jtag_reg_addr_o;
wire[31:0] jtag_reg_data_o;
wire jtag_reg_we_o;
wire[31:0] jtag_reg_data_i;
// tinyriscv
wire[`INT_WIDTH-1:0] int_flag;
wire rst_n;
wire jtag_rst_n;
// timer0
wire timer0_int;
// gpio
wire[1:0] io_in;
wire[31:0] gpio_ctrl;
wire[31:0] gpio_data;
assign int_flag = {{(`INT_WIDTH-1){1'b0}}, timer0_int};
//
rst_ctrl u_rst_ctrl(
.clk(clk),
.rst_ext_i(rst_ext_i),
.rst_jtag_i(jtag_reset_req_o),
.core_rst_n_o(rst_n),
.jtag_rst_n_o(jtag_rst_n)
);
// LED
// haltCPU
assign halted_ind = ~jtag_halt_req_o;
// tinyriscv
tinyriscv_core u_tinyriscv_core(
.clk(clk),
.rst_n(rst_n),
// 线
.ibus_addr_o(m0_addr_i),
.ibus_data_i(m0_data_o),
.ibus_data_o(m0_data_i),
.ibus_we_o(m0_we_i),
.ibus_sel_o(m0_sel_i),
.ibus_req_valid_o(m0_req_vld_i),
.ibus_req_ready_i(m0_req_rdy_o),
.ibus_rsp_valid_i(m0_rsp_vld_o),
.ibus_rsp_ready_o(m0_rsp_rdy_i),
// 线
.dbus_addr_o(m1_addr_i),
.dbus_data_i(m1_data_o),
.dbus_data_o(m1_data_i),
.dbus_we_o(m1_we_i),
.dbus_sel_o(m1_sel_i),
.dbus_req_valid_o(m1_req_vld_i),
.dbus_req_ready_i(m1_req_rdy_o),
.dbus_rsp_valid_i(m1_rsp_vld_o),
.dbus_rsp_ready_o(m1_rsp_rdy_i),
.jtag_halt_i(jtag_halt_req_o),
.int_i(int_flag)
);
//
rom #(
.DP(`ROM_DEPTH)
) u_rom(
.clk(clk),
.rst_n(rst_n),
.addr_i(s0_addr_o),
.data_i(s0_data_o),
.sel_i(s0_sel_o),
.we_i(s0_we_o),
.data_o(s0_data_i),
.req_valid_i(s0_req_vld_o),
.req_ready_o(s0_req_rdy_i),
.rsp_valid_o(s0_rsp_vld_i),
.rsp_ready_i(s0_rsp_rdy_o)
);
//
ram #(
.DP(`RAM_DEPTH)
) u_ram(
.clk(clk),
.rst_n(rst_n),
.addr_i(s1_addr_o),
.data_i(s1_data_o),
.sel_i(s1_sel_o),
.we_i(s1_we_o),
.data_o(s1_data_i),
.req_valid_i(s1_req_vld_o),
.req_ready_o(s1_req_rdy_i),
.rsp_valid_o(s1_rsp_vld_i),
.rsp_ready_i(s1_rsp_rdy_o)
);
// timer
timer timer_0(
.clk(clk),
.rst_n(rst_n),
.addr_i(s2_addr_o),
.data_i(s2_data_o),
.sel_i(s2_sel_o),
.we_i(s2_we_o),
.data_o(s2_data_i),
.req_valid_i(s2_req_vld_o),
.req_ready_o(s2_req_rdy_i),
.rsp_valid_o(s2_rsp_vld_i),
.rsp_ready_i(s2_rsp_rdy_o),
.int_sig_o(timer0_int)
);
// uart
uart uart_0(
.clk(clk),
.rst_n(rst_n),
.addr_i(s3_addr_o),
.data_i(s3_data_o),
.sel_i(s3_sel_o),
.we_i(s3_we_o),
.data_o(s3_data_i),
.req_valid_i(s3_req_vld_o),
.req_ready_o(s3_req_rdy_i),
.rsp_valid_o(s3_rsp_vld_i),
.rsp_ready_i(s3_rsp_rdy_o),
.tx_pin(uart_tx_pin),
.rx_pin(uart_rx_pin)
);
// io0
assign gpio[0] = (gpio_ctrl[1:0] == 2'b01)? gpio_data[0]: 1'bz;
assign io_in[0] = gpio[0];
// io1
assign gpio[1] = (gpio_ctrl[3:2] == 2'b01)? gpio_data[1]: 1'bz;
assign io_in[1] = gpio[1];
// gpio
gpio gpio_0(
.clk(clk),
.rst_n(rst_n),
.addr_i(s4_addr_o),
.data_i(s4_data_o),
.sel_i(s4_sel_o),
.we_i(s4_we_o),
.data_o(s4_data_i),
.req_valid_i(s4_req_vld_o),
.req_ready_o(s4_req_rdy_i),
.rsp_valid_o(s4_rsp_vld_i),
.rsp_ready_i(s4_rsp_rdy_o),
.io_pin_i(io_in),
.reg_ctrl(gpio_ctrl),
.reg_data(gpio_data)
);
// jtag
jtag_top #(
.DMI_ADDR_BITS(6),
.DMI_DATA_BITS(32),
.DMI_OP_BITS(2)
) u_jtag_top(
.clk(clk),
.jtag_rst_n(jtag_rst_n),
.jtag_pin_TCK(jtag_TCK),
.jtag_pin_TMS(jtag_TMS),
.jtag_pin_TDI(jtag_TDI),
.jtag_pin_TDO(jtag_TDO),
.reg_we_o(jtag_reg_we_o),
.reg_addr_o(jtag_reg_addr_o),
.reg_wdata_o(jtag_reg_data_o),
.reg_rdata_i(jtag_reg_data_i),
.mem_we_o(m2_we_i),
.mem_addr_o(m2_addr_i),
.mem_wdata_o(m2_data_i),
.mem_rdata_i(m2_data_o),
.mem_sel_o(m2_sel_i),
.req_valid_o(m2_req_vld_i),
.req_ready_i(m2_req_rdy_o),
.rsp_valid_i(m2_rsp_vld_o),
.rsp_ready_o(m2_rsp_rdy_i),
.halt_req_o(jtag_halt_req_o),
.reset_req_o(jtag_reset_req_o)
);
// rib线
rib #(
.MASTER_NUM(3),
.SLAVE_NUM(5)
) u_rib(
.clk(clk),
.rst_n(rst_n),
// master 0 interface
.m0_addr_i(m0_addr_i),
.m0_data_i(m0_data_i),
.m0_sel_i(m0_sel_i),
.m0_req_vld_i(m0_req_vld_i),
.m0_rsp_rdy_i(m0_rsp_rdy_i),
.m0_we_i(m0_we_i),
.m0_req_rdy_o(m0_req_rdy_o),
.m0_rsp_vld_o(m0_rsp_vld_o),
.m0_data_o(m0_data_o),
// master 1 interface
.m1_addr_i(m1_addr_i),
.m1_data_i(m1_data_i),
.m1_sel_i(m1_sel_i),
.m1_req_vld_i(m1_req_vld_i),
.m1_rsp_rdy_i(m1_rsp_rdy_i),
.m1_we_i(m1_we_i),
.m1_req_rdy_o(m1_req_rdy_o),
.m1_rsp_vld_o(m1_rsp_vld_o),
.m1_data_o(m1_data_o),
// master 2 interface
.m2_addr_i(m2_addr_i),
.m2_data_i(m2_data_i),
.m2_sel_i(m2_sel_i),
.m2_req_vld_i(m2_req_vld_i),
.m2_rsp_rdy_i(m2_rsp_rdy_i),
.m2_we_i(m2_we_i),
.m2_req_rdy_o(m2_req_rdy_o),
.m2_rsp_vld_o(m2_rsp_vld_o),
.m2_data_o(m2_data_o),
// master 3 interface
.m3_addr_i(m3_addr_i),
.m3_data_i(m3_data_i),
.m3_sel_i(m3_sel_i),
.m3_req_vld_i(m3_req_vld_i),
.m3_rsp_rdy_i(m3_rsp_rdy_i),
.m3_we_i(m3_we_i),
.m3_req_rdy_o(m3_req_rdy_o),
.m3_rsp_vld_o(m3_rsp_vld_o),
.m3_data_o(m3_data_o),
// slave 0 interface
.s0_data_i(s0_data_i),
.s0_req_rdy_i(s0_req_rdy_i),
.s0_rsp_vld_i(s0_rsp_vld_i),
.s0_addr_o(s0_addr_o),
.s0_data_o(s0_data_o),
.s0_sel_o(s0_sel_o),
.s0_req_vld_o(s0_req_vld_o),
.s0_rsp_rdy_o(s0_rsp_rdy_o),
.s0_we_o(s0_we_o),
// slave 1 interface
.s1_data_i(s1_data_i),
.s1_req_rdy_i(s1_req_rdy_i),
.s1_rsp_vld_i(s1_rsp_vld_i),
.s1_addr_o(s1_addr_o),
.s1_data_o(s1_data_o),
.s1_sel_o(s1_sel_o),
.s1_req_vld_o(s1_req_vld_o),
.s1_rsp_rdy_o(s1_rsp_rdy_o),
.s1_we_o(s1_we_o),
// slave 2 interface
.s2_data_i(s2_data_i),
.s2_req_rdy_i(s2_req_rdy_i),
.s2_rsp_vld_i(s2_rsp_vld_i),
.s2_addr_o(s2_addr_o),
.s2_data_o(s2_data_o),
.s2_sel_o(s2_sel_o),
.s2_req_vld_o(s2_req_vld_o),
.s2_rsp_rdy_o(s2_rsp_rdy_o),
.s2_we_o(s2_we_o),
// slave 3 interface
.s3_data_i(s3_data_i),
.s3_req_rdy_i(s3_req_rdy_i),
.s3_rsp_vld_i(s3_rsp_vld_i),
.s3_addr_o(s3_addr_o),
.s3_data_o(s3_data_o),
.s3_sel_o(s3_sel_o),
.s3_req_vld_o(s3_req_vld_o),
.s3_rsp_rdy_o(s3_rsp_rdy_o),
.s3_we_o(s3_we_o),
// slave 4 interface
.s4_data_i(s4_data_i),
.s4_req_rdy_i(s4_req_rdy_i),
.s4_rsp_vld_i(s4_rsp_vld_i),
.s4_addr_o(s4_addr_o),
.s4_data_o(s4_data_o),
.s4_sel_o(s4_sel_o),
.s4_req_vld_o(s4_req_vld_o),
.s4_rsp_rdy_o(s4_rsp_rdy_o),
.s4_we_o(s4_we_o)
);
endmodule

View File

@ -19,7 +19,7 @@ module gen_ticks_sync #(
parameter DP = 2,
parameter DW = 32)(
input wire rst,
input wire rst_n,
input wire clk,
input wire[DW-1:0] din,
@ -32,11 +32,11 @@ module gen_ticks_sync #(
genvar i;
generate
for (i = 0; i < DP; i = i + 1) begin: dp_width
for (i = 0; i < DP; i = i + 1) begin: ticks_sync
if (i == 0) begin: dp_is_0
gen_rst_0_dff #(DW) rst_0_dff(clk, rst, din, sync_dat[0]);
gen_rst_0_dff #(DW) rst_0_dff(clk, rst_n, din, sync_dat[0]);
end else begin: dp_is_not_0
gen_rst_0_dff #(DW) rst_0_dff(clk, rst, sync_dat[i-1], sync_dat[i]);
gen_rst_0_dff #(DW) rst_0_dff(clk, rst_n, sync_dat[i-1], sync_dat[i]);
end
end
endgenerate

View File

@ -19,7 +19,7 @@ module gen_pipe_dff #(
parameter DW = 32)(
input wire clk,
input wire rst,
input wire rst_n,
input wire hold_en,
input wire[DW-1:0] def_val,
@ -30,8 +30,8 @@ module gen_pipe_dff #(
reg[DW-1:0] qout_r;
always @ (posedge clk) begin
if (!rst | hold_en) begin
always @ (posedge clk or negedge rst_n) begin
if (!rst_n | hold_en) begin
qout_r <= def_val;
end else begin
qout_r <= din;
@ -47,7 +47,7 @@ module gen_rst_0_dff #(
parameter DW = 32)(
input wire clk,
input wire rst,
input wire rst_n,
input wire[DW-1:0] din,
output wire[DW-1:0] qout
@ -56,8 +56,8 @@ module gen_rst_0_dff #(
reg[DW-1:0] qout_r;
always @ (posedge clk) begin
if (!rst) begin
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
qout_r <= {DW{1'b0}};
end else begin
qout_r <= din;
@ -73,7 +73,7 @@ module gen_rst_1_dff #(
parameter DW = 32)(
input wire clk,
input wire rst,
input wire rst_n,
input wire[DW-1:0] din,
output wire[DW-1:0] qout
@ -82,8 +82,8 @@ module gen_rst_1_dff #(
reg[DW-1:0] qout_r;
always @ (posedge clk) begin
if (!rst) begin
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
qout_r <= {DW{1'b1}};
end else begin
qout_r <= din;
@ -99,7 +99,7 @@ module gen_rst_def_dff #(
parameter DW = 32)(
input wire clk,
input wire rst,
input wire rst_n,
input wire[DW-1:0] def_val,
input wire[DW-1:0] din,
@ -109,8 +109,8 @@ module gen_rst_def_dff #(
reg[DW-1:0] qout_r;
always @ (posedge clk) begin
if (!rst) begin
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
qout_r <= def_val;
end else begin
qout_r <= din;
@ -126,7 +126,33 @@ module gen_en_dff #(
parameter DW = 32)(
input wire clk,
input wire rst,
input wire rst_n,
input wire en,
input wire[DW-1:0] din,
output wire[DW-1:0] qout
);
reg[DW-1:0] qout_r;
always @ (posedge clk or negedge rst_n) begin
if (!rst_n) begin
qout_r <= {DW{1'b0}};
end else if (en == 1'b1) begin
qout_r <= din;
end
end
assign qout = qout_r;
endmodule
// 使
module gen_en_dffnr #(
parameter DW = 32)(
input wire clk,
input wire en,
input wire[DW-1:0] din,
@ -137,9 +163,7 @@ module gen_en_dff #(
reg[DW-1:0] qout_r;
always @ (posedge clk) begin
if (!rst) begin
qout_r <= {DW{1'b0}};
end else if (en == 1'b1) begin
if (en == 1'b1) begin
qout_r <= din;
end
end

72
rtl/utils/gen_ram.v Normal file
View File

@ -0,0 +1,72 @@
/*
Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
`include "../core/defines.v"
module gen_ram #(
parameter DP = 512,
parameter DW = 32,
parameter MW = 4,
parameter AW = 32)(
input wire clk,
input wire[AW-1:0] addr_i,
input wire[DW-1:0] data_i,
input wire[MW-1:0] sel_i,
input wire we_i,
output wire[DW-1:0] data_o
);
reg[DW-1:0] ram [0:DP-1];
reg[AW-1:0] addr_r;
wire[MW-1:0] wen;
wire ren;
assign ren = (~we_i);
assign wen = ({MW{we_i}} & sel_i);
always @ (posedge clk) begin
if (ren) begin
addr_r <= addr_i;
end
end
assign data_o = ram[addr_r];
genvar i;
generate
for (i = 0; i < MW; i = i + 1) begin: sel_width
if ((8 * i + 8) > DW) begin: i_gt_8
always @ (posedge clk) begin: i_gt_8_ff
if (wen[i]) begin: gt_8_wen
ram[addr_i][DW-1:8*i] <= data_i[DW-1:8*i];
end
end
end else begin: i_lt_8
always @ (posedge clk) begin: i_lt_8_ff
if (wen[i]) begin: lt_8_wen
ram[addr_i][8*i+7:8*i] <= data_i[8*i+7:8*i];
end
end
end
end
endgenerate
endmodule

57
rtl/utils/vld_rdy.v Normal file
View File

@ -0,0 +1,57 @@
/*
Copyright 2020 Blue Liang, liangkangnan@163.com
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
module vld_rdy #(
parameter CUT_READY = 0)(
input wire clk,
input wire rst_n,
input wire vld_i,
output wire rdy_o,
input wire rdy_i,
output wire vld_o
);
wire vld_set;
wire vld_clr;
wire vld_ena;
wire vld_r;
wire vld_nxt;
// The valid will be set when input handshaked
assign vld_set = vld_i & rdy_o;
// The valid will be clr when output handshaked
assign vld_clr = vld_o & rdy_i;
assign vld_ena = vld_set | vld_clr;
assign vld_nxt = vld_set | (~vld_clr);
gen_en_dff #(1) vld_dff(clk, rst_n, vld_ena, vld_nxt, vld_r);
assign vld_o = vld_r;
if (CUT_READY == 1) begin
// If cut ready, then only accept when stage is not full
assign rdy_o = (~vld_r);
end else begin
// If not cut ready, then can accept when stage is not full or it is popping
assign rdy_o = (~vld_r) | vld_clr;
end
endmodule

View File

@ -2,6 +2,5 @@
*.o
*.ko
*.obj
gpio.bin
gpio.dump
gpio
*.bin
*.dump

4
sdk/README.md Normal file
View File

@ -0,0 +1,4 @@
**bsp**板级支持包是所有C语言程序的基础公共部分代码
**examples**一些C语言程序例程。

View File

@ -1,4 +1,6 @@
# Object files
*.o
*.ko
*.obj
*.obj
*.bin
*.dump

3
sdk/bsp/README.md Normal file
View File

@ -0,0 +1,3 @@
**include**: 公共头文件目录。
**lib**: 公共函数目录。

View File

@ -1,14 +1,15 @@
RISCV_PATH := $(TOOLCHAIN_DIR)/tools/gnu-mcu-eclipse-riscv-none-gcc-8.2.0-2.2-20190521-0004-win64/
RISCV_TOOLS_PATH := $(TOOLCHAIN_DIR)/tools/gnu-mcu-eclipse-riscv-none-gcc-8.2.0-2.2-20190521-0004-win64/bin
RISCV_TOOLS_PREFIX := riscv-none-embed-
RISCV_GCC := $(abspath $(RISCV_PATH)/bin/riscv-none-embed-gcc)
RISCV_AS := $(abspath $(RISCV_PATH)/bin/riscv-none-embed-as)
RISCV_GXX := $(abspath $(RISCV_PATH)/bin/riscv-none-embed-g++)
RISCV_OBJDUMP := $(abspath $(RISCV_PATH)/bin/riscv-none-embed-objdump)
RISCV_GDB := $(abspath $(RISCV_PATH)/bin/riscv-none-embed-gdb)
RISCV_AR := $(abspath $(RISCV_PATH)/bin/riscv-none-embed-ar)
RISCV_OBJCOPY := $(abspath $(RISCV_PATH)/bin/riscv-none-embed-objcopy)
RISCV_READELF := $(abspath $(RISCV_PATH)/bin/riscv-none-embed-readelf)
RISCV_GCC := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)gcc)
RISCV_AS := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)as)
RISCV_GXX := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)g++)
RISCV_OBJDUMP := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)objdump)
RISCV_GDB := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)gdb)
RISCV_AR := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)ar)
RISCV_OBJCOPY := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)objcopy)
RISCV_READELF := $(abspath $(RISCV_TOOLS_PATH)/$(RISCV_TOOLS_PREFIX)readelf)
.PHONY: all
all: $(TARGET)
@ -20,8 +21,6 @@ C_SRCS += $(COMMON_DIR)/trap_handler.c
C_SRCS += $(COMMON_DIR)/lib/utils.c
C_SRCS += $(COMMON_DIR)/lib/xprintf.c
C_SRCS += $(COMMON_DIR)/lib/uart.c
C_SRCS += $(COMMON_DIR)/lib/flash_n25q.c
C_SRCS += $(COMMON_DIR)/lib/spi.c
LINKER_SCRIPT := $(COMMON_DIR)/link.lds

View File

@ -0,0 +1,19 @@
#ifndef _TRAP_CODE_H_
#define _TRAP_CODE_H_
#define TRAP_USER_SW (0x80000000)
#define TRAP_MACH_SW (0x80000003)
#define TRAP_USER_TIMER (0x80000004)
#define TRAP_MACH_TIMER (0x80000007)
#define TRAP_USER_EXT (0x80000008)
#define TRAP_MACH_EXT (0x8000000B)
#define TRAP_INST_ADDR_MISA (0x00000000)
#define TRAP_ILLEGAL_INST (0x00000002)
#define TRAP_BREAKPOINT (0x00000003)
#define TRAP_LOAD_ADDR_MISA (0x00000004)
#define TRAP_STORE_ADDR_MISA (0x00000006)
#define TRAP_ECALL_U (0x00000008)
#define TRAP_ECALL_S (0x00000009)
#define TRAP_ECALL_M (0x0000000B)
#endif

View File

@ -1,4 +1,6 @@
# Object files
*.o
*.ko
*.obj
*.obj
*.bin
*.dump

View File

@ -4,7 +4,7 @@ ENTRY(_start)
MEMORY
{
flash (wxa!ri) : ORIGIN = 0x00000000, LENGTH = 16K
flash (wxa!ri) : ORIGIN = 0x00000000, LENGTH = 32K
ram (wxa!ri) : ORIGIN = 0x10000000, LENGTH = 16K
}

View File

@ -50,10 +50,11 @@ test_if_asynchronous:
srli a2, a0, 31 /* MSB of mcause is 1 if handing an asynchronous interrupt - shift to LSB to clear other bits. */
beq a2, x0, handle_synchronous /* Branch past interrupt handing if not asynchronous. */
call trap_handler
call interrupt_handler
j asynchronous_return
handle_synchronous:
call exception_handler
addi a1, a1, 4
csrw mepc, a1
@ -97,7 +98,12 @@ asynchronous_return:
mret
.weak trap_handler
trap_handler:
.weak interrupt_handler
interrupt_handler:
1:
j 1b
.weak exception_handler
exception_handler:
2:
j 2b

18
sdk/bsp/trap_handler.c Normal file
View File

@ -0,0 +1,18 @@
#include <stdint.h>
#include "./include/trap_code.h"
extern void timer0_irq_handler() __attribute__((weak));
void interrupt_handler(uint32_t mcause, uint32_t mepc)
{
// we have only timer0 interrupt here
timer0_irq_handler();
}
void exception_handler(uint32_t mcause, uint32_t mepc)
{
if ((mcause != TRAP_BREAKPOINT) && (mcause != TRAP_ECALL_M))
while (1);
}

View File

@ -2,6 +2,6 @@
*.o
*.ko
*.obj
simple.bin
simple.dump
simple
*.bin
*.dump
freertos

View File

@ -11,7 +11,7 @@ TARGET = freertos
CFLAGS += -Os
ASM_SRCS := ../../Source/portable/RISC-V/portASM.S
#LDFLAGS +=
INCLUDES += -I. -I../../Source/portable/RISC-V -I../../Source/include -I../../../
INCLUDES += -I. -I../../Source/portable/RISC-V -I../../Source/include -I../../../../bsp
C_SRCS := \
main.c \
@ -23,6 +23,6 @@ C_SRCS := \
../../Source/portable/RISC-V/port.c \
COMMON_DIR = ../../..
COMMON_DIR = ../../../../bsp
TOOLCHAIN_DIR = ../../../../..
include ../../../common.mk
include ../../../../bsp/common.mk

View File

@ -0,0 +1,6 @@
# Object files
*.o
*.ko
*.obj
*.bin
*.dump

View File

@ -0,0 +1,6 @@
# Object files
*.o
*.ko
*.obj
*.bin
*.dump

Some files were not shown because too many files have changed in this diff Show More