1 jr指令分析
instruction | op | rs | rt | rd | shamt | func |
---|---|---|---|---|---|---|
jr | 000000 | rs | 00000 | 00000 | 00000 | 001000 |
举例:jr $31
功能:PC <- ($31)
这是个跳转指令,将指定寄存器的值,放入PC中,是无条件跳转。
我们需要
- 更新PC,加一个多路选择器,实现
+4
和PC <- (reg)
两种选择 - 增加控制信号
Jrn
,标识jr
指令
2 新的数据通路
3 器件修改
- 控制器,控制信号输出
Jrn
标识jr
指令 - PC,增加输入信号
jr
和输入数据32位寄存器值
控制信号:
instruction | op | func | ALUop | RegWrite | Sftmd | Jrn |
---|---|---|---|---|---|---|
jr | 000000 | 001000 | 1111 | 0 | 0 | 1 |
4 代码实现
4.1 PC
增加了输入信号和输入数据,更改了原来的pcNew
的名称为pcOrigin
,增加了多路选择器。
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/11/12 20:31:59
// Design Name:
// Module Name: pc_1
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module pc_1(input clk,input rst_n,// pc datainput [31:0] pcOrigin, // The PC value is from pcOld.input [31:0] JrPC, // jr instruction,from reg files.// pc controlinput Jrn, // jr instruction.output [31:0] pcOld);reg [31:0] pc = 0;
assign pcOld = pc;wire [31:0] pcSelect; // new pc dataassign pcSelect = (Jrn == 0) ? (pcOrigin + 4): JrPC;// Update PC register
always @(posedge clk)
beginif(rst_n == 1) // Xilinx 官方推荐:reset 高电平有效beginpc <= 0;endelsebeginpc <= pcSelect;end
endendmodule
4.2 control
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/11/14 22:30:48
// Design Name:
// Module Name: control_1
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module control_1(input [5:0] op,input [5:0] func,output reg RegWrite,output reg Sftmd, // indicate the instruction is sll/srl/sraoutput reg [3:0] ALUop,output reg Jrn // jr instruction);always @(*)
beginif(op == 6'b0)begincase (func)6'b100000: // addbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b0000;Jrn <= 0;end6'b100001: // addubeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b0001;Jrn <= 0;end6'b100010: // subbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b0010;Jrn <= 0;end6'b100011: // sububeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b0011;Jrn <= 0;end6'b100100: // andbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b0100;Jrn <= 0;end6'b100101: // orbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b0101;Jrn <= 0;end6'b100110: // xorbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b0110;Jrn <= 0;end6'b100111: // norbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b0111;Jrn <= 0;end6'b101010: // sltbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b1000;Jrn <= 0;end6'b101011: // sltubeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b1001;Jrn <= 0;end6'b000100: // sllvbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b1010;Jrn <= 0;end6'b000110: // srlvbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b1011;Jrn <= 0;end6'b000111: // sravbeginRegWrite <= 1;Sftmd <= 0;ALUop <= 4'b1100;Jrn <= 0;end6'b000000: // sllbeginRegWrite <= 1;Sftmd <= 1;ALUop <= 4'b1010;Jrn <= 0;end6'b000010: // srlbeginRegWrite <= 1;Sftmd <= 1;ALUop <= 4'b1011;Jrn <= 0;end6'b000011: // srabeginRegWrite <= 1;Sftmd <= 1;ALUop <= 4'b1100;Jrn <= 0;end6'b001000:beginRegWrite <= 0;Sftmd <= 0;ALUop <= 4'b1111;Jrn <= 1;enddefault:beginRegWrite <= 0;Sftmd <= 0;ALUop <= 4'b1111;Jrn <= 0;endendcaseendelsebeginRegWrite <= 0;Sftmd <= 0;ALUop <= 4'b1111;Jrn <= 0;end
endendmodule
4.3 datapath
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/11/27 11:41:34
// Design Name:
// Module Name: datapath_1
// Project Name:
// Target Devices:
// Tool Versions:
// Description: 仅仅实现了几个简单的R类指令的最简单的数据通路,不与外界交互
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module datapath_1(input clk,input rst_n,output [31:0] result // 测试syntheses,没有输出的模块是恐怖的);/******** PC ********/// pc_1 Inputs
wire Jrn;
wire [31:0] JrPC;// pc_1 Outputs
wire [31:0] pcOld;pc_1 u_pc_1 (.clk ( clk ),.rst_n ( rst_n ),.pcOrigin ( pcOld ),.JrPC ( JrPC ),.Jrn ( Jrn ),.pcOld ( pcOld ));/******** Instruction ROM ********/// blk_mem_gen_0 Inputs
// wire [13:0] addra = pcOld[15:2];// blk_mem_gen_0 Outputs // instructions
wire [31:0] instruction;blk_mem_gen_0 u_blk_mem_gen_0 (.clka ( clk ),.addra ( pcOld[15:2] ),.douta ( instruction ));/******** Reg Files ********/// reg_files_1 Inputs
wire [31:0] ALUresult;/// wire [4:0] rA = instruction[25:21];
/// wire [4:0] rB = instruction[20:16];
/// wire [4:0] rW = instruction[15:11];
/// wire [31:0] writeData = ALUresult;
wire RegWrite;// reg_files_1 Outputs
wire [31:0] A; // rs
wire [31:0] B; // rt
assign JrPC = A;reg_files_1 u_reg_files_1 (.clk ( clk ),.rst_n ( rst_n ),.rA ( instruction[25:21] ),.rB ( instruction[20:16] ),.rW ( instruction[15:11] ),.writeData ( ALUresult ),.RegWrite ( RegWrite ),.A ( A ),.B ( B ));/******** ALU ********/// ALU_1 Inputs
// wire [31:0] A;
// wire [31:0] B;
wire [3:0] ALUop;
wire Sftmd;// ALU_1 Outputs
// wire [31:0] ALUresult = writeData; // 【不能用!传输方向不对】ALU_1 u_ALU_1 (.A ( A ),.B ( B ),.shamt ( instruction[10:6]),.ALUop ( ALUop ),.Sftmd ( Sftmd ),.ALUresult ( ALUresult ));/******** controler ********/// control_1 Inputs
// wire [5:0] op = instruction[31:26];
// wire [5:0] func = instruction[5:0];// control_1 Outputs
// wire RegWrite
// wire [3:0] ALUop;control_1 u_control_1 (.op ( instruction[31:26] ),.func ( instruction[5:0] ),.RegWrite ( RegWrite ),.Sftmd ( Sftmd ),.ALUop ( ALUop ),.Jrn ( Jrn ));assign result = ALUresult;endmodule
5 测试
可以观察到跳变了。
nop
add $1,$2,$3 # $1 = 2 + 3 = 5
addu $2,$4,$1 # $2 = 4 + 5 = 9
sub $4,$2,$1 # $4 = 9 - 5 = 4
subu $5,$4,$3 # $5 = 4 - 3 = 1and $6,$7,$8 # $6 = 0111 and 1000 = 0
or $7,$6,$8 # $7 = 0 or 1000 = 8
xor $7,$6,$8 # $7 = 0000 xor 1000 = 1000 = 8
nor $8,$7,$6 # $8 = not (1000 or 0) = 11111111111110111slt $10,$11,$12 # $10 = 11 < 12 = 1 # 应该用负数验证,以后再说
sltu $10,$12,$11 # $10 = 12 > 11 = 0# sllv $12,$5,$13 # $12 = 1101 << 1 = 1101_0 = 1A 【注意此处的倒置问题! sllv rd,rt,rs】
# srlv $12,$5,$13 # $12 = 1101 >> 1 = 110 = 6
# srav $14,$5,$15 # $14 = 1111 >>> 1 = 111 = 7 应该用负数验证,以后再说# 上面3条是错误的!我们应该改的不是使用,而是内部运算逻辑
# 对于使用者来说,逻辑就是 $13 << $5
# 而实际的编码是 rt = $13,rs = $5,这与一般的指令不一样
# 因此,我们在ALU运算中 rt--B,rs--A,应该是 【B << A】,而不是 A >> B。
sllv $12,$13,$5 # $12 = 1101 << 1 = 1101_0 = 1A
srlv $12,$13,$5 # $12 = 1101 >> 1 = 110 = 6
srav $14,$15,$5 # $14 = 1111 >>> 1 = 111 = 7 应该用负数验证,以后再说sll $16,$17,2 # $16 = 1_0001 << 2 = 100_0100 = 44
srl $16,$18,2 # $16 = 1_0010 >> 2 = 0100 = 4
sra $16,$19,2 # 应该用负数验证,以后再说 $16 = 4jr $16 # PC = 4
编码
memory_initialization_radix = 16;
memory_initialization_vector =
00000000,
00430820,
00811021,
00412022,
00832823,
00e83024,
00c83825,
00c83826,
00e64027,
016c502a,
018b502b,
00ad6004,
00ad6006,
00af7007,
00118080,
00128082,
00138083,
02000008;
测试完成。