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