当前位置:   article > 正文

LoongArch CPU设计实验_实践任务5:5条指令单周期CPU_实践任务 5:5 条指令单周期 cpu

实践任务 5:5 条指令单周期 cpu

实践任务5:5条指令单周期CPU

本实践任务要求:

阅读并理解实验环境中提供的代码,补充代码中缺失的部分,使设计可以通过仿真和上板验证。
请参照第2.3.1节中介绍的方式获取本次实践任务所需的实验开发环境。具体的实验环境位于 mini_env/ 目录下,其组织结构和使用方式已在本章4.1节介绍过,此处不再重复。

实验环境准备就绪后,请参考下列步骤完成本实践任务:

  1. 在 minicpu_env/soc_verify/run_vivado/ 目录下打开miniCPU工程。如需要,请参考附录D.4节进行工程和IP核升级。
  2. 对miniCPU工程中的inst_ram重新定制,选择对应func的coe文件(minicpu_env/func/inst_ram.coe)。
  3. 运行miniCPU工程的仿真(进入仿真界面后,直接点击run all),开始调试。可以修改 minicpu_env/soc_verify/testbench/ 目录下的minicpu_tb.v文件中的switch值观察led输出值是否符合预期(每次修改switch值之后都要重新仿真)。(因为本实验的测试程序为斐波那契数程序,斐波那契数列是:0,1,1,2,3,5,……从第三项开始,每一项都等于前两项之和。规定数列第三项为f(1),即f(1)=1,f(2)=2,f(3)=3,f(4)=5, …… 。修改拨码开关switch值相当于修改n,led输出值对应f(n)。
  4. myCPU仿真通过后,综合实现后生成bit流文件,进行上板验证。(如果无硬件实验平台,请跳过该步骤。)

指令格式

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

inst_ram

1c000000:       addi.w   $t0,$zero,0x0      //置第1项的0
1c000004:       addi.w   $t1,$zero,0x1      //置第2项的1
1c000008:       addi.w   $s0,$zero,0x0      //循环变量i初始化为0
1c00000c:       addi.w   $s1,$zero,0x1      //循环的步长置为1
1c000010:       ld.w     $a0,$zero,1024     //读取拨码开关输入的终止值
          loop:
1c000014:       add.w    $t2,$t0,$t1        //f(i) = f(i-2) + f(i-1) 
1c000018:       addi.w   $t0,$t1,0x0        //记录f(i-1)
1c00001c:       addi.w   $t1,$t2,0x0        //记录f(i) 
1c000020:       add.w    $s0,$s0,$s1        //i++
1c000024:       bne      $s0,$a0,loop       //if i!=n, goto loop
1c000028:       st.w     $t2,$zero,1028     //将f(n)的值输出到数码管上
          end:
1c00002c:       bne      $s1, $zero, end    //测试完毕,进入死循环
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

代码

module minicpu_top(
    input  wire        clk,
    input  wire        resetn,

    output wire        inst_sram_we,
    output wire [31:0] inst_sram_addr,
    output wire [31:0] inst_sram_wdata,
    input  wire [31:0] inst_sram_rdata,

    output wire        data_sram_we,
    output wire [31:0] data_sram_addr,
    output wire [31:0] data_sram_wdata,
    input  wire [31:0] data_sram_rdata
);

reg         reset;
always @(posedge clk) reset <= ~resetn;

reg         valid;
always @(posedge clk) begin
    if (reset) begin
        valid <= 1'b0;
    end
    else begin
        valid <= 1'b1;
    end
end

reg  [31:0] pc;
wire [31:0] nextpc;
   
wire [31:0] inst;

wire [ 5:0] op_31_26;
wire [ 3:0] op_25_22;
wire [ 1:0] op_21_20;
wire [ 4:0] op_19_15;
wire [63:0] op_31_26_d;
wire [15:0] op_25_22_d;
wire [ 3:0] op_21_20_d;
wire [31:0] op_19_15_d;
wire [ 4:0] rd;
wire [ 4:0] rj;
wire [ 4:0] rk;
wire [11:0] i12;
wire [15:0] i16;
wire [15:0] i16_2;

wire        inst_add_w;
wire        inst_addi_w;
wire        inst_ld_w;
wire        inst_st_w;
wire        inst_bne;

wire        src2_is_imm;
wire        res_from_mem;
wire        gr_we;
wire        mem_we;
wire        src_reg_is_rd;
wire [31:0] rj_value;
wire [31:0] rkd_value;

wire [ 4:0] rf_raddr1;
wire [ 4:0] rf_raddr2;
wire [ 4:0] rf_waddr;
wire [31:0] rf_wdata;

wire        br_taken;
wire        rj_eq_rd;
wire [31:0] br_offs;
wire [31:0] br_target;

wire [31:0] imm;
wire [31:0] alu_src1;
wire [31:0] alu_src2;
wire [31:0] alu_result;


always @(posedge clk) begin
    if (reset) begin
        pc <= 32'h1bfffffc;     //trick: to make nextpc be 0x1c000000 during reset 
    end
    else begin
        pc <= nextpc;
    end
end

assign inst_sram_we    = 1'b0;
assign inst_sram_addr  = pc;
assign inst_sram_wdata = 32'b0;
assign inst            = inst_sram_rdata;

assign op_31_26 = inst[31:26];
assign op_25_22 = inst[25:22];
assign op_21_20 = inst[21:20];
assign op_19_15 = inst[19:15];
assign rd       = inst[ 4: 0];
assign rj       = inst[ 9: 5];
assign rk       = inst[14:10];
assign i12      = inst[21:10];
assign i16      = inst[25:10];
assign i16_2    = i16 << 2;

decoder_6_64 u_dec0(.in(op_31_26 ), .co(op_31_26_d ));
decoder_4_16 u_dec1(.in(op_25_22 ), .co(op_25_22_d ));
decoder_2_4  u_dec2(.in(op_21_20 ), .co(op_21_20_d ));
decoder_5_32 u_dec3(.in(op_19_15 ), .co(op_19_15_d ));

assign inst_add_w  = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h00];
assign inst_addi_w = op_31_26_d[6'h00] & op_25_22_d[4'ha];
assign inst_ld_w   = op_31_26_d[6'h0a] & op_25_22_d[4'h2];
assign inst_st_w   = op_31_26_d[6'h0a] & op_25_22_d[4'h6];
assign inst_bne    = op_31_26_d[6'h17];

assign src2_is_imm   = inst_addi_w | inst_ld_w | inst_st_w;//在这里实现立即数选择信号
assign res_from_mem  = inst_ld_w;
assign gr_we         = inst_add_w | inst_ld_w | inst_addi_w;
assign mem_we        = inst_st_w;
assign src_reg_is_rd = inst_bne | inst_st_w;

assign rf_raddr1 = rj;
assign rf_raddr2 = src_reg_is_rd ? rd : rk;
regfile u_regfile(
    .clk    (clk      ),
    .raddr1 (rf_raddr1),
    .rdata1 (rj_value ),
    .raddr2 (rf_raddr2),
    .rdata2 (rkd_value),
    .we     (gr_we    ),
    .waddr  (rf_waddr ),
    .wdata  (rf_wdata )
    );//在空出的括号里完成引脚匹配

assign br_offs   = {{14{i16[15]}}, i16, 2'b00};//在这里完成br_offs信号的生成
assign br_target = pc + br_offs;
assign rj_eq_rd  = (rj_value == rkd_value);
assign br_taken  = valid && inst_bne && !rj_eq_rd;
assign nextpc    = br_taken ? br_target : pc + 4;//在这里实现nextpc信号的生成

// se si12
assign imm      = {{20{i12[11]}},i12[11:0]};
assign alu_src1 = rj_value;
assign alu_src2 = src2_is_imm ? imm : rkd_value;//在这里实现alu_src2信号

assign alu_result = alu_src1 + alu_src2;

assign data_sram_we    = mem_we;
assign data_sram_addr  = alu_result;
assign data_sram_wdata = rkd_value;

assign rf_waddr = rd;
assign rf_wdata = res_from_mem ? data_sram_rdata : alu_result;//在这里完成写回寄存器值的选择

endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154

仿真

led低电平
在这里插入图片描述

参考资料

[1] CPU设计实战(汪文祥)第四章
[2] LoongArch CPU设计实验_实践任务5
[3] CDP_EDE_local
[4] 龙芯架构32位精简版参考手册

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/941994
推荐阅读
相关标签
  

闽ICP备14008679号