【计算机系统设计】实践笔记(3)改进数据通路:jr指令分析与实现

本文探讨了一种对jr指令的改进,涉及PC更新的多路选择器设计、控制信号Jrn的引入,以及新数据通路和控制器模块的实现。通过实例和代码展示了如何调整PC寄存器和控制逻辑,以支持无条件跳转和寄存器依赖的PC修改。
摘要由CSDN通过智能技术生成

1 jr指令分析

instructionoprsrtrdshamtfunc
jr000000rs000000000000000001000

举例:jr $31
功能:PC <- ($31)

这是个跳转指令,将指定寄存器的值,放入PC中,是无条件跳转

我们需要

  1. 更新PC,加一个多路选择器,实现+4PC <- (reg)两种选择
  2. 增加控制信号Jrn,标识jr指令

2 新的数据通路

在这里插入图片描述

3 器件修改

  1. 控制器,控制信号输出Jrn标识jr指令
  2. PC,增加输入信号jr和输入数据32位寄存器值

控制信号:

instructionopfuncALUopRegWriteSftmdJrn
jr0000000010001111001

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 data
           input [31:0] pcOrigin,  // The PC value is from pcOld.
           input [31:0] JrPC,   // jr instruction,from reg files.

           // pc control
           input Jrn,   // jr instruction.

           output [31:0] pcOld
       );


reg [31:0] pc = 0;
assign pcOld = pc;

wire [31:0] pcSelect; // new pc data

assign pcSelect = (Jrn == 0) ? (pcOrigin + 4): JrPC;

// Update PC register
always @(posedge clk)
begin
    if(rst_n == 1) // Xilinx 官方推荐:reset 高电平有效
    begin
        pc <= 0;
    end
    else
    begin
        pc <= pcSelect;
    end
end


endmodule

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/sra
           output reg [3:0] ALUop,
           output reg Jrn   // jr instruction
       );

always @(*)
begin
    if(op == 6'b0)
    begin
        case (func)
            6'b100000:  // add
            begin
                RegWrite <= 1;
                Sftmd <= 0;
                ALUop <= 4'b0000;
                Jrn <= 0;
            end
            6'b100001:  // addu
            begin
                RegWrite <= 1;
                Sftmd <= 0;
                ALUop <= 4'b0001;
                Jrn <= 0;
            end
            6'b100010:  // sub
            begin
                RegWrite <= 1;
                Sftmd <= 0;
                ALUop <= 4'b0010;
                Jrn <= 0;
            end
            6'b100011:  // subu
            begin
                RegWrite <= 1;
                Sftmd <= 0;
                ALUop <= 4'b0011;
                Jrn <= 0;
            end
            6'b100100:  // and
            begin
                RegWrite <= 1;
                Sftmd <= 0;
                ALUop <= 4'b0100;
                Jrn <= 0;
            end
            6'b100101:  // or
            begin
                RegWrite <= 1;
                Sftmd <= 0;
                ALUop <= 4'b0101;
                Jrn <= 0;
            end
            6'b100110:  // xor
            begin
                RegWrite <= 1;
                Sftmd <= 0;
                ALUop <= 4'b0110;
                Jrn <= 0;
            end
            6'b100111:  // nor
            begin
                RegWrite <= 1;
                Sftmd <= 0;
                ALUop <= 4'b0111;
                Jrn <= 0;
            end
            6'b101010:  // slt
            begin
                RegWrite <= 1;
                Sftmd <= 0;
                ALUop <= 4'b1000;
                Jrn <= 0;
            end
            6'b101011:  // sltu
            begin
                RegWrite <= 1;
                Sftmd <= 0;
                ALUop <= 4'b1001;
                Jrn <= 0;
            end
            6'b000100:  // sllv
            begin
                RegWrite <= 1;
                Sftmd <= 0;
                ALUop <= 4'b1010;
                Jrn <= 0;
            end
            6'b000110:  // srlv
            begin
                RegWrite <= 1;
                Sftmd <= 0;
                ALUop <= 4'b1011;
                Jrn <= 0;
            end
            6'b000111:  // srav
            begin
                RegWrite <= 1;
                Sftmd <= 0;
                ALUop <= 4'b1100;
                Jrn <= 0;
            end
            6'b000000:  // sll
            begin
                RegWrite <= 1;
                Sftmd <= 1;
                ALUop <= 4'b1010;
                Jrn <= 0;
            end
            6'b000010:  // srl
            begin
                RegWrite <= 1;
                Sftmd <= 1;
                ALUop <= 4'b1011;
                Jrn <= 0;
            end
            6'b000011:  // sra
            begin
                RegWrite <= 1;
                Sftmd <= 1;
                ALUop <= 4'b1100;
                Jrn <= 0;
            end
            6'b001000:
            begin
                RegWrite <= 0;
                Sftmd <= 0;
                ALUop <= 4'b1111;
                Jrn <= 1;
            end
            default:
            begin
                RegWrite <= 0;
                Sftmd <= 0;
                ALUop <= 4'b1111;
                Jrn <= 0;
            end
        endcase
    end
    else
    begin
        RegWrite <= 0;
        Sftmd <= 0;
        ALUop <= 4'b1111;
        Jrn <= 0;
    end
end

endmodule

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 = 1

and $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) = 11111111111110111

slt $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 = 4

jr $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;

测试完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XV_

感谢您的认可,我会继续努力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值