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

接下来的分析和实践非常粗糙,因为跟之前一样的分析流程,不再多说了,如果前面真的掌握,这里不看也罢。

分析

先看beq指令。

ALU输入的是rs和rt,不输入imm,进行subu操作,判断是否为zero,输出zero信号。

控制器增加Branch信号,识别beq指令,当zero和Branch同时成立,就可以跳转,目标地址是PC + 4 + (sign-extend)offset。

bne指令同理。

实现

ALU

ALU增加zero输出,如果rs - rt == 0zero = 0,即rs = rt,对应beq指令,若zero = 1,对应bne指令

增加offset输出,是offset字段符号扩展并左移2位后的结果,用于和pc + 4在pc模块相加。

pc

增加offset数据信号,以及Branch和nBranch跳转信号,和zero信号。

control

增加BranchnBranch信号。

Datapath

最后更改顶层数据通路。

注意一个大坑

我们设计的数据通路,取指需要2个周期,这个时候,跳转指令的pc,其实已经变成了pc + 8了,如果再执行 pc + 4 + offset,就会执行原本应该执行的下下条指令,这是错误的

因此,我们应该将PC + 4的值,与当前执行的PC指令,一起传过去。这里偷懒起见,直接在原来基础上PC - 8以避开2个时钟周期的取指延迟。

关于取指延迟对需要pc值的指令的影响,可能有不少,后续再说

在这里插入图片描述
可以看见,ROM延迟两个时钟周期,因此说,刚才的解决方案,也不对……即便能够跳转到正确的指令,但是,在此之前,如果有指令不需要执行,但是也被执行了,每一个b跳转指令,最多被错误地执行2条指令

……这可咋办呢?这是单周期,又不是流水线……如何改变局面?

后续再说。

类比:这个情况下,似乎是类流水线了,分为取指和执行2个阶段!……嗯,回头想想解决方案吧

尝试一

取指占2个时钟周期,执行占1个时钟周期,每条指令执行占3个时钟周期。

`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.

           // beq bne
           input [31:0] offset,
           input zero,
           input Branch,
           input nBranch,

           output [31:0] pcOld
       );


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


// judge validity of beq/bne instruction
reg isBranch;
always @(*)
begin
    if((zero == 1) && (Branch == 1)) // beq valid
    begin
        isBranch <= 1;
    end
    else if((zero == 0) && (nBranch == 1)) // bne valid
    begin
        isBranch <= 1;
    end
    else
    begin
        isBranch <= 0;
    end
end


// select new pc value
reg [31:0] pcSelect; // new pc data
always @(*)
begin
    case({Jrn,Branch,nBranch})
        3'b000: // pc + 4
            pcSelect <= pcOrigin + 4;
        3'b100: // jr
            pcSelect <= JrPC;
        3'b010: // beq
            pcSelect <= pcOrigin + 4 + offset;  /**** NOTE ****/
        3'b001: // bne // fetch instruction waste 2 clock cycles,then execute 1 cycle
            pcSelect <= pcOrigin + 4 + offset;  /**** NOTE ****/
        default:
            pcSelect <= 0;
    endcase
end


// counter: wait 2 clock cycles to fetch instruction
reg counter = 0;
always @(posedge clk)
begin
    if(counter == 1)
        counter <= 0;
    else
        counter <= counter + 1;
end


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


endmodule

加了计时器,但是,还是解决不了问题……

在这里插入图片描述

现在,能够满足当前执行的指令,pc值是下一条指令的地址,但是更新存在问题,依然避不开的是,取指需要2个时钟周期

问题解决:让CPU与Memory的时钟频率不一样!

首先,我们需要知道,CPU和Memory内外有别,它们的clk频率完全可以不一样,这样,我们让Memory的频率快一点,使得CPU在一个时钟周期内,完成取指和执行,就满足了我们的设计要求。

这里需要强化一个概念,我们需要知道,单周期CPU,指的是CPU在一个时钟周期内能够完成一条指令的取指和执行操作单周期指的是CPU,而不是Memory。

实践笔记(5)插叙:内外有别之CPU和Memory

1 解决方案

1.1 增加时钟分频器

在这里插入图片描述在这里插入图片描述
使用MMCM,不是PLL

在这里插入图片描述
在这里插入图片描述
注意,此IP核有启动时间。

在这里插入图片描述
另外……当仿真没有信号的时候,看看是不是没有加信号……
在这里插入图片描述

1.2 分别对待CPU与Memory的时钟频率

CPU时钟频率20MHz
内存时钟频率100MHz

1.3 其他部件的实现

PC

`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.

           // beq bne
           input [31:0] offset,
           input zero,
           input Branch,
           input nBranch,

           output [31:0] pcOld
       );


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


// judge validity of beq/bne instruction
reg isBranch;
always @(*)
begin
    if((zero == 1) && (Branch == 1)) // beq valid
    begin
        isBranch <= 1;
    end
    else if((zero == 0) && (nBranch == 1)) // bne valid
    begin
        isBranch <= 1;
    end
    else
    begin
        isBranch <= 0;
    end
end


// select new pc value
reg [31:0] pcSelect; // new pc data
always @(*)
begin
    case({Jrn,isBranch})
        2'b00: // pc + 4
            pcSelect <= pcOrigin + 4;
        2'b10: // jr
            pcSelect <= JrPC;
        // fetching 1 instruction wastes 2 clock cycles(memory), and
        // executing the instruction needs 1 clock cycle(CPU).
        // NOTE:the frequency of two clocks is different. 
        2'b01: // beq bne
            pcSelect <= pcOrigin + 4 + offset;    
        default:
            pcSelect <= 0;
    endcase
end



// Update PC register
always @(posedge clk)
begin
    if(rst_n == 1) // Xilinx suggest:reset high level effective
    begin
        pc <= 0;
    end
    else
    begin
        pc <= pcSelect;
    end
end


endmodule

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
           output reg Lui,   // lui instruction
           output reg RegDst,
           output reg ALUSrc,
           output reg Zero_sign_ex,
           output reg Branch,   // beq
           output reg nBranch   // bne
       );

always @(*)
begin
    case(op)
        6'b000000:   R-type 
        begin
            case (func)
                6'b100000:  // add
                begin
                    RegWrite <= 1;
                    Sftmd <= 0;
                    ALUop <= 4'b0000;
                    Jrn <= 0;
                    Lui <= 0;
                    RegDst <= 1;
                    ALUSrc <= 0;
                    Zero_sign_ex <= 0;
                    Branch <= 0;
                    nBranch <= 0;

                end
                6'b100001:  // addu
                begin
                    RegWrite <= 1;
                    Sftmd <= 0;
                    ALUop <= 4'b0001;
                    Jrn <= 0;
                    Lui <= 0;
                    RegDst <= 1;
                    ALUSrc <= 0;
                    Zero_sign_ex <= 0;
                    Branch <= 0;
                    nBranch <= 0;

                end
                6'b100010:  // sub
                begin
                    RegWrite <= 1;
                    Sftmd <= 0;
                    ALUop <= 4'b0010;
                    Jrn <= 0;
                    Lui <= 0;
                    RegDst <= 1;
                    ALUSrc <= 0;
                    Zero_sign_ex <= 0;
                    Branch <= 0;
                    nBranch <= 0;

                end
                6'b100011:  // subu
                begin
                    RegWrite <= 1;
                    Sftmd <= 0;
                    ALUop <= 4'b0011;
                    Jrn <= 0;
                    Lui <= 0;
                    RegDst <= 1;
                    ALUSrc <= 0;
                    Zero_sign_ex <= 0;
                    Branch <= 0;
                    nBranch <= 0;

                end
                6'b100100:  // and
                begin
                    RegWrite <= 1;
                    Sftmd <= 0;
                    ALUop <= 4'b0100;
                    Jrn <= 0;
                    Lui <= 0;
                    RegDst <= 1;
                    ALUSrc <= 0;
                    Zero_sign_ex <= 0;
                    Branch <= 0;
                    nBranch <= 0;

                end
                6'b100101:  // or
                begin
                    RegWrite <= 1;
                    Sftmd <= 0;
                    ALUop <= 4'b0101;
                    Jrn <= 0;
                    Lui <= 0;
                    RegDst <= 1;
                    ALUSrc <= 0;
                    Zero_sign_ex <= 0;
                    Branch <= 0;
                    nBranch <= 0;

                end
                6'b100110:  // xor
                begin
                    RegWrite <= 1;
                    Sftmd <= 0;
                    ALUop <= 4'b0110;
                    Jrn <= 0;
                    Lui <= 0;
                    RegDst <= 1;
                    ALUSrc <= 0;
                    Zero_sign_ex <= 0;
                    Branch <= 0;
                    nBranch <= 0;

                end
                6'b100111:  // nor
                begin
                    RegWrite <= 1;
                    Sftmd <= 0;
                    ALUop <= 4'b0111;
                    Jrn <= 0;
                    Lui <= 0;
                    RegDst <= 1;
                    ALUSrc <= 0;
                    Zero_sign_ex <= 0;
                    Branch <= 0;
                    nBranch <= 0;

                end
                6'b101010:  // slt
                begin
                    RegWrite <= 1;
                    Sftmd <= 0;
                    ALUop <= 4'b1000;
                    Jrn <= 0;
                    Lui <= 0;
                    RegDst <= 1;
                    ALUSrc <= 0;
                    Zero_sign_ex <= 0;
                    Branch <= 0;
                    nBranch <= 0;

                end
                6'b101011:  // sltu
                begin
                    RegWrite <= 1;
                    Sftmd <= 0;
                    ALUop <= 4'b1001;
                    Jrn <= 0;
                    Lui <= 0;
                    RegDst <= 1;
                    ALUSrc <= 0;
                    Zero_sign_ex <= 0;
                    Branch <= 0;
                    nBranch <= 0;

                end
                6'b000100:  // sllv
                begin
                    RegWrite <= 1;
                    Sftmd <= 0;
                    ALUop <= 4'b1010;
                    Jrn <= 0;
                    Lui <= 0;
                    RegDst <= 1;
                    ALUSrc <= 0;
                    Zero_sign_ex <= 0;
                    Branch <= 0;
                    nBranch <= 0;

                end
                6'b000110:  // srlv
                begin
                    RegWrite <= 1;
                    Sftmd <= 0;
                    ALUop <= 4'b1011;
                    Jrn <= 0;
                    Lui <= 0;
                    RegDst <= 1;
                    ALUSrc <= 0;
                    Zero_sign_ex <= 0;
                    Branch <= 0;
                    nBranch <= 0;

                end
                6'b000111:  // srav
                begin
                    RegWrite <= 1;
                    Sftmd <= 0;
                    ALUop <= 4'b1100;
                    Jrn <= 0;
                    Lui <= 0;
                    RegDst <= 1;
                    ALUSrc <= 0;
                    Zero_sign_ex <= 0;
                    Branch <= 0;
                    nBranch <= 0;

                end
                6'b000000:  // sll
                begin
                    RegWrite <= 1;
                    Sftmd <= 1;
                    ALUop <= 4'b1010;
                    Jrn <= 0;
                    Lui <= 0;
                    RegDst <= 1;
                    ALUSrc <= 0;
                    Zero_sign_ex <= 0;
                    Branch <= 0;
                    nBranch <= 0;

                end
                6'b000010:  // srl
                begin
                    RegWrite <= 1;
                    Sftmd <= 1;
                    ALUop <= 4'b1011;
                    Jrn <= 0;
                    Lui <= 0;
                    RegDst <= 1;
                    ALUSrc <= 0;
                    Zero_sign_ex <= 0;
                    Branch <= 0;
                    nBranch <= 0;

                end
                6'b000011:  // sra
                begin
                    RegWrite <= 1;
                    Sftmd <= 1;
                    ALUop <= 4'b1100;
                    Jrn <= 0;
                    Lui <= 0;
                    RegDst <= 1;
                    ALUSrc <= 0;
                    Zero_sign_ex <= 0;
                    Branch <= 0;
                    nBranch <= 0;

                end
                6'b001000:  // jr
                begin
                    RegWrite <= 0;
                    Sftmd <= 0;
                    ALUop <= 4'b1111;
                    Jrn <= 1;
                    Lui <= 0;
                    RegDst <= 1;
                    ALUSrc <= 0;
                    Zero_sign_ex <= 0;
                    Branch <= 0;
                    nBranch <= 0;

                end
                default:
                begin
                    RegWrite <= 0;
                    Sftmd <= 0;
                    ALUop <= 4'b1111;
                    Jrn <= 0;
                    Lui <= 0;
                    RegDst <= 1;
                    ALUSrc <= 0;
                    Zero_sign_ex <= 0;
                    Branch <= 0;
                    nBranch <= 0;
                end
            endcase
        end
        
        /*************** I-type ***************/
        
        6'b001000:  // addi
        begin
            ALUop <= 4'b0000;
            RegWrite <= 1;
            Sftmd <= 0;
            Jrn <= 0;
            Lui <= 0;
            RegDst <= 0;
            ALUSrc <= 1;
            Zero_sign_ex <= 1;
            Branch <= 0;
            nBranch <= 0;
        end
        6'b001001:  // addiu
        begin
            ALUop <= 4'b0001;
            RegWrite <= 1;
            Sftmd <= 0;
            Jrn <= 0;
            Lui <= 0;
            RegDst <= 0;
            ALUSrc <= 1;
            Zero_sign_ex <= 1;
            Branch <= 0;
            nBranch <= 0;
        end
        6'b001100:  // andi
        begin
            ALUop <= 4'b0100;
            RegWrite <= 1;
            Sftmd <= 0;
            Jrn <= 0;
            Lui <= 0;
            RegDst <= 0;
            ALUSrc <= 1;
            Zero_sign_ex <= 0;
            Branch <= 0;
            nBranch <= 0;
        end
        6'b001101:  // ori
        begin
            ALUop <= 4'b0101;
            RegWrite <= 1;
            Sftmd <= 0;
            Jrn <= 0;
            Lui <= 0;
            RegDst <= 0;
            ALUSrc <= 1;
            Zero_sign_ex <= 0;
            Branch <= 0;
            nBranch <= 0;
        end
        6'b001110:  // xori
        begin
            ALUop <= 4'b0110;
            RegWrite <= 1;
            Sftmd <= 0;
            Jrn <= 0;
            Lui <= 0;
            RegDst <= 0;
            ALUSrc <= 1;
            Zero_sign_ex <= 0;
            Branch <= 0;
            nBranch <= 0;
        end
        6'b001111:  // lui  note 
        begin
            ALUop <= 4'b1101;
            RegWrite <= 1;
            Sftmd <= 0;
            Jrn <= 0;
            Lui <= 1;
            RegDst <= 0;
            ALUSrc <= 1;
            Zero_sign_ex <= 0;
            Branch <= 0;
            nBranch <= 0;
        end
        6'b001010:  // slti
        begin
            ALUop <= 4'b1000;
            RegWrite <= 1;
            Sftmd <= 0;
            Jrn <= 0;
            Lui <= 0;
            RegDst <= 0;
            ALUSrc <= 1;
            Zero_sign_ex <= 1;
            Branch <= 0;
            nBranch <= 0;
        end
        6'b001011:  // sltiu
        begin
            ALUop <= 4'b1001;
            RegWrite <= 1;
            Sftmd <= 0;
            Jrn <= 0;
            Lui <= 0;
            RegDst <= 0;
            ALUSrc <= 1;
            Zero_sign_ex <= 0;
            Branch <= 0;
            nBranch <= 0;
        end
        6'b000100:  // beq
        begin
            ALUop <= 4'b0011;
            RegWrite <= 0;
            Sftmd <= 0;
            Jrn <= 0;
            Lui <= 0;
            RegDst <= 0;
            ALUSrc <= 0;
            Zero_sign_ex <= 1;
            Branch <= 1;
            nBranch <= 0;
        end
        6'b000101:  // bne
        begin
            ALUop <= 4'b0011;
            RegWrite <= 0;
            Sftmd <= 0;
            Jrn <= 0;
            Lui <= 0;
            RegDst <= 0;
            ALUSrc <= 0;
            Zero_sign_ex <= 1;
            Branch <= 0;
            nBranch <= 1;
        end

        default:
        begin
            RegWrite <= 0;
            Sftmd <= 0;
            ALUop <= 4'b1111;
            Jrn <= 0;
            Lui <= 0;
            RegDst <= 0;
            ALUSrc <= 0;
            Zero_sign_ex <= 0;
            Branch <= 0;
            nBranch <= 0;
        end
    endcase
end

endmodule

ALU

`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/11/14 22:30:23
// Design Name:
// Module Name: ALU_1
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//


module ALU_1(
           // data
           input [31:0] A,
           input [31:0] B,
           input [4:0] shamt,
           // control
           input [3:0] ALUop,
           input Sftmd, // shift instruction control

           /*** I-type ***/
           input [15:0] imm, // data
           // control
           input Lui,           // 1:lui instruction
           input ALUSrc,        // 1:imm calculate
           input Zero_sign_ex,  // 0:zero extension; 1:sign extension

           output reg [31:0] ALUresult,
           // beq bne 
           output [31:0] offset,    
           output zero  // ALUresult == 0 => zero = 1;
       );

// convert A and B to signed numbers
wire signed [31:0] A_signed = A;
wire signed [31:0] B_signed;
wire signed [31:0] B_signed_origin = B; // for sra instruction

// for shift instructions
// select data: if (Sftmd == 1) input shamt else input rs
wire [31:0] A_or_Shift = (Sftmd == 0) ? A : {27'b0,shamt};


/*** I-type: data select ***/

// immediate data extension and select
wire [31:0] zero_imm_ex = {16'b0,imm};
wire [31:0] sign_imm_ex = (imm[15] == 1)? {16'hffff,imm}: {16'b0,imm}; // NOTE: 16'b1 is incorrect
wire [31:0] imm_input = (Zero_sign_ex == 0)? zero_imm_ex: sign_imm_ex;

// R[rt] or imm extension
wire [31:0] B_select = (ALUSrc == 0)? B: imm_input;
assign B_signed = B_select;

// output: (sign extension)offset << 2
assign offset = imm_input << 2;

/* calculate */
always @(*)
begin
    case (ALUop)
        4'b0000:    // add addi
        begin
            ALUresult <= A + B_select;
        end
        4'b0001:    // addu addiu
        begin
            ALUresult <= A + B_select;
        end
        4'b0010:    // sub
        begin
            ALUresult <= A - B;
        end
        4'b0011:    // subu
        begin
            ALUresult <= A - B;
            // zero <= ((A-B) == 0)? 1: 0; // beq
        end
        4'b0100:    // and andi
        begin
            ALUresult <= A & B_select;
        end
        4'b0101:    // or ori
        begin
            ALUresult <= A | B_select;
        end
        4'b0110:    // xor xori
        begin
            ALUresult <= A ^ B_select;
        end
        4'b0111:    // nor nori
        begin
            ALUresult <= ~(A | B_select);
        end
        4'b1000:    // slt slti // note:********signed********//
        begin
            if(A_signed < B_signed)
                ALUresult <= 1;
            else
                ALUresult <= 0;
        end
        4'b1001:    // sltu sltiu
        begin
            if(A < B_select)
                ALUresult <= 1;
            else
                ALUresult <= 0;
        end

        4'b1010:    // sllv 10  /*** note: not B_select ***/
        begin
            ALUresult <= B << A_or_Shift;    // NOTE: not A << B!
        end
        4'b1011:    // srlv
        begin
            ALUresult <= B >> A_or_Shift;    // NOTE: not A >> B!
        end
        4'b1100:    // srav // note: ******signed*******//
        begin
            ALUresult <= B_signed_origin >>> A_or_Shift;    // NOTE: not A_signed >> B!
        end

        4'b1101: // lui
        begin
            ALUresult <= (Lui == 1)? {imm,16'b0}: 0;
        end
        default:
        begin
            ALUresult <= 0;
        end
    endcase
end

assign zero = (ALUresult == 0)? 1: 0;

endmodule

注意ALU的zero信号,就是判断ALUresult是不是0,是的话就是1

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,   // 100MHz 
           input rst_n,

           output [31:0] result // 测试syntheses,没有输出的模块是恐怖的
       );

/
/******* clk *******/
/

// cpu_clk Inputs
// reg   clk;   

// cpu_clk Outputs
wire  clk_div; // 20Mhz

cpu_clk  u_cpu_clk (
    .clk_in1                 ( clk        ),

    .clk_out1                ( clk_div    )
);

//
/******** PC ********/
//

// pc_1 Inputs
wire  Jrn;
wire  [31:0]  JrPC;

wire [31:0] offset_in;
wire zero_in;
wire Branch_in;
wire nBranch_in;

// pc_1 Outputs
wire  [31:0]  pcOld;

pc_1  u_pc_1 (
          .clk                     ( clk_div     ),
          .rst_n                   ( rst_n   ),

          .pcOrigin                ( pcOld   ),
          .JrPC                    ( JrPC    ),

          .Jrn                     ( Jrn     ),

          .offset                  ( offset_in  ),
          .zero                    ( zero_in    ),
          .Branch                  ( Branch_in  ),
          .nBranch                 ( nBranch_in ),

          .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;
wire   RegDst_in;

// 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_div         ),
                 .rst_n                   ( rst_n       ),
                 .rA                      ( instruction[25:21]          ),
                 .rB                      ( instruction[20:16]          ),
                 .rW                      ( instruction[15:11]          ),
                 .writeData               ( ALUresult   ),
                 .RegWrite                ( RegWrite    ),

                 .RegDst                  ( RegDst_in   ),

                 .A                       ( A           ),
                 .B                       ( B           )
             );

///
/******** ALU ********/
///

// ALU_1 Inputs
// wire   [31:0]  A;
// wire   [31:0]  B;
wire   [3:0]  ALUop;
wire   Sftmd;

wire   [15:0] imm = instruction[15:0];
wire Lui_in;
wire ALUSrc_in;
wire Zero_sign_ex_in;

// ALU_1 Outputs
// wire  [31:0]  ALUresult = writeData; // Note:Error!
wire  [31:0]  offset;
wire  zero;

assign offset_in = offset;
assign zero_in = zero;

ALU_1  u_ALU_1 (
           .A                       ( A           ),
           .B                       ( B           ),
           .shamt                   ( instruction[10:6]),

           .ALUop                   ( ALUop       ),
           .Sftmd                   ( Sftmd       ),

           /** I-type **/
           .imm                     ( imm              ),
           .Lui                     ( Lui_in           ),
           .ALUSrc                  ( ALUSrc_in        ),
           .Zero_sign_ex            ( Zero_sign_ex_in  ),

           .ALUresult               ( ALUresult        ),
           .offset                  ( offset           ),
           .zero                    ( zero             )
       );


/
/******** 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;
wire Lui;
wire RegDst;
wire ALUSrc;
wire Zero_sign_ex;
wire Branch;
wire nBranch;

// send to Reg Files
assign RegDst_in = RegDst;
// send to ALU
assign Lui_in = Lui;
assign ALUSrc_in = ALUSrc;
assign Zero_sign_ex_in = Zero_sign_ex;
// send to pc
assign Branch_in = Branch;
assign nBranch_in = nBranch;

control_1  u_control_1 (
               .op                      ( instruction[31:26]         ),
               .func                    ( instruction[5:0]       ),

               .RegWrite                ( RegWrite   ),
               .Sftmd                   ( Sftmd      ),
               .ALUop                   ( ALUop      ),
               .Jrn                     ( Jrn        ),
               // I type
               .Lui                     ( Lui        ),
               .RegDst                  ( RegDst     ),
               .ALUSrc                  ( ALUSrc     ),
               .Zero_sign_ex            ( Zero_sign_ex ),
               // beq bne
               .Branch                  ( Branch     ),
               .nBranch                 ( nBranch    )
           );

assign result = ALUresult;

endmodule

仿真,综合,实现

成功!

还没有开发板下载验证。

`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,   // 100MHz 
           input rst_n,

           output [31:0] result // 测试syntheses,没有输出的模块是恐怖的
       );

/
/******* clk *******/
/

// cpu_clk Inputs
// reg   clk;   

// cpu_clk Outputs
wire  clk_div; // 20Mhz

cpu_clk  u_cpu_clk (
    .clk_in1                 ( clk        ),

    .clk_out1                ( clk_div    )
);

//
/******** PC ********/
//

// pc_1 Inputs
wire  Jrn;
wire  [31:0]  JrPC;

wire [31:0] offset_in;
wire zero_in;
wire Branch_in;
wire nBranch_in;

// pc_1 Outputs
wire  [31:0]  pcOld;

pc_1  u_pc_1 (
          .clk                     ( clk_div     ),
          .rst_n                   ( rst_n   ),

          .pcOrigin                ( pcOld   ),
          .JrPC                    ( JrPC    ),

          .Jrn                     ( Jrn     ),

          .offset                  ( offset_in  ),
          .zero                    ( zero_in    ),
          .Branch                  ( Branch_in  ),
          .nBranch                 ( nBranch_in ),

          .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;
wire   RegDst_in;

// 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_div         ),
                 .rst_n                   ( rst_n       ),
                 .rA                      ( instruction[25:21]          ),
                 .rB                      ( instruction[20:16]          ),
                 .rW                      ( instruction[15:11]          ),
                 .writeData               ( ALUresult   ),
                 .RegWrite                ( RegWrite    ),

                 .RegDst                  ( RegDst_in   ),

                 .A                       ( A           ),
                 .B                       ( B           )
             );

///
/******** ALU ********/
///

// ALU_1 Inputs
// wire   [31:0]  A;
// wire   [31:0]  B;
wire   [3:0]  ALUop;
wire   Sftmd;

wire   [15:0] imm = instruction[15:0];
wire Lui_in;
wire ALUSrc_in;
wire Zero_sign_ex_in;

// ALU_1 Outputs
// wire  [31:0]  ALUresult = writeData; // Note:Error!
wire  [31:0]  offset;
wire  zero;

assign offset_in = offset;
assign zero_in = zero;

ALU_1  u_ALU_1 (
           .A                       ( A           ),
           .B                       ( B           ),
           .shamt                   ( instruction[10:6]),

           .ALUop                   ( ALUop       ),
           .Sftmd                   ( Sftmd       ),

           /** I-type **/
           .imm                     ( imm              ),
           .Lui                     ( Lui_in           ),
           .ALUSrc                  ( ALUSrc_in        ),
           .Zero_sign_ex            ( Zero_sign_ex_in  ),

           .ALUresult               ( ALUresult        ),
           .offset                  ( offset           ),
           .zero                    ( zero             )
       );


/
/******** 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;
wire Lui;
wire RegDst;
wire ALUSrc;
wire Zero_sign_ex;
wire Branch;
wire nBranch;

// send to Reg Files
assign RegDst_in = RegDst;
// send to ALU
assign Lui_in = Lui;
assign ALUSrc_in = ALUSrc;
assign Zero_sign_ex_in = Zero_sign_ex;
// send to pc
assign Branch_in = Branch;
assign nBranch_in = nBranch;

control_1  u_control_1 (
               .op                      ( instruction[31:26]         ),
               .func                    ( instruction[5:0]       ),

               .RegWrite                ( RegWrite   ),
               .Sftmd                   ( Sftmd      ),
               .ALUop                   ( ALUop      ),
               .Jrn                     ( Jrn        ),
               // I type
               .Lui                     ( Lui        ),
               .RegDst                  ( RegDst     ),
               .ALUSrc                  ( ALUSrc     ),
               .Zero_sign_ex            ( Zero_sign_ex ),
               // beq bne
               .Branch                  ( Branch     ),
               .nBranch                 ( nBranch    )
           );

assign result = ALUresult;

endmodule


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

XV_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值