Bootstrap

使用Verilog语言对RISC-V单周期处理器的修改与测试

所涉及的程序及文件
链接:https://pan.baidu.com/s/1S9vrGjryHHj3c8qQUkwuAQ
提取码:escq

设计目标

对授课内容的单周期 RISC-V 处理器进行扩展,使之能够支持两个额外的指令:lui 和 xor。 图 1 所示是一个完整的单周期处理器,图 2 是控制单元,图 3 是 ALU。 表 1 和表 2 是 Main Decoder 和 ALU Decoder 真值表,表 3 列出的是 ImmSrc 编码,图 4 是 RISC-V 单周期处理器的测试程序。

确定结构

第一步: 确定通路

在已有单周期流水线处理器模型的基础上可根据指令所涉及到的单元,确定两条新的指令的数据通路,在数据通路的基础上,查阅相关资料,确定在RISC-V指令集中单周期处理器所涉及到的opcode及相应控制信号。
在这里插入图片描述
上述修改均为查阅所涉及指令实际opcode之后的结果,对于每个模块具体所需译码器的相关输出已经在图中标出。实际上,具体信号的标出应在第二步确定真值表之后。

第二步:确定真值表

确定Main Decoder真值表
在这里插入图片描述
查阅相关资料,确定Main Decoder真值表如图所示

确定ALU Decoder真值表
在这里插入图片描述
查阅相关资料,确定ALU Decoder真值表如图所示。

确定ImmSrc编码方式
在这里插入图片描述

第三步:确定控制单元

在已有控制单元的基础上,确定控制单元所产生的相关控制信号(红色为lui,紫色为xor)
在这里插入图片描述

第四步:确定ALU结构

在这里插入图片描述
可以看出,此处因为新增的xor指令,不得不引出新的ALU结构,增加了一个异或门,增加了一条多路选择器的通路。

二、编写代码

第四步:修改top.v文件

将top.v文件与tb_top.v文件加入vivado工程下
修改top.v文件,使之能容纳lui指令与xor指令,具体修改处如下:
1.立即数扩展控制信号位宽从2bit改为3bit

wire [2:0] ImmSrc;//修改为3bit

模块如controller、maindec、datapath、extend中ImmSrc处进行相应修改,对于maindec中的control信号同样需要相应地修改位宽。
2.修改控制信号
值得注意的是,第一条末尾位置还应为添加新增指令所需的控制信号

always @(*)
        case (op)//controls从11bits修改为12bits
            7'b0000011: controls = 12'b100010010000;
            7'b0100011: controls = 12'b000111000000;
            7'b0110011: controls = 12'b1xxx00000100;//R-type
            7'b1100011: controls = 12'b001000001010;
            7'b0010011: controls = 12'b100010000100;//I-type
            7'b1101111: controls = 12'b101100100001;
            7'b0110111: controls = 12'b1100x0110xx0;//lui

            default: controls = 12'bxxxxxxxxxxxx;
        endcase

另外,aludec模块中,对ALUControl信号增加如下

3'b100: ALUControl = 3'b100;//xor

3.修改输出的多路选择器
lui指令引入了额外的结果通路,在此将三路的多路选择器改成四路

mux4 #(.WIDTH(32)) resultmux(//修改为mux4
        .d0(ALUResult),
        .d1(ReadData),
        .d2(PCPlus4),
        .d3(ImmExt),//新增通路
        .s(ResultSrc),
        .y(Result)
    );
module mux4 (//修改为mux4
    input wire [WIDTH - 1:0] d0,
    input wire [WIDTH - 1:0] d1,
    input wire [WIDTH - 1:0] d2,
    input wire [WIDTH - 1:0] d3,//新增通路,连接至extend
    input wire [1:0] s,
    output wire [WIDTH - 1:0] y
);
    parameter WIDTH = 8;

    assign y = (s[1] ? (s[0] ? d3 : d2) : (s[0] ? d1 : d0));//增加选择通路
endmodule

4.修改立即数扩展方式
lui指令引入了新的立即数扩展方式

always @(*)
        case (immsrc)//以下对应3bit修改
            3'b000: immext = {{20 {instr[31]}}, instr[31:20]};
            3'b001: immext = {{20 {instr[31]}}, instr[31:25], instr[11:7]};
            3'b010: immext = {{20 {instr[31]}}, instr[7], instr[30:25], instr[11:8], 1'b0};
            3'b011: immext = {{12 {instr[31]}}, instr[19:12], ilnstr[20], instr[30:21], 1'b0};
            3'b100: immext = {instr[31:12],12'b0};
            default: immext = 32'bx;
        endcase

三、程序仿真

第五步:运行给出的测试程序

测试文件名为riscvtest.txt,测试程序详解如下
在这里插入图片描述
对于以上测试程序,测试结果如下
在这里插入图片描述
运行通过
对以下信号进行仿真: clk、reset、PC、Instr、SrcA、SrcB、 ALUResult、DataAdr、WriteData 和 MemWrite
在这里插入图片描述
可以看出,所有信号均正常

第六步:新建测试程序

对于增加的指令,构建测试文件riscvtest2.txt,思路如下
在这里插入图片描述

第七步:修改tb_top.v文件

对于新的测试程序,程序正确运行判定条件须进行一定修改,添加后方带注释的四行

always @(negedge clk)
        if (MemWrite)
            if ((DataAdr === 100) & (WriteData === 25)) begin
                $display("Simulation succeeded");
                $stop;
            end
            else if ((DataAdr === 0) & (WriteData === 4294963212)) begin//新
                $display("Simulation failed");//新
                $stop;// 新
            end//新
            else if (DataAdr !== 96) begin
                $display("Simulation failed");
                $stop;
            end

第八步:运行新的测试用例

在这里插入图片描述
运行成功,本次作业完成

;