实验目的:
1.了解MIPS指令集中的运算指令,学会对这些指令进行归纳分类。
2.熟悉并掌握译码器的原理、功能和设计。
3.进一步加强运用 verilog 语言进行电路设计的能力。
4.为后续设计 cpu 的实验打下基础。
实验重点:
熟悉使用verilog语言进行设计,仿真的过程。
实验难点:
观察仿真波形,确认电路设计是否正确。
学习MIPS指令集,熟知指令类型,了解指令功能和编码,译码器实现框图2.1。译码器输入输出端口说明如表2.1。
表2.1 译码器端口说明
序号 | 接口名 | 宽度 | 输入/输出 | 作用 |
1 | rst | 1 | 输入 | 复位信号 |
2 | inst_i | 32 | 输入 | 译码阶段的指令 |
3 | reg1_data_i | 32 | 输入 | 从regfile读入数据1 |
4 | reg2_data_i | 32 | 输入 | 从regfile读入数据2 |
5 | aluop_o | 14 | 输出 | 译码阶段运算类型 |
6 | reg1_o | 32 | 输出 | 译码阶段源操作数1 |
7 | reg2_o | 32 | 输出 | 译码阶段源操作数2 |
8 | wd_o | 5 | 输出 | 目的寄存器地址,inst_i[15:11] |
9 | wreg_o | 1 | 输出 | 是否要写入目的寄存器 |
10 | reg2_addr_o | 5 | 输出 | 第二个寄存器地址,inst_i[20:16] |
11 | reg2_read_o | 1 | 输出 | regfile第二个寄存器读使能信号 |
12 | reg1_addr_o | 5 | 输出 | 第一个寄存器地址,inst_i[25:21] |
13 | reg1_read_o | 1 | 输出 | regfile第一个寄存器读使能信号 |
MIPS指令主要由I-Type,J-Type,R-Type三种格式组成。我们的实验任务主要针对R-Type和I-Type设计CPU.
为此,我们需要将指令进行划分,用来译码。表2.2是用来译码的指令段。由此可分析得知我们需要6-64译码器,以及5-32译码器。
表2.2 译码器内部信号说明
序号 | 接口名 | 宽度 | 作用 |
1 | op | 6 | 对应inst_i[31:26],用于译码输入 |
2 | op_d | 64 | op译码输出 |
3 | op1 | 5 | 对应inst_i[25:21],用于译码输入 |
4 | op1_d | 32 | op1译码输出 |
5 | sa | 5 | 对应inst_i[10:6],用于译码输入 |
6 | sa_d | 32 | sa译码输出 |
7 | func | 6 | 对应inst_i[5:0] |
8 | func_d | 64 | func译码输出 |
通过分析,我们得知译码器需要译码出reg1_read_o和reg2_read_o,以及aluop_o,wreg_o信号。信号和指令的关系,如表2.3所示。
表2.3 信号和指令的关系
add | addu | sub | subu | slt | sltu | and | or | xor | nor | sll | srl | sra | lui | |
reg1_read_o | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
reg2_read_o | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 |
wreg_o | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
aluop_o | 独热码编码 |
表2.4 寄存器地址说明
寄存器 | 说明 |
reg1_addr_o | inst_i[25:21] |
reg2_addr_o | inst_i[20:16] |
wd_o | inst_lui?inst_i[20:16]:inst_i[15:11] |
译码器设计代码
`timescale 1ns / 1ps
`include "defines.v"
module id(
input wire rst,
input wire[31:0] inst_i,
input wire[31:0] reg1_data_i,
input wire[31:0] reg2_data_i,
output wire[13:0] aluop_o,
output wire[31:0] reg1_o,
output wire[31:0] reg2_o,
output wire[4:0] wd_o,
output wire wreg_o,
output wire[4:0] reg1_addr_o,
output wire reg1_read_o,
output wire[4:0] reg2_addr_o,
output wire reg2_read_o
);
wire[5:0] op;
wire[63:0] op_d;
wire[4:0] op1;
wire[31:0] op1_d;
wire[4:0] sa;
wire[31:0] sa_d;
wire[5:0] func;
wire[63:0] func_d;
assign op = inst_i[31:26];
assign op1 = inst_i[25:21];
assign sa = inst_i[10:6];
assign func = inst_i[5:0];
decoder_6_64 d0(op,op_d);
decoder_5_32 d1(op1,op1_d);
decoder_5_32 d2(sa,sa_d);
decoder_6_64 d3(func,func_d);
wire inst_add,inst_addu,inst_sub,inst_subu,
inst_slt,inst_sltu,inst_and,inst_or,inst_xor,
inst_nor,inst_sll,inst_srl,inst_sra,inst_lui;
assign inst_add = op_d[`OpZero]&&sa_d[`SaZero]&&func_d[`FuncAdd];
assign inst_addu = op_d[`OpZero]&&sa_d[`SaZero]&&func_d[`FuncAddu];
assign inst_sub = op_d[`OpZero]&&sa_d[`SaZero]&&func_d[`FuncSub];
assign inst_subu = op_d[`OpZero]&&sa_d[`SaZero]&&func_d[`FuncSubu];
assign inst_slt = op_d[`OpZero]&&sa_d[`SaZero]&&func_d[`FuncSlt];
assign inst_sltu = op_d[`OpZero]&&sa_d[`SaZero]&&func_d[`FuncSltu];
assign inst_and = op_d[`OpZero]&&sa_d[`SaZero]&&func_d[`FuncAnd];
assign inst_or = op_d[`OpZero]&&sa_d[`SaZero]&&func_d[`FuncOr];
assign inst_xor = op_d[`OpZero]&&sa_d[`SaZero]&&func_d[`FuncXor];
assign inst_nor = op_d[`OpZero]&&sa_d[`SaZero]&&func_d[`FuncNor];
assign inst_sll = op_d[`OpZero]&&op1_d[`Op1Zero]&&func_d[`FuncSll];
assign inst_srl = op_d[`OpZero]&&op1_d[`Op1Zero]&&func_d[`FuncSrl];
assign inst_sra = op_d[`OpZero]&&op1_d[`Op1Zero]&&func_d[`FuncSra];
assign inst_lui = op_d[`OpLui]&&op1_d[`Op1Zero];
assign aluop_o =(rst==1)?14'b0: {inst_add,inst_addu,inst_sub,inst_subu,
inst_slt,inst_sltu,inst_and,inst_or,inst_xor,
inst_nor,inst_sll,inst_srl,inst_sra,inst_lui};
assign reg1_read_o=(rst==1)?
0:(!(inst_sll||inst_srl||inst_sra||inst_lui)?1:0);
assign reg2_read_o=(rst==1)?
0:(inst_lui?0:1);
assign wd_o=(rst==1)?
0:(inst_lui?inst_i[20:16]:inst_i[15:11]);
assign wreg_o=(rst==1)?0:1;
assign reg1_addr_o=(rst==1)?0:inst_i[25:21];
assign reg2_addr_o=(rst==1)?0:inst_i[20:16];
wire[31:0] imm;//jicunqi or lijishu
assign imm = inst_lui?{inst_i[15:0],16'b0}:{27'b0,inst_i[10:6]};
assign reg1_o=(rst==1)?
0:(reg1_read_o?reg1_data_i:imm);
assign reg2_o=(rst==1)?
0:(reg2_read_o?reg2_data_i:imm);
endmodule
译码器仿真代码
`timescale 1ns / 1ps
module id_tb(
);
reg rst;
reg[31:0] inst_i;
reg[31:0] reg1_data_i;
reg[31:0] reg2_data_i;
wire[13:0] aluop_o;
wire[31:0] reg1_o;
wire[31:0] reg2_o;
wire[4:0] wd_o;
wire wreg_o;
wire[4:0] reg1_addr_o;
wire reg1_read_o;
wire[4:0] reg2_addr_o;
wire reg2_read_o;
id id0(rst,inst_i,reg1_data_i,reg2_data_i,aluop_o,
reg1_o,reg2_o,wd_o,wreg_o,reg1_addr_o,reg1_read_o,
reg2_addr_o,reg2_read_o);
reg[31:0]regs[19:0];
integer i;
initial begin
$readmemh("F:\inst_rom.data",regs);
end
initial begin
rst=1;
#50
rst=0;
reg1_data_i=32'h12345678;
reg2_data_i=32'h11223344;
for(i=0;i<14;i=i+1)begin
inst_i=regs[i];
#20;
end
$finish;
end
endmodule
波形图
标签:wire,reg2,译码器,vivado,inst,&&,设计,reg1,assign From: https://blog.csdn.net/2301_80398020/article/details/145214992