发新帖我要提问
12
返回列表
[其他]

基于RISC-V指令集架构的SoC设计

[复制链接]
楼主: coshi
手机看帖
扫描二维码
随时随地手机跟帖
coshi|  楼主 | 2021-7-8 10:38 | 显示全部楼层
测试平台

tb_riscv_soc.sv :在testbench中直接将要执行的指令load进入Memory中。


//`timescale 1ns / 1ps


// Company:

// Engineer:

//

// Create Date: 2021/03/13

// Author Name: Sniper

// Module Name: tb_riscv_soc

// Project Name:

// Target Devices:

// Tool Versions:

// Description:

//

// Dependencies:

//

// Revision:

// Revision 0.01 - File Created

// Additional Comments:

//



module tb_riscv_soc;


//parameter

parameter MEM_SIZE = 8192;

parameter FIRMWARE = "";



//DUT signals

reg         clk;

reg         reset;

wire        lock;

reg         uart_rx;

wire        uart_tx;

reg  [31:0] gpio_in;

wire [31:0] gpio_out;



initial

begin

    clk = 1;

    reset = 1;

    uart_rx = 1'b1;

    gpio_in = 32'hABCD5678;



        #100;

    @(posedge clk);

    reset <= 0;

end


//clock

always #5 clk = ~clk;



localparam  INSTR_CNT = 30'd24;

wire [0:INSTR_CNT-1] [31:0] instr_rom_cell = {

    32'h000062b3,   // 0x00000000

    32'h200002b7,   // 0x00000004

    32'h12345337,   // 0x00000008

    32'h67836313,   // 0x0000000c

    32'h0062a023,   // 0x00000010

    32'h00006e33,   // 0x00000014

    32'h008e6e13,   // 0x00000018

    32'h00006333,   // 0x0000001c

    32'h0fe36313,   // 0x00000020

    32'h01c31333,   // 0x00000024

    32'h0dc36313,   // 0x00000028

    32'h0062a023,   // 0x0000002c

    32'h0002a383,   // 0x00000030

    32'h000062b3,   // 0x00000034

    32'h00006333,   // 0x00000038

    32'h000063b3,   // 0x0000003c

    32'h00006e33,   // 0x00000040

    32'h000062b3,   // 0x00000044

    32'h0082e293,   // 0x00000048

    32'h12345337,   // 0x0000004c

    32'h67836313,   // 0x00000050

    32'h0062a023,   // 0x00000054

    32'h0002a383,   // 0x00000058

    32'hfa5ff06f    // 0x0000005c

};


//Instructions

integer i;

initial

begin

    for(i=0;i<INSTR_CNT;i++)

    begin

        u_riscv_soc.u_memory.mem_r = instr_rom_cell;

        $display("mem[%0d] = %32x", i, u_riscv_soc.u_memory.mem_r);

    end

end





//DUT

riscv_soc

#(

    .MEM_SIZE(MEM_SIZE),

    .FIRMWARE(FIRMWARE)

)

u_riscv_soc

(

    .clk_i(clk),

    .reset_i(reset),

    .lock_o(lock),

    .uart_rx_i(uart_rx),

    .uart_tx_o(uart_tx),

    .gpio_in_i(gpio_in),

    .gpio_out_o(gpio_out)

);


initial

begin

    $dumpfile("tb_riscv_soc.vcd");

    $dumpvars(0,tb_riscv_soc);

end


initial #5000 $finish;


endmodule



使用特权

评论回复
coshi|  楼主 | 2021-7-8 10:39 | 显示全部楼层
Makefile


# Makefile
# -------------------------
# target file : source file
# [TAB]command


RTL   += ../rtl/soc/riscv_soc.v
RTL   += ../rtl/cpu/riscv_cpu.v
RTL   += ../rtl/bus/bus_mux.v
RTL   += ../rtl/perips/per_gpio.v
RTL   += ../rtl/perips/per_uart.v
RTL   += ../rtl/perips/per_timer.v
RTL   += ../rtl/perips/memory.v


TB    := ../bench/tb_riscv_soc.sv


CURVE := ./tb_riscv_soc.vcd




# ---------- run common simulation ----------
run: compile simulate


compile:
        vcs -sverilog -debug_all -timescale=1ns/1ns $(RTL) $(TB) -l com.log


simulate:
        ./simv -l run.log


run_dve:
        dve -vpd $(CURVE) &


clean:
        rm -rf csrc DVEfiles simv.daidir coverage *.vdb *.key *.vcd *.vpd *.log simv


使用特权

评论回复
coshi|  楼主 | 2021-7-8 10:39 | 显示全部楼层
加载汇编程序

汇编指令如下所示,主要测试了GPIO读写、Memory读写。

.org 0x0

        .global _start

_start:


main:

    # GPIO外设测试,令t0寄存器=0x20000000,即gpio外设的地址

    or    t0, zero,zero    # t0 清零

    lui   t0, 0x20000      # t0 寄存器的高20bit=0x20000

       

    lui   t1, 0x12345      # t1 寄存器的高20bit=0x12345

    ori   t1, t1, 0x678    # t1 寄存器的低12bit=0x678

    sw    t1, (t0)         # t1 写入t0地址,即GPIO输出0x12345678


    or    t3, zero,zero    # t3 清零

    ori   t3, t3, 0x008    # t3 寄存器的低12bit=0x008

    or    t1, zero,zero    # t1 清零

    ori   t1, t1, 0x0FE    # t1 寄存器的低12bit=0x0FE

    sll   t1, t1, t3       # t1 = t1 << t3 (= t1 << 8)

    ori   t1, t1, 0x0DC    # t1 = t1 | 0x00000DC

    sw    t1, (t0)         # t1写入t0地址,即GPIO输出0x0000FEDC

       

    lw    t2, (t0)         # 将GPIO输入值读取到t2寄存器


    or    t0, zero,zero    # t0 清零

    or    t1, zero,zero    # t1 清零

    or    t2, zero,zero    # t2 清零

    or    t3, zero,zero    # t3 清零



    # Memory读写测试,令t0寄存器=0x00000008,是MEM所在的地址区间

    or    t0, zero,zero    # t0 清零

    ori   t0, t0, 0x008    # t0 寄存器的低12bit=0x008

       

    lui   t1, 0x12345      # t1 寄存器的高20bit=0x12345

    ori   t1, t1, 0x678    # t1 寄存器的低12bit=0x678

    sw    t1, (t0)         # t1 写入t0地址,即MEM写入0x12345678


    lw    t2, (t0)         # 将MEM中(t0)地址对应的数据字读取到t2寄存器


return:

    jal   zero, main       # 程序结束,跳到main,重新运行



使用特权

评论回复
coshi|  楼主 | 2021-7-8 10:40 | 显示全部楼层
汇编程序生成机器指令,使用到了一个软件来转换指令的格式,相关的RISC-V汇编软件网上应该也有很多。将保存下来的指令流(Verilog)添加到tb_riscv_soc.sv的56行位置即可。
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21lbmcxNTA2Nzg5,size_16,color_FFFFFF,t_70.jpg

使用特权

评论回复
coshi|  楼主 | 2021-7-8 10:41 | 显示全部楼层
测试结果

在sim文件夹下包含一个Makefile,可以在sim路径下使用以下命令进行RTL仿真。


make run

make run_dve

make clean


结果如下所示:


[IC@IC sim]$ make run
vcs -sverilog -debug_all -timescale=1ns/1ns ../rtl/soc/riscv_soc.v ../rtl/cpu/riscv_cpu.v ../rtl/bus/bus_mux.v ../rtl/perips/per_gpio.v ../rtl/perips/per_uart.v ../rtl/perips/per_timer.v ../rtl/perips/memory.v ../bench/tb_riscv_soc.sv -l com.log


...




                 130         Read insturction: mem[0] = 0x000062b3
                 210         Read insturction: mem[1] = 0x200002b7
                 290         Read insturction: mem[2] = 0x12345337
                 370         Read insturction: mem[3] = 0x67836313
                 450         Read insturction: mem[4] = 0x0062a023
                 490 GPIO_OUT_DATA = 0x12345678
                 530         Read insturction: mem[5] = 0x00006e33
                 610         Read insturction: mem[6] = 0x008e6e13
                 690         Read insturction: mem[7] = 0x00006333
                 770         Read insturction: mem[8] = 0x0fe36313
                 850         Read insturction: mem[9] = 0x01c31333
                 930         Read insturction: mem[10] = 0x0dc36313
                1010         Read insturction: mem[11] = 0x0062a023
                1050 GPIO_OUT_DATA = 0x0000fedc
                1090         Read insturction: mem[12] = 0x0002a383
                1130 GPIO_READ_DATA = 0xabcd5678
                1170         Read insturction: mem[13] = 0x000062b3
                1250         Read insturction: mem[14] = 0x00006333
                1330         Read insturction: mem[15] = 0x000063b3
                1410         Read insturction: mem[16] = 0x00006e33
                1490         Read insturction: mem[17] = 0x000062b3
                1570         Read insturction: mem[18] = 0x0082e293
                1650         Read insturction: mem[19] = 0x12345337
                1730         Read insturction: mem[20] = 0x67836313
                1810         Read insturction: mem[21] = 0x0062a023
                1850 Write memory: mem[2][7:0] = 0x78
                1850 Write memory: mem[2][15:8] = 0x56
                1850 Write memory: mem[2][23:16] = 0x34
                1850 Write memory: mem[2][31:24] = 0x12
                1890         Read insturction: mem[22] = 0x0002a383
                1930 Read memory: mem[2] = 0x12345678 (word)
                1970         Read insturction: mem[23] = 0xfa5ff06f
                2050         Read insturction: mem[0] = 0x000062b3
                2130         Read insturction: mem[1] = 0x200002b7
                2210         Read insturction: mem[2] = 0x12345678
                2220 Illegal Instruction. CPU is locked.


$finish called from file "../bench/tb_riscv_soc.sv", line 121.
$finish at simulation time                 5000
           V C S   S i m u l a t i o n   R e p o r t
Time: 5000 ns
...


[IC@IC sim]$



6464760e665d462c9f.png

可以看到,当程序从main: 运行第二次时,由于第一次在mem[2]中改变了数据,CPU识别不出这条新的“指令”,因此进入了LOCK状态,这就是冯·诺依曼体系结构可能存在的bug(或者也可以说是一种动态修改指令的功能)。如果要避免这种情况,可以添加数据地址段的访问权限。

使用特权

评论回复
coshi|  楼主 | 2021-7-8 10:42 | 显示全部楼层
总结与展望
目前设计的这个SoC还比较简单,整个SoC还有进一步改进的空间:(1)CPU可以实现pipeline结构(这就要引入旁路、分支预测等技术来解决流水线的数据冲突、提高pipeline处理速度);(2)CPU可以实现更多的RISC-V指令;(3)CPU可以添加JTAG接口用来观测内部运行情况、载入机器指令程序;(4)CPU增加中断响应操作;(5)总线可采用AXI等标准总线实现高性能传输;(6)每个IP在读写数据接口可以增加异步FIFO作为缓存。


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则