单周期CPU(三)译码模块(minisys)(verilog)(vivado)

`timescale 1ns / 1ps
//

module Idecode32 (
    input           reset,
    input           clock,
    output  [31:0]  read_data_1,     // 输出的第一操作数
    output  [31:0]  read_data_2,     // 输出的第二操作数
    input   [31:0]  Instruction,     // 取指单元来的指令
    input   [31:0]  read_data,       // 从DATA RAM or I/O port取出的数据
    input   [31:0]  ALU_result,      // 从执行单元来的运算的结果,需要扩展立即数到32位
    input           Jal,             // 来自控制单元,说明是JAL指令 
    input           RegWrite,        // 来自控制单元
    input           MemtoReg,        // 来自控制单元
    input           RegDst,          // 来自控制单元
    output  [31:0]  Sign_extend,     // 译码单元输出的扩展后的32位立即数
    input   [31:0]  opcplus4        // 来自取指单元,JAL中用
);

    reg[31:0] register[0:31];              // 寄存器组共32个32位寄存器
    reg[4:0] write_register_address;        // 要写的寄存器的号
    reg[31:0] write_data;                   // 要写寄存器的数据放这里

    wire[4:0] read_register_1_address;     // 要读的第一个寄存器的号(rs)
    wire[4:0] read_register_2_address;     // 要读的第二个寄存器的号(rt)
    wire[4:0] write_register_address_1;    // r-form指令要写的寄存器的号(rd)
    wire[4:0] write_register_address_0;    // i-form指令要写的寄存器的号(rt)
    wire[15:0] Instruction_immediate_value; // 指令中的立即数
    wire[5:0] opcode;                      // 指令码

    assign opcode = Instruction[31:26];    // OP
    assign read_register_1_address = Instruction[25:21]; // rs
    assign read_register_2_address = Instruction[20:16]; // rt
    assign write_register_address_1 = Instruction[15:11]; // rd (r-form)
    assign write_register_address_0 = Instruction[20:16]; // rt (i-form)
    assign Instruction_immediate_value = Instruction[15:0]; // data, rladr (i-form)

    wire sign; // 取符号位的值

    assign sign = Instruction[15]; // 取指令的第15位作为符号位

    assign Sign_extend[31:16] = (sign) ? {16{1'b1}} : {16{1'b0}}; // 符号扩展,根据符号位填充高位
    assign Sign_extend[15:0] = Instruction[15:0]; // 将原始的16位立即数填充到低位

    assign read_data_1 = register[read_register_1_address]; // 从寄存器组中读取第一个源寄存器的数据
    assign read_data_2 = register[read_register_2_address]; // 从寄存器组中读取第二个源寄存器的数据

    always @* begin
        if (Jal) begin
            write_register_address = 5'b11111; // JAL指令的目标寄存器是31号寄存器
        end else begin
            if (RegDst) begin
                write_register_address = write_register_address_1; // r-form指令的目标寄存器地址
            end else begin
                write_register_address = write_register_address_0; // i-form指令的目标寄存器地址
            end
        end
    end

    always @* begin
        if (MemtoReg) begin
            write_data = read_data; // 数据来自数据RAM的输出
        end else begin
            write_data = ALU_result; // 运算指令的数据来自ALU_result
        end
    end

    integer i;
    always @(posedge clock) begin
        if (reset == 1) begin
            for (i = 0; i < 32; i = i + 1)
                register[i] <= 0; // 初始化寄存器组,将所有寄存器清零
        end else if (RegWrite == 1) begin
            if (write_register_address != 5'b00000) begin
                register[write_register_address] <= write_data; // 写入数据到目标寄存器,除了0号寄存器
            end
        end
    end

endmodule

仿真代码如下

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 
// Design Name: 
// Module Name: idcode32_sim
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module idcode32_sim ();

    // input 
    reg[31:0]  Instruction = 32'b000000_00010_00011_00111_00000_100000; //add $7,$2,$3
    reg[31:0]  read_data = 32'h00000000;                    //  从DATA RAM or I/O port取出的数据
    reg[31:0]  ALU_result = 32'h00000005;                   //  需要扩展立即数到32位
    reg        Jal = 1'b0; 
    reg        RegWrite = 1'b1;
    reg        MemtoReg = 1'b0;
    reg        RegDst = 1'b1;
    reg         clock = 1'b0 ,reset = 1'b1;
    reg[31:0]  opcplus4 = 32'h00000004;                 // 来自取指单元,JAL中用
    // output
    wire[31:0] read_data_1;
    wire[31:0] read_data_2;
    wire[31:0] Sign_extend;
    
	Idecode32 Uid (
		.reset			(reset),		// 复位(高电平有效)
		.clock			(clock),		// CPU时钟
		.read_data_1	(read_data_1),	// 输出的第一操作数
		.read_data_2	(read_data_2),	// 输出的第二操作数
		.Instruction	(Instruction),	// 取指单元来的指令
		.read_data		(read_data),	// 从DATA RAM or I/O port取出的数据
		.ALU_result		(ALU_result),	// 从执行单元来的运算的结果,需要扩展立即数到32位
		.Jal			(Jal),			// 来自控制单元,说明是JAL指令 
		.RegWrite		(RegWrite),		// 来自控制单元
		.MemtoReg	(MemtoReg),		// 来自控制单元
		.RegDst			(RegDst),		// 来自控制单元
		.Sign_extend	(Sign_extend),	// 扩展后的32位立即数
		.opcplus4		(opcplus4)		// 来自取指单元,JAL中用
	);

    initial begin
        #200   reset = 1'b0;
        #200   begin Instruction = 32'b001000_00111_00011_1000000000110111;  //addi $3,$7,0X8037
                    read_data = 32'h00000000; 
                    ALU_result = 32'hFFFF803C;
                    Jal = 1'b0;
                    RegWrite = 1'b1;
                    MemtoReg = 1'b0;
                    RegDst = 1'b0;
                    opcplus4 = 32'h00000008; 
               end
        #200   begin Instruction = 32'b001100_00010_00100_1000000010010111;  //andi $4,$2,0X8097
                           read_data = 32'h00000000; 
                           ALU_result = 32'h00000002;
                           Jal = 1'b0;
                           RegWrite = 1'b1;
                           MemtoReg = 1'b0;
                           RegDst = 1'b0;
                           opcplus4 = 32'h0000000c; 
                end
        #200   begin Instruction = 32'b000000_00000_00001_00101_00010_000000;  //sll $5,$1,2
                                   read_data = 32'h00000000; 
                                   ALU_result = 32'h00000004;
                                   Jal = 1'b0;
                                   RegWrite = 1'b1;
                                   MemtoReg = 1'b0;
                                   RegDst = 1'b1;
                                   opcplus4 = 32'h00000010; 
               end
        #200   begin Instruction = 32'b100011_00000_00110_0000000100000000;  //LW $6,0(0X100)
                                          read_data = 32'h0000007B; 
                                          ALU_result = 32'h00000054;
                                          Jal = 1'b0;
                                          RegWrite = 1'b1;
                                          MemtoReg = 1'b1;
                                          RegDst = 1'b0;
                                          opcplus4 = 32'h00000014; 
               end
        #200   begin Instruction = 32'b000011_00000000000000000000000000;  //JAL 0000
                                          read_data = 32'h00000000; 
                                          ALU_result = 32'h00000004;
                                          Jal = 1'b1;
                                          RegWrite = 1'b1;
                                          MemtoReg = 1'b0;
                                          RegDst = 1'b0;
                                          opcplus4 = 32'h00000018; 
               end
    end 
    always #50 clock = ~clock;            
endmodule

仿真波形图如下图

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值