为了再水一篇文章,所以把流水线处理器附加部分又新建了一篇文章(就是水!)。

流水线处理器的verilog实现在下面!(一些没有改动的模块就不放在这里了)


具体思路

我的实现方法具体如下:

IF阶段设置一个指令冲突分析模块,在IF阶段指令读取之后,将这条指令以及之前的三条指令作为输入(因为最多与前三条指令发生冲突),分析是哪种冲突,是否需要暂停或者定向?并输出标志信号。

ID阶段设置一个多选二寄存器,因为附加实验的指令冲突都是关于寄存器的读后写(RAW)冲突,所以放在寄存器读出来的数与ID_EX寄存器之间,再将需要重定向的数据定向过来,通过冲突分析输出的标志信号作为控制信号决定输出。

暂停:如果分析出来必须暂停,那么下一个时钟周期PC值保持不变,IF_ID传出去的信息全都为0,相当于在本条指令之前插入一个空周期,来避免冲突。

代码实现

CPU.v

`timescale 1ns / 1ps


module cpu(
    input clk,
    input resetn,
    
    output [31:0]    debug_wb_pc     , 
    output           debug_wb_rf_wen , 
    output [4 :0]    debug_wb_rf_addr,  
    output [31:0]    debug_wb_rf_wdata
    );

/**********************************Start defining the connection lines********************************/

/**********************************IF Part********************************/
    wire [31:0]IF_NPC;
    wire [31:0]IF_PC;
    wire [31:0]IF_INS;
    wire [31:0]IF_ADDNPC;
    wire [3:0]signal_1;
    wire [3:0]signal_2;
    wire [3:0]base;
    wire stall;
/**********************************ID Part********************************/
    wire [31:0]ID_NPC;
    wire [31:0]ID_INS;
    wire [31:0]ID_IMM;
    wire [31:0]ID_RS;
    wire [31:0]ID_RT;
    wire [31:0]ID_PC;
    wire [31:0]ID_A;
    wire [31:0]ID_B;
/**********************************EX Part********************************/
    wire [31:0]EX_NPC;
    wire [31:0]EX_INS;
    wire [31:0]EX_RS;
    wire [31:0]EX_RT;
    wire [31:0]EX_A;
    wire [31:0]EX_B;
    wire [31:0]EX_IMM;
    wire EX_JUDG;
    wire [31:0]EX_ALUOUT;
    wire [31:0]EX_PC;
/**********************************MEM Part********************************/
    wire [31:0]MEM_INS;
    wire MEM_JUDG;
    wire [31:0]MEM_ALUOUT;
    wire [31:0]MEM_RT;
    wire [31:0]MEM_MEMOUT;
    wire [31:0]MEM_PC;
/**********************************WB Part********************************/
    wire [31:0]WB_INS;
    wire [31:0]WB_MEMOUT;
    wire [31:0]WB_ALUOUT;
    wire [31:0]WB_DATA;
    wire [31:0]WB_PC;
    wire [4:0]WB_ADDR;
    wire WB_ABLE;
    
/**********************************Data conflict part********************************/


    
/**********************************Start link module**************************************/
    assign debug_wb_pc=WB_PC;
    assign debug_wb_rf_wen=WB_ABLE;
    assign debug_wb_rf_addr=WB_ADDR;
    assign debug_wb_rf_wdata=WB_DATA;
    
 /**********************************IF Part********************************/   
 
    PC PC(
    .clk(clk),
    .resetn(resetn),
    .next_pc(IF_NPC),
    .stall(stall),
    .pc(IF_PC)
    );
    ADD ADD(
    .pc(IF_PC),
    .add_result(IF_ADDNPC)
    );
    Ins_reg Ins_reg(
    .ins_addr(IF_PC),
    .ins_out(IF_INS)
    );
    NPC_MUX NPC_MUX(
    .ori_npc(IF_ADDNPC),
    .jmp_npc(MEM_ALUOUT),
    .select(MEM_JUDG),
    .npc(IF_NPC)
    );
    IF_ID IF_ID(
    .clk(clk),
    .resetn(resetn),
    .stall(stall),
    .wdata_1_1(IF_NPC),
    .wdata_1_2(IF_INS),
    .wdata_1_3(IF_PC),
    .rdata_1_1(ID_NPC),
    .rdata_1_2(ID_INS),
    .rdata_1_3(ID_PC)
    );
    
    Conflict Conflict(
    .clk(clk),
    .resetn(resetn),
    .id_ins(ID_INS),
    .ex_ins(EX_INS),
    .mem_ins(MEM_INS),
    .new_ins(IF_INS),
    .base(base),
    .stall(stall),
    .signal_1(signal_1),
    .signal_2(signal_2)
    );
    
 /**********************************ID Part********************************/   
 
    Regs Regs(
    .clk(clk),
    .we(WB_ABLE),
    .raddr1(ID_INS[25:21]),
    .raddr2(ID_INS[20:16]),
    .rdata1(ID_RS),
    .rdata2(ID_RT),
    .waddr(WB_ADDR),
    .wdata(WB_DATA)
    );
    Extender Extender(
    .imm(ID_INS[25:0]),
    .opcode(ID_INS[31:26]),
    .extend_result(ID_IMM)
    );
    ID_EX ID_EX(
    .clk(clk),
    .resetn(resetn),
    .wdata_2_1(ID_NPC),
    .wdata_2_2(ID_A),
    .wdata_2_3(ID_B),
    .wdata_2_4(ID_IMM),
    .wdata_2_5(ID_INS),
    .wdata_2_6(ID_PC),
    .rdata_2_1(EX_NPC),
    .rdata_2_2(EX_RS),
    .rdata_2_3(EX_RT),
    .rdata_2_4(EX_IMM),
    .rdata_2_5(EX_INS),
    .rdata_2_6(EX_PC)
    );
    
    Con_mux Con_mux(
    .clk(clk),
    .signal_1(signal_1),
    .signal_2(signal_2),
    .base(base),
    .id_rs(ID_RS),
    .id_rt(ID_RT),
    .ex_aluout(EX_ALUOUT),
    .mem_aluout(MEM_ALUOUT),
    .mem_memout(MEM_MEMOUT),
    .wb_data(WB_DATA),
    .id_a(ID_A),
    .id_b(ID_B)
    );
    
 /**********************************EX Part********************************/  
 
    zero zero(
    .a(EX_RS),
    .b(EX_RT),
    .opcode(EX_INS[31:26]),
    .judge(EX_JUDG)
    );
    MUX_1 MUX_1(
    .d0(EX_NPC),
    .d1(EX_RS),
    .select(EX_INS[31:26]),
    .out(EX_A)
    );
    MUX_2 MUX_2(
    .d0(EX_IMM),
    .d1(EX_RT),
    .select(EX_INS[31:26]),
    .out(EX_B)
    );
    ALU ALU(
    .A(EX_A),
    .B(EX_B),
    .sll(EX_INS[10:6]),
    .Card(EX_INS[5:0]),
    .opcode(EX_INS[31:26]),
    .F(EX_ALUOUT)
    );
    EX_MEM EX_MEM(
    .clk(clk),
    .resetn(resetn),
    .wdata_3_1(EX_JUDG),
    .wdata_3_2(EX_ALUOUT),
    .wdata_3_3(EX_RT),
    .wdata_3_4(EX_INS),
    .wdata_3_5(EX_PC),
    .rdata_3_1(MEM_JUDG),
    .rdata_3_2(MEM_ALUOUT),
    .rdata_3_3(MEM_RT),
    .rdata_3_4(MEM_INS),
    .rdata_3_5(MEM_PC)
    );
    
 /**********************************MEM Part********************************/  
 
    Data_reg Data_reg(
    .clk(clk),
    .opcode(MEM_INS[31:26]),
    .data_reg_wdata(MEM_RT),
    .data_reg_addr(MEM_ALUOUT),
    .data_reg_rdata(MEM_MEMOUT)
    );
    MEM_WB MEM_WB(
    .clk(clk),
    .resetn(resetn),
    .wdata_4_1(MEM_MEMOUT),
    .wdata_4_2(MEM_ALUOUT),
    .wdata_4_3(MEM_INS),
    .wdata_4_4(MEM_PC),
    .rdata_4_1(WB_MEMOUT),
    .rdata_4_2(WB_ALUOUT),
    .rdata_4_3(WB_INS),
    .rdata_4_4(WB_PC),
    .wb_enable(WB_ABLE)
    );
    
 /**********************************WB Part********************************/  
 
    WB_MUX WB_MUX(
    .d0(WB_MEMOUT),
    .d1(WB_ALUOUT),
    .select(WB_INS[31:26]),
    .out(WB_DATA)
    );
    WB_MUX_2 WB_MUX_2(
    .a(WB_INS[20:16]),
    .b(WB_INS[15:11]),
    .opcode(WB_INS[31:26]),
    .result(WB_ADDR)
    );
 
  

  
 
endmodule

涉及到修改以及添加的模块并不多:冲突分析、多选二选择器、PC、IF_ID:

Conflict

`timescale 1ns / 1ps


module Conflict(
    input clk,
    input resetn,
    input [31:0]new_ins,
    input [31:0]id_ins,
    input [31:0]ex_ins,
    input [31:0]mem_ins,
    output reg stall,
    output reg [3:0]base,
    output reg [3:0]signal_1,
    output reg [3:0]signal_2
    );
    

    
    always @(*) begin
    stall=0;
    base=0;
    signal_1=0;
    signal_2=0;
    /*******Stall************************************/
    if(id_ins[31:26]==6'b100011&&(id_ins[20:16]==new_ins[25:21]||(new_ins[31:26]==6'b000000&&id_ins[20:16]==new_ins[20:16]))) begin
    stall=1;
    end
    else if(id_ins[31:26]!=6'b100011) begin
    stall=0;
    end
    /*********signal_1**************************/
    if(id_ins!=32'b0&&id_ins[31:26]==6'b000000&&new_ins[31:26]==6'b000000&&new_ins[25:21]==id_ins[15:11]) begin
    signal_1=4'b0100;
    end
    else if(ex_ins!=32'b0&&ex_ins[31:26]==6'b000000&&new_ins[31:26]==6'b000000&&ex_ins[31:26]==6'b000000&&new_ins[25:21]==ex_ins[15:11]) begin
    signal_1=4'b1000;
    end
    else if(ex_ins!=32'b0&&ex_ins[31:26]==6'b100011&&new_ins[31:26]==6'b000000&&ex_ins[31:26]==6'b100011&&new_ins[25:21]==ex_ins[20:16]) begin
    signal_1=4'b0010;
    end
    else if(mem_ins!=32'b0&&mem_ins[31:26]==6'b000000&&new_ins[31:26]==6'b000000&&mem_ins[31:26]==6'b000000&&new_ins[25:21]==mem_ins[15:11]) begin
    signal_1=4'b1100;
    end
    else if(mem_ins!=32'b0&&mem_ins[31:26]==6'b100011&&new_ins[31:26]==6'b000000&&mem_ins[31:26]==6'b100011&&new_ins[25:21]==mem_ins[20:16]) begin
    signal_1=4'b0011;
    end   
    
    /**************signal_2***********************/
    
    if(id_ins!=32'b0&&id_ins[31:26]==6'b000000&&new_ins[31:26]==6'b000000&&new_ins[20:16]==id_ins[15:11]) begin
    signal_2=4'b0100;
    end
    else if(ex_ins!=32'b0&&ex_ins[31:26]==6'b000000&&new_ins[31:26]==6'b000000&&ex_ins[31:26]==6'b000000&&new_ins[20:16]==ex_ins[15:11]) begin
    signal_2=4'b1000;
    end
    else if(ex_ins!=32'b0&&ex_ins[31:26]==6'b100011&&new_ins[31:26]==6'b000000&&ex_ins[31:26]==6'b100011&&new_ins[20:16]==ex_ins[20:16]) begin
    signal_2=4'b0010;
    end
    else if(mem_ins!=32'b0&&mem_ins[31:26]==6'b000000&&new_ins[31:26]==6'b000000&&mem_ins[31:26]==6'b000000&&new_ins[20:16]==mem_ins[15:11]) begin
    signal_2=4'b1100;
    end
    else if(mem_ins!=32'b0&&mem_ins[31:26]==6'b100011&&new_ins[31:26]==6'b000000&&mem_ins[31:26]==6'b100011&&new_ins[20:16]==mem_ins[20:16]) begin
    signal_2=4'b0011;
    end
    
    /****************base*****************/
    
    if(id_ins!=32'b0&&id_ins[31:26]==6'b000000&&new_ins[31:26]==6'b100011&&new_ins[25:21]==id_ins[15:11]) begin
    base=4'b0100;
    end
    else if(ex_ins!=32'b0&&ex_ins[31:26]==6'b100011&&new_ins[31:26]==6'b100011&&ex_ins[31:26]==6'b100011&&new_ins[25:21]==ex_ins[20:16]) begin
    base=4'b0010;
    end
    else if(ex_ins!=32'b0&&ex_ins[31:26]==6'b000000&&new_ins[31:26]==6'b100011&&ex_ins[31:26]==6'b000000&&new_ins[25:21]==ex_ins[15:11]) begin
    base=4'b1000;
    end
    else if(mem_ins!=32'b0&&mem_ins[31:26]==6'b100011&&new_ins[31:26]==6'b100011&&mem_ins[31:26]==6'b100011&&new_ins[25:21]==mem_ins[20:16]) begin
    base=4'b0011;
    end
    else if(mem_ins!=32'b0&&mem_ins[31:26]==6'b000000&&new_ins[31:26]==6'b100011&&mem_ins[31:26]==6'b000000&&new_ins[25:21]==mem_ins[15:11]) begin
    base=4'b1100;
    end
    

    
    end
    
    
    


   
endmodule

Con_mux

`timescale 1ns / 1ps



module Con_mux(
    input clk,
    input [3:0]signal_1,
    input [3:0]signal_2,
    input [3:0]base,
    input [31:0]id_rs,
    input [31:0]id_rt,
    input [31:0]ex_aluout,
    input [31:0]mem_memout,
    input [31:0]wb_data,
    input [31:0]mem_aluout,
    
    output reg [31:0]id_a,
    output reg [31:0]id_b

    );
    
   always @(posedge clk) begin
/**********RS端口******************/    
    if(base==4'b0100||signal_1==4'b0100) begin
    assign id_a=ex_aluout;
    end
    else if(base==4'b0010||signal_1==4'b0010) begin
    assign id_a=mem_memout;
    end
    else if(base==4'b1000||signal_1==4'b1000) begin
    assign id_a=mem_aluout;
    end
    else if(base==4'b1100||base==4'b0011||signal_1==4'b1100||signal_1==4'b0011) begin
    assign id_a=wb_data;
    end
    else begin
    assign id_a=id_rs;
    end
    
    
/**********RT端口************************/
    if(signal_2==4'b0100) begin
    assign id_b=ex_aluout;
    end
    else if(signal_2==4'b0010)begin
    assign id_b=mem_memout;
    end
    else if(signal_2==4'b1000) begin
    assign id_b=mem_aluout;
    end
    else if(signal_2==4'b1100||signal_2==4'b0011) begin
    assign id_b=wb_data;
    end
    else begin
    assign id_b=id_rt;
    end
    
    end
endmodule

PC

`timescale 1ns / 1ps



module PC(
    input clk,
    input resetn,
    input stall,
    
    input [31:0]next_pc,
    output reg [31:0]pc
    );
    
always @(posedge clk)
    if(resetn==1'b0) begin
    pc<=0;
    end
    else if(stall==1) begin
    pc=pc;
    end
    else  begin
    pc<=next_pc;
    end
    
    
endmodule

IF_ID

`timescale 1ns / 1ps



module IF_ID(
    input clk,
    input resetn,
    input [31:0]wdata_1_1,
    input [31:0]wdata_1_2,
    input [31:0]wdata_1_3,
    input stall,
    
    output reg [31:0]rdata_1_1,
    output reg [31:0]rdata_1_2,
    output reg [31:0]rdata_1_3
    );
    
    always @(posedge clk)
    if(resetn==0||stall==1) begin
    rdata_1_1<=0;
    rdata_1_2<=0;
    rdata_1_3<=0;
    end
    else begin
    rdata_1_1<=wdata_1_1;
    rdata_1_2<=wdata_1_2;
    rdata_1_3<=wdata_1_3;
    end
    
    
endmodule

结束

整个lab1到此结束

最后修改:2023 年 10 月 20 日
如果觉得我的文章对你有用,请随意赞赏