自学内容网 自学内容网

单周期CPU设计(二)取指模块(minisys)(verilog)(vivado)

`timescale 1ns / 1ps
//
module Ifetc32 (
inputreset,// 复位信号(高电平有效)
    inputclock,// 时钟(23MHz)
output[31:0]Instruction,// 输出指令到其他模块
    output[31:0]PC_plus_4_out,// (pc+4)送执行单元
    input[31:0]Add_result,// 来自执行单元,算出的跳转地址
    input[31:0]Read_data_1,// 来自译码单元,jr指令用的地址
    inputBranch,// 来自控制单元
    inputnBranch,// 来自控制单元
    inputJmp,// 来自控制单元
    inputJal,// 来自控制单元
    inputJrn,// 来自控制单元
    inputZero,// 来自执行单元
    output[31:0]opcplus4,// JAL指令专用的PC+4
    // ROM Pinouts
output[13:0]rom_adr_o,// 给程序ROM单元的取指地址
input[31:0]Jpadr// 从程序ROM单元中获取的指令
);
    
    wire [31:0] PC_plus_4;
    reg [31:0] PC;
    reg [31:0] next_PC;// 下条指令的PC(不一定是PC+4)
    reg [31:0] opcplus4;
    
// ROM Pinouts
assign rom_adr_o = PC[15:2];
assign Instruction = Jpadr;
    

assign PC_plus_4[31:2] = PC[31:2] + 4;
assign PC_plus_4[1:0] = 2'b00;
assign PC_plus_4_out = PC_plus_4[31:0];
 

    always @* begin  // beq $n ,$m if $n=$m branch   bne if $n /=$m branch jr
    

        if (Branch && Zero) begin
            next_PC = PC + Add_result;
        end else if (nBranch && !Zero) begin
            next_PC = PC + Add_result;
        end else if (Jrn) begin
            next_PC = Read_data_1;
        end else begin
            next_PC = PC_plus_4;
        end
    end
  // 请考虑以上三条指令的判断条件,
                                // 以及三条指令的执行该给next_PC赋什么值

    
   always @(negedge clock) begin
                                    if (reset) begin
                                        PC <= 32'h00000000;
                                        opcplus4 <= 32'h00000000;
                                    end else begin
                                        PC <= next_PC;
                                        if (Jal) begin
                                            opcplus4 <= PC + 4;
                                        end else begin
                                            opcplus4 <= 32'h00000000;
                                        end
                                    end
                                end

endmodule

仿真代码如下

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


module ifetc32_sim ();
    // input
    reg[31:0]  Add_result = 32'h00000000;
    reg[31:0]  Read_data_1 = 32'h00000000;
    reg        Branch = 1'b0;
    reg        nBranch = 1'b0;
    reg        Jmp = 1'b0;
    reg        Jal = 1'b0;
    reg        Jrn = 1'b0;
    reg        Zero = 1'b0;
    reg        clock = 1'b0,reset = 1'b1;

    // output
    wire [31:0] Instruction;            // 输出指令
    wire [31:0] PC_plus_4_out;
    wire [31:0] opcplus4;
wire [13:0] rom_adr;
wire [31:0] Jpadr;

Ifetc32 Uif (
.reset(reset),// 复位(高电平有效)
.clock(clock),// CPU时钟
.Instruction(Instruction),// 输出指令到其他模块
.PC_plus_4_out(PC_plus_4_out),// (pc+4)送执行单元
.Add_result(Add_result),// 来自执行单元,算出的跳转地址
.Read_data_1(Read_data_1),// 来自译码单元,jr指令用的地址
.Branch(Branch),// 来自控制单元
.nBranch(nBranch),// 来自控制单元
.Jmp(Jmp),// 来自控制单元
.Jal(Jal),// 来自控制单元
.Jrn(Jrn),// 来自控制单元
.Zero(Zero),// 来自执行单元
.opcplus4(opcplus4),// JAL指令专用的PC+4
// ROM Pinouts
.rom_adr_o(rom_adr),// 给程序ROM单元的取指地址
.Jpadr(Jpadr)// 从程序ROM单元中获取的指令
);

// 分配64KB ROM, 编译器实际只用 64KB ROM
    prgrom instmem (
        .clka(clock),
.wea(0),
        .addra(rom_adr),
.dina(0),
        .douta(Jpadr)
    );

    initial begin
        #100   reset = 1'b0;
        #100   Jal = 1;
        #100   begin Jrn = 1;Jal = 0; Read_data_1 = 32'h0000019c;end;
        #100   begin Jrn = 0;Branch = 1'b1; Zero = 1'b1; Add_result = 32'h00000020;end;        
        #100   begin Branch = 1'b0; Zero = 1'b0; end;        
    end
    always #50 clock = ~clock;
endmodule

仿真波形图如下

 

 


原文地址:https://blog.csdn.net/m0_74626628/article/details/140555221

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!