Verilog

31条指令单周期cpu设计(Verilog)-(十)上代码→顶层模块设计&总结

详解31条MIPS单周期CPU的顶层模块Verilog代码实现,包括模块连接方式、控制信号设计、以及整个CPU设计流程的总结。

说在前面

  • 开发环境:Vivado
  • 语言:Verilog
  • cpu框架:Mips
  • 控制器:组合逻辑

设计思路

  • 按照预先设计好的数据通路图将各个模块连接起来
    `timescale 1ns / 1ps
    module cpu(
        input         clk,
        input         reset,
        input  [31:0] inst,
        input  [31:0] rdata,
        output [31:0] pc,
        output [31:0] addr,
        output [31:0] wdata,
        output        IM_R,
        output        DM_CS,
        output        DM_R,
        output        DM_W
        );
        //--------------------------------//控制信号(除有关存储器)
        wire PC_CLK;                     //
        wire PC_ENA;                     //
        wire M1;                         //
        wire M2;                         //
        wire M3;                         //
        wire M4;                         //
        wire M5;                         //
        wire M6;                         //
        wire M7;                         //
        wire M8;                         //
        wire M9;                         //
        wire M10;                        //
        wire M11;                        //
        wire [3:0] ALUC;                 //
        wire RF_W;                       //
        wire RF_CLK;                     //
        wire C_EXT16;                    //
        //--------------------------------//运算标志位
        wire zero;                       //
        wire carry;                      //
        wire negative;                   //
        wire overflow;                   //
        wire add_overflow;               //
        //--------------------------------// 
        wire [31:0] INS;                 //译码后指令
        //--------------------------------//数据通路(除有关存储器)
        wire [31:0] D_ALU;               //
        wire [31:0] D_PC;                //
        wire [31:0] D_RF;                //
        wire [31:0] D_Rs;                //
        wire [31:0] D_Rt;                //
        wire [31:0] D_IM;                //
        wire [31:0] D_DM;                //
        wire [31:0] D_Mux1;              //
        wire [31:0] D_Mux2;              //
        wire [31:0] D_Mux3;              //
        wire [4:0]  D_Mux4;              //
        wire [4:0]  D_Mux5;              //
        wire [31:0] D_Mux6;              //
        wire [31:0] D_Mux7;              //
        wire [31:0] D_Mux8;              //
        wire [31:0] D_Mux9;              //
        wire [31:0] D_Mux10;             //
        wire        D_Mux11;             //
                                          //
        wire [31:0] D_EXT1;              //
        wire [31:0] D_EXT5;              //
        wire [31:0] D_EXT16;             //
        wire [31:0] D_EXT18;             //
        wire [31:0] D_ADD;               //
        wire [31:0] D_ADD8;              //
        wire [31:0] D_NPC;               //
        wire [31:0] D_ii;                //
        assign PC_ENA = 1;
        //--------------------------------//外部通路连接
        assign pc = D_PC;
        assign addr = D_ALU;
        assign wdata = D_Rt;
        
        //--------------------------------//指令译码
        instr_dec cpu_ins (inst, INS);
        operation cpu_opcode (clk,zero,INS,PC_CLK,IM_R,M1,M2,M3,M4,M5,M6,M7,M9,  M10,ALUC,RF_W,RF_CLK,DM_W,DM_R,DM_CS,C_EXT16);
        //--------------------------------//部件
        pcreg   pc_out      (PC_CLK,     reset,      PC_ENA,      D_Mux1,     D_PC);
        alu     cpu_alu     (D_Mux9,     D_Mux10,    ALUC[3:0],   D_ALU,      zero,         carry,        negative, overflow);
        regfile cpu_ref     (RF_CLK,     reset,      RF_W,        overflow, inst  [25:21],  inst[20:16],  D_Mux5,   D_Mux6,D_Rs, D_Rt);
        mux     cpu_mux1    (D_Mux3,     D_Mux2,     M1,          D_Mux1);
        mux     cpu_mux2    (D_NPC,      D_ADD,      M2,          D_Mux2);
        mux     cpu_mux3    (D_ii,       D_Rs,       M3,          D_Mux3);
        mux5    cpu_mux4    (inst[10:6], D_Rs[4:0],  {INS[30],M4},D_Mux4);
        mux5    cpu_mux5    (inst[15:11],inst[20:16],{INS[30],M5},D_Mux5);
        mux     cpu_mux6    (D_Mux7,     D_ADD8,     M6,          D_Mux6);
        mux     cpu_mux7    (D_ALU,     rdata,      M7,          D_Mux7);
        mux     cpu_mux9    (D_EXT5,     D_Rs,       M9,          D_Mux9);
        mux     cpu_mux10   (D_Rt,       D_EXT16,    M10,         D_Mux10);
        extend5 cpu_ext5    (D_Mux4,     D_EXT5);
        extend16 cpu_ext16  (inst[15:0], C_EXT16,    D_EXT16);
        extend18 cpu_ext18  (inst[15:0], D_EXT18);
        add     cpu_add     (D_EXT18,    D_NPC,      D_ADD,       add_overflow);
        add8    cpu_add8    (D_PC,       D_ADD8);
        npc     cpu_npc     (D_PC,       reset,      D_NPC);
        II      cpu_ii      (D_PC[31:28],inst[25:0], D_ii);
        
    endmodule
    

总结

  • 总算把鸽的写完了,我觉得这个系列的重点在前面的设计部分,后面的代码可以自己写,只要掌握了整个流程写起来还是挺简单的,就是工作量很大,如果想要自己写的话就看前面几篇即可,代码部分可以不看了。