天天看点

CPU设计实战 第6章 实践任务前言一、实验内容

CPU设计实战-汪文祥 邢金璋

第6章 实践任务

实验环境 lab7.zip

文章目录

  • 前言
  • 一、实验内容

前言

在lab6的实验环境下,在流水线中添加转移指令和访存指令。

一、实验内容

添加转移指令:

我们将所有转移指令都放在译码级完成

//ID_stage添加代码:
wire        inst_bgez;
wire        inst_bgtz;
wire        inst_blez;
wire        inst_bltz;
wire        inst_bgezal;
wire        inst_bltzal;
wire        inst_j;
wire        inst_jalr;
assign inst_bgez   = op_d[6'h01] & rt_d[5'h01];
assign inst_bgtz   = op_d[6'h07] & rt_d[5'h00];
assign inst_blez   = op_d[6'h06] & rt_d[5'h00];
assign inst_bltz   = op_d[6'h01] & rt_d[5'h00];
assign inst_bgezal = op_d[6'h01] & rt_d[5'h11];
assign inst_bltzal = op_d[6'h01] & rt_d[5'h10];
assign inst_j      = op_d[6'h02];
assign inst_jalr   = op_d[6'h00] & func_d[6'h09] & rt_d[5'h00] & sa_d[5'h00];
wire        rsgez;
wire        rsgtz;
wire        rslez;
wire        rsltz;
assign rsgez    = (rs_value[31] == 1'b0 || rs_value == 32'd0);
assign rsgtz    = (rs_value[31] == 1'b0 && rs_value != 32'd0);
assign rslez    = (rs_value[31] == 1'b1 || rs_value == 32'd0);
assign rsltz    = (rs_value[31] == 1'b1 && rs_value != 32'd0);

//ID_stage修改代码:
assign alu_op[ 0] = inst_addu   | inst_addiu | inst_lw    | inst_sw 
                  | inst_jal    | inst_add   | inst_addi  | inst_jalr
                  | inst_bgezal | inst_bltzal| inst_lb    | inst_lbu
                  | inst_lh     | inst_lhu   | inst_lwl   | inst_lwr
                  | inst_sb     | inst_sh    | inst_swl   | inst_swr;
assign src1_is_pc   = inst_jal   | inst_bgezal | inst_bltzal | inst_jalr;
assign src2_is_8    = inst_jal | inst_bgezal | inst_bltzal | inst_jalr;
assign dst_is_r31   = inst_jal   | inst_bgezal | inst_bltzal;
assign gr_we        = ~inst_sw   & ~inst_beq  & ~inst_bne  & ~inst_jr   &
                      ~inst_bgez & ~inst_bgtz & ~inst_blez & ~inst_bltz &
                      ~inst_sb   & ~inst_sh   & ~inst_swl  & ~inst_swr;  
assign br_taken = (   inst_beq    &&  rs_eq_rt
                   || inst_bne    && !rs_eq_rt
                   || inst_bgez   &&  rsgez
                   || inst_bgtz   &&  rsgtz
                   || inst_blez   &&  rslez
                   || inst_bltz   &&  rsltz
                   || inst_bltzal &&  rsltz
                   || inst_bgezal &&  rsgez
                   || inst_jal
                   || inst_j
                   || inst_jalr
                   || inst_jr
                  ) && ds_valid;
assign br_target = (inst_beq || inst_bne || inst_bgez || inst_bgtz || inst_blez || inst_bltz || inst_bgezal || inst_bltzal) ? 
                   (fs_pc + {{14{imm[15]}}, imm[15:0], 2'b0}) :
                   (inst_jr || inst_jalr)          ? rs_value :
                  /*inst_jal*/              {fs_pc[31:28], jidx[25:0], 2'b00};
assign inst_no_dest = inst_beq  | inst_bne  | inst_jr   | inst_sw 
                    | inst_bgez | inst_bgtz | inst_blez | inst_bltz
                    | inst_j    | inst_sb   | inst_sh   | inst_swl 
                    | inst_swr;
           

添加存数指令:

我们将所有存数指令都放在执行级完成

//ID_stage添加代码:
wire        inst_swl;
wire        inst_swr;
wire        inst_sb;
wire        inst_sh;
assign inst_swl    = op_d[6'h2a];
assign inst_swr    = op_d[6'h2e];
assign inst_sb     = op_d[6'h28];
assign inst_sh     = op_d[6'h29];
wire [11:0] mem_control;
assign mem_control = {inst_swr, inst_swl, inst_sh, 
                      inst_sb , inst_lwr, inst_lwl, 
                      inst_lhu, inst_lh , inst_lbu,
                      inst_lb , inst_sw , inst_lw};


//ID_stage修改代码:
assign alu_op[ 0] = inst_addu   | inst_addiu | inst_lw    | inst_sw 
                  | inst_jal    | inst_add   | inst_addi  | inst_jalr
                  | inst_bgezal | inst_bltzal| inst_lb    | inst_lbu
                  | inst_lh     | inst_lhu   | inst_lwl   | inst_lwr
                  | inst_sb     | inst_sh    | inst_swl   | inst_swr;
assign src2_is_imm_sign  = inst_addiu | inst_lw    | inst_sw   | inst_addi 
                         | inst_slti  | inst_sltiu | inst_lb   | inst_lbu 
                         | inst_lh    | inst_lhu   | inst_lwl  | inst_lwr
                         | inst_sb    | inst_sh    | inst_swl  | inst_swr;
assign gr_we        = ~inst_sw   & ~inst_beq  & ~inst_bne  & ~inst_jr   &
                      ~inst_bgez & ~inst_bgtz & ~inst_blez & ~inst_bltz &
                      ~inst_sb   & ~inst_sh   & ~inst_swl  & ~inst_swr;                                           
assign mem_we       = inst_sw | inst_sb | inst_sh | inst_swl | inst_swr;
assign inst_no_dest = inst_beq  | inst_bne  | inst_jr   | inst_sw 
                    | inst_bgez | inst_bgtz | inst_blez | inst_bltz
                    | inst_j    | inst_sb   | inst_sh   | inst_swl 
                    | inst_swr;
assign ds_to_es_bus = {mem_control ,  //156:145
                       mf_mt       ,  //144:141
                       mult_div    ,  //140:137
                       alu_op      ,  //136:125
                       load_op     ,  //124:124
                       src1_is_sa  ,  //123:123
                       src1_is_pc  ,  //122:122
                       src2_is_imm ,  //121:120
                       src2_is_8   ,  //119:119
                       gr_we       ,  //118:118
                       mem_we      ,  //117:117
                       dest        ,  //116:112
                       imm         ,  //111:96
                       rs_value    ,  //95 :64
                       rt_value    ,  //63 :32
                       ds_pc          //31 :0
                      };

//EXE_stage添加代码:
wire [11:0] es_mem_control;
wire [ 3:0] sram_wen;           //SRAM写使能信号
wire [31:0] write_sram_data;    //SRAM写数据
wire        inst_is_sb;
wire        inst_is_sh;
wire        inst_is_swl;
wire        inst_is_swr;
assign      inst_is_sb  = es_mem_control == 12'b000100000000;
assign      inst_is_sh  = es_mem_control == 12'b001000000000;
assign      inst_is_swl = es_mem_control == 12'b010000000000;
assign      inst_is_swr = es_mem_control == 12'b100000000000;

assign write_sram_data = inst_is_sb  ? (es_alu_result[1:0] == 2'b00 ? {24'd0, es_rt_value[7:0]}        :
                                        es_alu_result[1:0] == 2'b01 ? {16'd0, es_rt_value[7:0],  8'd0} :
                                        es_alu_result[1:0] == 2'b10 ? { 8'd0, es_rt_value[7:0], 16'd0} :
                                                                      {es_rt_value[7:0],        24'd0}
                                       ) :
                         inst_is_sh  ? (es_alu_result[1:0] == 2'b00 ? {16'd0, es_rt_value[15:0]} :
                                                                      {es_rt_value[15:0], 16'd0}
                                       ) : 
                         inst_is_swl ? (es_alu_result[1:0] == 2'b00 ? {24'd0, es_rt_value[31:24]} :
                                        es_alu_result[1:0] == 2'b01 ? {16'd0, es_rt_value[31:16]} :
                                        es_alu_result[1:0] == 2'b10 ? { 8'd0, es_rt_value[31:8]}  :
                                                                       es_rt_value
                                       ) :
                         inst_is_swr ? (es_alu_result[1:0] == 2'b00 ?  es_rt_value               :
                                        es_alu_result[1:0] == 2'b01 ? {es_rt_value[23:0],  8'd0} :
                                        es_alu_result[1:0] == 2'b10 ? {es_rt_value[15:0], 16'd0} :
                                                                      {es_rt_value[ 7:0], 24'd0}
                                       ) :
                                       es_rt_value;

assign sram_wen        = inst_is_sb  ? (es_alu_result[1:0] == 2'b00 ? 4'b0001 :
                                        es_alu_result[1:0] == 2'b01 ? 4'b0010 :
                                        es_alu_result[1:0] == 2'b10 ? 4'b0100 :
                                                                      4'b1000
                                       ) :
                         inst_is_sh  ? (es_alu_result[1:0] == 2'b00 ? 4'b0011 :
                                                                      4'b1100
                                       ) :
                         inst_is_swl ? (es_alu_result[1:0] == 2'b00 ? 4'b0001 :
                                        es_alu_result[1:0] == 2'b01 ? 4'b0011 :
                                        es_alu_result[1:0] == 2'b10 ? 4'b0111 :
                                                                      4'b1111
                                       ) :
                         inst_is_swr ? (es_alu_result[1:0] == 2'b00 ? 4'b1111 :
                                        es_alu_result[1:0] == 2'b01 ? 4'b1110 :
                                        es_alu_result[1:0] == 2'b10 ? 4'b1100 :
                                                                      4'b1000
                                       ) :
                                       4'b1111;

//EXE_stage修改代码:
assign {es_mem_control ,  //156:145
        mf_mt          ,  //144:141
        mult_div       ,  //140:137
        es_alu_op      ,  //136:125
        es_load_op     ,  //124:124
        es_src1_is_sa  ,  //123:123
        es_src1_is_pc  ,  //122:122
        es_src2_is_imm ,  //121:120
        es_src2_is_8   ,  //119:119
        es_gr_we       ,  //118:118
        es_mem_we      ,  //117:117
        es_dest        ,  //116:112
        es_imm         ,  //111:96
        es_rs_value    ,  //95 :64
        es_rt_value    ,  //63 :32
        es_pc             //31 :0
       } = ds_to_es_bus_r;
assign data_sram_wen   = es_mem_we&&es_valid ? sram_wen : 4'h0;  
assign data_sram_wdata = write_sram_data;  
           

添加取数指令:

我们将所有取数指令都放在访存级完成

//ID_stage添加代码:
wire        inst_lb;
wire        inst_lbu;
wire        inst_lh;
wire        inst_lhu;
wire        inst_lwl;
wire        inst_lwr;
assign inst_lb     = op_d[6'h20];
assign inst_lbu    = op_d[6'h24];
assign inst_lh     = op_d[6'h21];
assign inst_lhu    = op_d[6'h25];
assign inst_lwl    = op_d[6'h22];
assign inst_lwr    = op_d[6'h26];

//ID_stage修改代码:
assign alu_op[ 0] = inst_addu   | inst_addiu | inst_lw    | inst_sw 
                  | inst_jal    | inst_add   | inst_addi  | inst_jalr
                  | inst_bgezal | inst_bltzal| inst_lb    | inst_lbu
                  | inst_lh     | inst_lhu   | inst_lwl   | inst_lwr
                  | inst_sb     | inst_sh    | inst_swl   | inst_swr;
assign load_op      = inst_lw | inst_lb | inst_lbu | inst_lh | inst_lhu | inst_lwl | inst_lwr;
assign src2_is_imm_sign  = inst_addiu | inst_lw    | inst_sw   | inst_addi 
                         | inst_slti  | inst_sltiu | inst_lb   | inst_lbu 
                         | inst_lh    | inst_lhu   | inst_lwl  | inst_lwr
                         | inst_sb    | inst_sh    | inst_swl  | inst_swr;
assign dst_is_rt    = inst_addiu | inst_lui   | inst_lw   | inst_addi 
                    | inst_slti  | inst_sltiu | inst_andi | inst_ori 
                    | inst_xori  | inst_lb    | inst_lbu  | inst_lh 
                    | inst_lhu   | inst_lwl   | inst_lwr;
assign src2_no_rt = inst_addiu | inst_lw   | inst_jal   | inst_lui 
                  | inst_addi  | inst_slti | inst_sltiu | inst_andi 
                  | inst_ori   | inst_xori | inst_lb    | inst_lbu  
                  | inst_lh    | inst_lhu;

//EXE_stage修改代码:
assign es_to_ms_bus = {es_rt_value    ,  //114:83
                       es_mem_control ,  //82:71
                       es_res_from_mem,  //70:70
                       es_gr_we       ,  //69:69
                       es_dest        ,  //68:64
                       es_result      ,  //63:32
                       es_pc             //31:0
                      };

//MEM_stage添加代码:
wire [11:0] ms_mem_control;
wire [31:0] ms_rt_value;
wire 		load_sign_lb;
wire 		load_sign_lh;
wire [31:0] mem_result_lb;
wire [31:0] mem_result_lbu;
wire [31:0] mem_result_lh;
wire [31:0] mem_result_lhu;
wire [31:0] mem_result_lwl;
wire [31:0] mem_result_lwr;

//lb/lbu
assign load_sign_lb         = (ms_alu_result[1:0] == 2'd0) ? data_sram_rdata[ 7] :
                              (ms_alu_result[1:0] == 2'd1) ? data_sram_rdata[15] :
                              (ms_alu_result[1:0] == 2'd2) ? data_sram_rdata[23] :
                                                             data_sram_rdata[31];                                                  
assign mem_result_lb[ 7:0]  = (ms_alu_result[1:0] == 2'd0) ? data_sram_rdata[ 7:0 ] :
                              (ms_alu_result[1:0] == 2'd1) ? data_sram_rdata[15:8 ] :
                              (ms_alu_result[1:0] == 2'd2) ? data_sram_rdata[23:16] :
                                                             data_sram_rdata[34:24];
assign mem_result_lb[31:8]  = {24{load_sign_lb}};
assign mem_result_lbu       = {24'd0, mem_result_lb[7:0]};


//lh/lhu
assign load_sign_lh         = (ms_alu_result[1:0] == 2'b00) ? data_sram_rdata[15]   :
                              (ms_alu_result[1:0] == 2'b10) ? data_sram_rdata[31]   : 1'b0;                                                   
assign mem_result_lh[15:0]  = (ms_alu_result[1:0] == 2'b00) ? data_sram_rdata[15:0] : 
                              (ms_alu_result[1:0] == 2'b10) ? data_sram_rdata[31:16]: 16'd0;
assign mem_result_lh[31:16] = {16{load_sign_lh}};
assign mem_result_lhu       = {16'd0, mem_result_lh[15:0]};

//lwl
assign mem_result_lwl       = (ms_alu_result[1:0] == 2'd0) ? {data_sram_rdata[ 7:0], ms_rt_value[23:0]} :
                              (ms_alu_result[1:0] == 2'd1) ? {data_sram_rdata[15:0], ms_rt_value[15:0]} :
                              (ms_alu_result[1:0] == 2'd2) ? {data_sram_rdata[23:0], ms_rt_value[7 :0]} :
                                                              data_sram_rdata[31:0];

//lwr
assign mem_result_lwr       = (ms_alu_result[1:0] == 2'd0) ?  data_sram_rdata[31:0]                       :
                              (ms_alu_result[1:0] == 2'd1) ? {ms_rt_value[31:24], data_sram_rdata[31: 8]} :
                              (ms_alu_result[1:0] == 2'd2) ? {ms_rt_value[31:16], data_sram_rdata[31:16]} :
                                                             {ms_rt_value[31: 8], data_sram_rdata[31:24]} ;

//MEM_stage修改代码:
assign {ms_rt_value    ,  //114:83
        ms_mem_control ,  //82:71
        ms_res_from_mem,  //70:70
        ms_gr_we       ,  //69:69
        ms_dest        ,  //68:64
        ms_alu_result  ,  //63:32
        ms_pc             //31:0
       } = es_to_ms_bus_r;
assign mem_result = (ms_mem_control == 12'b000000000100) ? mem_result_lb  :
                    (ms_mem_control == 12'b000000001000) ? mem_result_lbu :
                    (ms_mem_control == 12'b000000010000) ? mem_result_lh  :
                    (ms_mem_control == 12'b000000100000) ? mem_result_lhu : 
                    (ms_mem_control == 12'b000001000000) ? mem_result_lwl :
                    (ms_mem_control == 12'b000010000000) ? mem_result_lwr :
                                                           data_sram_rdata;
           

最后别忘了修改mycpu.h的宏定义:

`ifndef MYCPU_H
    `define MYCPU_H

    `define BR_BUS_WD       34   //lab4修改
    `define FS_TO_DS_BUS_WD 64
    `define DS_TO_ES_BUS_WD 157  //lab7修改
    `define ES_TO_MS_BUS_WD 115  //lab7修改
    `define MS_TO_WS_BUS_WD 70
    `define WS_TO_RF_BUS_WD 38
`endif