cisen / blog

Time waits for no one.
133 stars 20 forks source link

tinyriscv 相关 #1014

Open cisen opened 3 years ago

cisen commented 3 years ago

总结

1.支持RV32IM指令集,通过RISC-V指令兼容性测试;

2.采用三级流水线,即取指,译码,执行;

3.可以运行C语言程序;

4.支持JTAG,可以通过openocd读写内存(在线更新程序);

5.支持中断;

6.支持总线;

7.支持FreeRTOS;

  1. 下载freertos.bin的时候,uart的使能要设置为0,如果不行,可以重复下载bin和重复设置为0

247269-20200502133246486-626702544

GPIO

问答

GPIO为什么要做特殊处理?有哪些特色的地方?

timer是做什么的?

pc寄存器有什么作用?

if_id有什么用?

触发器(Flip-Flop)是什么?

译码是如何实现的?

执行是如何实现的? 执行模块所在的源文件:rtl/core/ex.v

执行(ex)模块是一个纯组合逻辑电路,主要作用有以下几点: 1.根据当前是什么指令执行对应的操作,比如add指令,则将寄存器1的值和寄存器2的值相加。 2.如果是内存加载指令,则读取对应地址的内存数据。 3.如果是跳转指令,则发出跳转信号。 执行模块的输入输出信号如下表所示:

序号 信号名 输入/输出 位宽(bits) 说明
1 rst 输入 1 复位信号
2 inst_i 输入 32 指令内容
3 inst_addr_i 输入 32 指令地址
4 reg_we_i 输入 1 寄存器写使能
5 reg_waddr_i 输入 5 通用寄存器写地址,即写哪一个通用寄存器
6 reg1_rdata_i 输入 32 通用寄存器1读数据
7 reg2_rdata_i 输入 32 通用寄存器2读数据
8 csr_we_i 输入 1 CSR寄存器写使能
9 csr_waddr_i 输入 32 CSR寄存器写地址,即写哪一个CSR寄存器
10 csr_rdata_i 输入 32 CSR寄存器读数据
11 int_assert_i 输入 1 中断信号
12 int_addr_i 输入 32 中断跳转地址,即中断发生后跳转到哪个地址
13 mem_rdata_i 输入 32 内存读数据
14 div_ready_i 输入 1 除法模块是否准备好信号,即是否可以进行除法运算
15 div_result_i 输入 64 除法结果
16 div_busy_i 输入 1 除法模块忙信号,即正在进行除法运算
17 div_op_i 输入 3 具体的除法运算,即DIV、DIVU、REM和REMU中的哪一种
18 div_reg_waddr_i 输入 5 除法运算完成后要写的通用寄存器地址
19 mem_wdata_o 输出 32 内存写数据
20 mem_raddr_o 输出 32 内存读地址
21 mem_waddr_o 输出 32 内存写地址
22 mem_we_o 输出 1 内存写使能
23 mem_req_o 输出 1 请求访问内存信号
24 reg_wdata_o 输出 32 通用寄存器写数据
25 reg_we_o 输出 1 通用寄存器写使能
26 reg_waddr_o 输出 5 通用寄存器写地址
27 csr_wdata_o 输出 32 CSR寄存器写数据
28 csr_we_o 输出 1 CSR寄存器写使能
29 csr_waddr_o 输出 32 CSR寄存器写地址,即写哪一个CSR寄存器
30 div_start_o 输出 1 开始除法运算
31 div_dividend_o 输出 32 除法运算中的被除数
32 div_divisor_o 输出 32 除法运算中的除数
33 div_op_o 输出 3 具体的除法运算,即DIV、DIVU、REM和REMU中的哪一种
34 div_reg_waddr_o 输出 5 除法运算完成后要写的通用寄存器地址
35 hold_flag_o 输出 1 暂停流水线信号
36 jump_flag_o 输出 1 跳转信号
37 jump_addr_o 输出 32 跳转地址

下面以add指令为例说明,add指令的作用就是将寄存器1的值和寄存器2的值相加,最后将结果写入目的寄存器。代码如下:

`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 = reg1_rdata_i + reg2_rdata_i;
                 end else begin
                     reg_wdata = reg1_rdata_i - reg2_rdata_i;
                 end
        ...
     end

第2~4行,译码操作。 第5行,对add或sub指令进行处理。 第6~12行,当前指令不涉及到的操作(比如跳转、写内存等)需要将其置回默认值。 第13行,指令编码中的第30位区分是add指令还是sub指令。0表示add指令,1表示sub指令。 第14行,执行加法操作。 第16行,执行减法操作。

取完指令是如何过度到执行指令的?

乘法是如何实现的?如何重复调用加法器?

除法是如何实现的?

固化后如何输入一堆指令?

多条指令执行以默认自动+4?pc_o <= pc_o + 4'h4;

cisen commented 3 years ago

https://github.com/cisen/sourcecode-tinyriscv-zynq-00/tree/main/blog