数字电路设计之五级流水线设计(CPU)

来源:互联网 发布:新版淘宝联盟申请高佣 编辑:程序博客网 时间:2024/04/30 05:37

这个流水线应该是我大二上的时候的最高水平了,现在看起来确实很简单,代码风格也不是很好,没有模块化,而且这些指令也不是严格的mips的所有指令,是自己定义的一些。但是放在博客里也算是对自己过去的一个总结吧!

现在再看这个代码,我觉得写得太恶心了,没有注释,没有说清楚关键的地方。我自己都忘了为什么这么写~~

后来发现有非常坑爹的Bug!!!!祝好!!!我没有改过来了~~~

• 实验步骤

1.先写好CPU的指令集。

 

    

          

2.根据指令集先把一些基本的指令实现,比如LOAD,STORE等,把大概的流水线先画出框图。画出框图后,把基本指令实现。调试,仿真。

     

3.在2的基础上加入别的指令,考虑好hazard的问题


4.优化代码代码,调试,simulation。

 

• 实验原理

流水线是数字系统中一种提高系统稳定性和工作速度的方法,广泛应用于高档CPU的架构中。根据MIPS处理器的特点,将整体的处理过程分为取指令(IF)、指令译码(ID)、执行(EX)、存储器访问(MEM)和寄存器会写(WB)五级,对应多周期的五个处理阶段。一个指令的执行需要5个时钟周期,每个时钟周期的上升沿来临时,此指令所代表的一系列数据和控制信息将转移到下一级处理。

流水线寄存器负责将流水线的各部分分开,共有IF/ID、ID/EX、EX/MEM、MEM/WB四组。根据前面的介绍可知,四组流水线寄存器要求不完全相同,因此设计也有不同考虑。

(1)EX/MEM、MEM/WB两组流水线寄存器只是普通寄存器。

(2)当流水线发生数据跳转时,需清空ID/EX流水线寄存器而插入一个气泡,因此ID/EX流水线寄存器是一个带同步清零功能的寄存器。

需要注意的是,由于仿真对初始值的要求,上述寄存器都应考虑有reset信号的接入,以提供仿真时各寄存器的初值。

 

流水线:

 

             取址:处理器从指令存储器中读取指令

 

             译码:处理器从寄存器文件中读取源操作数并对指令译码产生控制信号

 

              执行:处理器使用ALU执行计算   

 

              存储器访问:处理器从数据存储器中读取或者写入数据

 

              写回:若是LOAD指令,将结果写回寄存器文件。

 

     >>加、减电路的设计考虑

减法、比较及部分分支指令(BN、BNE等)均可用加法器和必要的辅助电路来实现。对ALU来说,它的两个操作数输入时都已经是补码形式,当要完成两个操作数的减法时,即A-B补,可将减法转换为加法,利用加法器来实现:

›A-B= A+(-B)= A+(B)= A+B补)反+1

加法器完成的功能为:

sum=A+~B+1即可完成加减运算。

由于32位加法器的运算速度影响着CPU频率的高低,因此设计一个高速加法器尤为重要,本实验采用的是超前进位加法器,不过弄出来的速度比不过描述级语言写出的加法,所以后来加法就改成直接加了。

比较电路的设计考虑

对于比较运算,如果最高为不同,即A[31]B[31],则根据A[31]B[31]决定比较结果,但应注意有符号数和无符号数比较运算的区别。

①在有符号数比较SLT运算中,判断A<B的方法为:

A为负数、B0或正数:A[15]&&(~B[15])

AB符号相同,A-B为负:(A[15]~^B[15]) && sum[15]

SLTResult=(A[15]&&(~B[15])) ||( (A[15]~^B[15]) && sum[15])

②在无符号数比较SLT运算中,判断A<B的方法为:

A最高位为0B最高位为1(~A[15] )&&B[15]

AB最高位相同,A-B为负:(A[15]~^B[15]) && sum[15]

SLTResult=((~A[15] )&&B[15]) ||( (A[15]~^B[15]) && sum[15])

算术右移运算电路的设计考虑:

Verilog HDL的算术右移的运算符为“<<<”。要实现算术右移应注意,被移位的对象必须定义为reg类型,但是在SRA指令,被移位的对象操作数B为输入信号,不能定义为reg类型,因此必须引入reg类型中间变量B_reg,相应的Verilog HDL语句为:

reg signed [31:0] B_reg;

always @(B) begin

B_reg = B;  end

引入reg类型的中间变量B_reg后,就可对B_reg进行算术右移操作。

逻辑运算:

与、或、或非、异或、逻辑移位等运算较为简单,只是要注意一点,ANDXOROR三条指令的立即数为16位无符号数,应“0扩展”为32位无符号数,在运算的同时完成“0扩展”。


CPU的verilog代码:

`timescale 1ns / 1ps// state macro define`define idle1'b0`define exec1'b1// instruction macro define`define NOP5'b00000`define HALT5'b00001`define LOAD5'b00010`define STORE5'b00011`define SLL5'b00100`define SLA5'b00101`define SRL5'b00110`define SRA5'b00111`define ADD5'b01000`define ADDI5'b01001`define SUB5'b01010`define SUBI5'b01011`define CMP5'b01100`define AND5'b01101`define OR5'b01110`define XOR5'b01111`define LDIH5'b10000`define ADDC5'b10001`define SUBC5'b10010`define JUMP5'b11000`define JMPR5'b11001`define BZ5'b11010`define BNZ5'b11011`define BN5'b11100`define BNN5'b11101`define BC5'b11110`define BNC5'b11111// general register`define gr03'b000`define gr13'b001`define gr23'b010`define gr33'b011`define gr43'b100`define gr53'b101`define gr63'b110`define gr73'b111 module CPU(input wire  reset,       input wire  enable,          //make the   input wire  start,           //start CPU   input wire  clock,           //clock   input wire  [15:0]i_datain,  //instruction   input wire  [15:0]d_datain,  //data from memory   output reg  d_we,            //write enable       output wire [7:0]i_addr,     //pc   output reg  [7:0]d_addr,     //output adder for data memory   output reg  [15:0]d_dataout  //output data to data memory);  reg [15:0]gr[7:0];             //register filereg state,next_state;          //to control the CPUassign i_addr      =    pc;//************* CPU control *************//always @(posedge clock)begin  if (!reset)      state <= `idle;  else      state <= next_state;endalways@(*)begin   case (state)   `idle : if ((enable == 1'b1) && (start == 1'b1))next_state <= `exec;elsenext_state <= `idle;   `exec :if ((enable == 1'b0) || (wb_ir[15:11] == `HALT))next_state <= `idle;elsenext_state <= `exec;   endcaseend//_______________________________________________reg [15:0]id_ir;reg [7:0]pc;//************* IF *************//always@(posedge clock or negedge reset)begin   if (!reset)   beginid_ir <= 16'b0000_0000_0000_0000;pc <= 8'b0000_0000;   end   else if (state ==`exec)   beginif(((ex_ir[15:11] == `BZ) && (zf == 1'b1)) || ((ex_ir[15:11] == `BN) && (nf == 1'b1))|| ((ex_ir[15:11] == `BNZ) && (zf == 1'b0)) || ((ex_ir[15:11] == `BNN) && (nf == 1'b0))||  ((ex_ir[15:11] == `BC) && (cf == 1'b1)) || ((ex_ir[15:11] == `BNC) && (cf == 1'b0))|| ex_ir[15:11] == `JMPR)beginpc <= ALUo[7:0];id_ir <= i_datain;endelse if(id_ir[15:11] == `JUMP)//如果判断出指令是JUMP,直接跳转,就可以减少功耗,不必冒险beginpc <= id_ir[7:0];id_ir <= i_datain;end         //------------------------------------------------对于LOAD的处理--------------------------------------else if((id_ir[15:11] == `LOAD)&&(i_datain[15:11]!=`JUMP)&&(i_datain[15:11]!=`NOP)&&(i_datain[15:11]!=`HALT)                &&(i_datain[15:11]!=`LOAD))beginif((id_ir[10:8]==i_datain[2:0])&&((i_datain[15:11]==`ADD)||(i_datain[15:11]==`ADDC)||(i_datain[15:11]==`SUB) ||(i_datain[15:11]==`SUBC)||(i_datain[15:11]==`CMP)||(i_datain[15:11]==`AND)||(i_datain[15:11]==`OR)                 ||(i_datain[15:11]==`XOR)))beginpc <= pc;id_ir <= 16'bx;endelse if((id_ir[10:8]==i_datain[6:4])&&((i_datain[15:11]==`STORE)||(i_datain[15:11]==`ADD)||(i_datain[15:11]==`ADDC)      ||(i_datain[15:11]==`SUB)||(i_datain[15:11]==`SUBC)||(i_datain[15:11]==`AND)||(i_datain[15:11]==`OR)                      ||(i_datain[15:11]==`XOR)||(i_datain[15:11]==`CMP)||(i_datain[15:11]==`SLL)||(i_datain[15:11]==`SRL)                      ||(i_datain[15:11]==`SLA)||(i_datain[15:11]==`SRA) ))beginpc <= pc;id_ir <= 16'bx;endelse if((id_ir[10:8]==i_datain[10:8])&&((i_datain[15:11]==`STORE)||(i_datain[15:11]==`LDIH)||(i_datain[15:11]==`SUBI)   ||(i_datain[15:11]==`JMPR)||(i_datain[15:11]==`BZ)||(i_datain[15:11]==`BNZ)||(i_datain[15:11]==`BN)   ||(i_datain[15:11]==`BNN)||(i_datain[15:11]==`BNC)))beginpc <= pc;id_ir <= 16'bx;endend elsebeginpc <= pc + 1;                id_ir <= i_datain;        endendelse if (state ==`idle)pc <= pc;        else;end//----------------------------------------------------------------------------------------------------------------------------------------------------reg [15:0]ex_ir,reg_A,reg_B,smdr;//************* ID *************//always@(posedge clock or negedge reset)begin   if(!reset)   beginex_ir <= 16'b0000_0000_0000_0000;reg_A <= 16'b0000_0000_0000_0000;reg_B <= 16'b0000_0000_0000_0000;smdr  <= 16'b0000_0000_0000_0000;   end   else if (state == `exec)   beginex_ir <= id_ir;        //------------------根据不同的操作,reg_A的赋值以处理hazard-------------------------------if ((id_ir[15:11] == `BZ) || (id_ir[15:11] == `BN) || (id_ir[15:11] == `BNZ) || (id_ir[15:11] == `BNN) || (id_ir[15:11] == `JMPR)|| (id_ir[15:11] == `LDIH)||(id_ir[15:11] == `ADDI) || (id_ir[15:11] == `SUBI) || (id_ir[15:11] == `BC) || (id_ir[15:11] == `BNC))               begin    //处理ADD等hazard       if((id_ir[10:8]==ex_ir[10:8])&&(ex_ir!=`NOP)&&(ex_ir!=`CMP)&&(ex_ir!=`JUMP)&&(ex_ir!=`LOAD)&&(ex_ir!=`HALT))//这些指令没有目的寄存器,LOAD指令是所需的内容还没有出来存  reg_A <= ALUo;                    //后一条指令要用到前一条指令的结果       else if((id_ir[10:8]==mem_ir[10:8])&&(mem_ir!=`NOP)&&(mem_ir!=`CMP)&&(mem_ir!=`JUMP)&&(mem_ir!=`HALT))               //----------------------------------------------------------------------                   begin   if(mem_ir==`LOAD)   reg_A <= d_datain;   else           reg_A <= reg_C;                   //看看LOAD指令在这里会不会已经出结果了                   end               //----------------------------------------------------------------------       else if((id_ir[10:8]== wb_ir[10:8])&&(wb_ir!=`NOP)&&(wb_ir!=`CMP)&&(wb_ir!=`JUMP)&&(wb_ir!=`HALT))   reg_A <= reg_C1;       else                  //reg_A <= gr[id_ir[10:8]];   beginif(id_ir[10:8] == 0)reg_A <= gr[0];else if(id_ir[10:8] == 1)reg_A <= gr[1];else if(id_ir[10:8] == 2)reg_A <= gr[2];else if(id_ir[10:8] == 3)reg_A <= gr[3];else if(id_ir[10:8] == 4)reg_A <= gr[4];else if(id_ir[10:8] == 5)reg_A <= gr[5];else if(id_ir[10:8] == 6)reg_A <= gr[6];else if(id_ir[10:8] == 7)reg_A <= gr[7];    endendelse if((id_ir[15:11] == `ADD)||(id_ir[15:11] == `LOAD)||(id_ir[15:11] == `STORE)||(id_ir[15:11] == `ADDC)||(id_ir[15:11] == `SUB)           ||(id_ir[15:11] == `SUBC)||(id_ir[15:11] == `CMP) ||(id_ir[15:11] == `AND)  ||(id_ir[15:11] == `OR)  ||(id_ir[15:11] == `XOR)     ||(id_ir[15:11] == `SLL) ||(id_ir[15:11] == `SRL) ||(id_ir[15:11] == `SLA)  ||(id_ir[15:11] == `SRA))                 //LAOD,STORE,CMP,ADD,ADDC,SUB,SUBC,AND,OR,XOR,SLL,SRL,SLA,SRAbegin    //处理ADD等hazard   if((id_ir[6:4]==ex_ir[10:8])&&(ex_ir!=`NOP)&&(ex_ir!=`CMP)&&(ex_ir!=`JUMP)&&(ex_ir!=`LOAD)&&(ex_ir!=`HALT))//这些指令没有目的寄存器,LOAD指令是所需的内容还没有出来存reg_A <= ALUo;                    //后一条指令要用到前一条指令的结果   else if((id_ir[6:4]==mem_ir[10:8])&&(mem_ir!=`NOP)&&(mem_ir!=`CMP)&&(mem_ir!=`JUMP)&&(mem_ir!=`HALT))           //----------------------------------------------------------------------               begin               if(mem_ir[15:11]==`LOAD)       reg_A <= d_datain;       else       reg_A <= reg_C;                                  end            //----------------------------------------------------------------------    else if((id_ir[6:4]== wb_ir[10:8])&&(wb_ir!=`NOP)&&(wb_ir!=`CMP)&&(wb_ir!=`JUMP)&&(wb_ir!=`HALT))       reg_A <= reg_C1;    else                begin                if(id_ir[6:4] == 0)reg_A <= gr[0];                else if(id_ir[6:4] == 1)                reg_A <= gr[1];else if(id_ir[6:4] == 2)reg_A <= gr[2];else if(id_ir[6:4] == 3)reg_A <= gr[3];else if(id_ir[6:4] == 4)reg_A <= gr[4];else if(id_ir[6:4] == 5)reg_A <= gr[5];else if(id_ir[6:4] == 6)reg_A <= gr[6];else if(id_ir[6:4] == 7)reg_A <= gr[7];            end end         else if((( mem_ir[15:11] == `BZ) && (zf == 1'b1)) || ((mem_ir[15:11] == `BN) && (nf == 1'b1)) || (( mem_ir[15:11] == `BNZ) && (zf == 1'b0))|| ((mem_ir[15:11] == `BNN) && (nf == 1'b0))||  ((mem_ir[15:11] == `BC) && (cf == 1'b1)) || ((mem_ir[15:11] == `BNC) && (cf == 1'b0))||             mem_ir[15:11] == `JMPR)reg_A <= 16'b0000_0000_0000_0000;         else;                 //------------------根据不同的操作,reg_B的赋值以处理hazard------------------------------- if (id_ir[15:11] == `LDIH)reg_B <= {id_ir[7:0], 8'b0000_0000}; else if ((id_ir[15:11] == `LOAD) || (id_ir[15:11] == `STORE) || (id_ir[15:11] == `SLL)         || (id_ir[15:11] == `SRL) || (id_ir[15:11] == `SLA)   || (id_ir[15:11] == `SRA))reg_B <= {12'b0000_0000_0000, id_ir[3:0]}; else if ((id_ir[15:11] == `BZ) || (id_ir[15:11] == `BN) || (id_ir[15:11] == `BNZ) || (id_ir[15:11] == `BNN)|| (id_ir[15:11] == `JMPR)    || (id_ir[15:11] == `SUBI) || (id_ir[15:11] == `ADDI) || (id_ir[15:11] == `BC) || (id_ir[15:11] == `BNC) || (id_ir[15:11] == `JUMP))reg_B <= {8'b0000_0000, id_ir[7:0]}; else if ((id_ir[15:11] == `ADD)||(id_ir[15:11] == `ADDC)||(id_ir[15:11] == `SUB)||(id_ir[15:11] == `SUBC)       ||(id_ir[15:11] == `CMP)||(id_ir[15:11] == `AND) ||(id_ir[15:11] == `OR) ||(id_ir[15:11] == `XOR))                //ADD,ADDC,SUB,SUBC,AND,OR,XOR,CMPbegin    //处理ADD等hazardif((id_ir[2:0]==ex_ir[10:8])&&(ex_ir!=`NOP)&&(ex_ir!=`CMP)&&(ex_ir!=`JUMP)&&(ex_ir!=`LOAD)&&(ex_ir!=`HALT))//这些指令没有目的寄存器,LOAD指令是所需的内容还没有出来存     reg_B <= ALUo;                    //后一条指令要用到前一条指令的结果else if((id_ir[2:0]==mem_ir[10:8])&&(mem_ir!=`NOP)&&(mem_ir!=`CMP)&&(mem_ir!=`JUMP)&&(mem_ir!=`HALT))                //----------------------------------------------------------------------                begin     if(mem_ir[15:11]==`LOAD)     reg_B <= d_datain;     else     reg_B <= reg_C;                   //看看LOAD指令在这里会不会已经出结果了                end                //----------------------------------------------------------------------else if((id_ir[2:0]== wb_ir[10:8])&&(wb_ir!=`NOP)&&(wb_ir!=`CMP)&&(wb_ir!=`JUMP)&&(wb_ir!=`HALT))     reg_B <= reg_C1;else                //reg_B <= gr[id_ir[2:0]];                begin     if(id_ir[2:0] == 0)     reg_B <= gr[0];     else if(id_ir[2:0] == 1)     reg_B <= gr[1];     else if(id_ir[2:0] == 2)     reg_B <= gr[2];     else if(id_ir[2:0] == 3)     reg_B <= gr[3];     else if(id_ir[2:0] == 4)     reg_B <= gr[4];     else if(id_ir[2:0] == 5)     reg_B <= gr[5];     else if(id_ir[2:0] == 6)     reg_B <= gr[6];     else if(id_ir[2:0] == 7)     reg_B <= gr[7]; end  end  else if(((mem_ir[15:11] == `BZ) && (zf == 1'b1)) || ((mem_ir[15:11] == `BN) && (nf == 1'b1))||  ((mem_ir[15:11] == `BNZ) && (zf == 1'b0)) || ((mem_ir[15:11] == `BNN) && (nf == 1'b0))||  ((mem_ir[15:11] == `BC) && (cf == 1'b1)) || ((mem_ir[15:11] == `BNC) && (cf == 1'b0))||     mem_ir[15:11] == `JMPR)     reg_B <= 16'b0000_0000_0000_0000;          else;          //-----------------------------------------------------------------------------------------------------------------------------------          //--------------------------------------------------------------------对smdr的赋值---------------------------------------------------  if(id_ir[15:11] == `STORE)  //  smdr <= gr[id_ir[10:8]];          begin    //处理ADD等hazard      if((id_ir[10:8]==ex_ir[10:8])&&(ex_ir!=`NOP)&&(ex_ir!=`CMP)&&(ex_ir!=`JUMP)&&(ex_ir!=`LOAD)&&(ex_ir!=`HALT))//这些指令没有目的寄存器,LOAD指令是所需的内容还没有出来存      smdr <= ALUo;                    //后一条指令要用到前一条指令的结果      else if((id_ir[10:8]==mem_ir[10:8])&&(mem_ir!=`NOP)&&(mem_ir!=`CMP)&&(mem_ir!=`JUMP)&&(mem_ir!=`HALT))              //----------------------------------------------------------------------              beginif(mem_ir==`LOAD)smdr <= d_datain;elsesmdr <= reg_C;                                end              //----------------------------------------------------------------------      else if((id_ir[10:8]== wb_ir[10:8])&&(wb_ir!=`NOP)&&(wb_ir!=`CMP)&&(wb_ir!=`JUMP)&&(wb_ir!=`HALT))smdr <= reg_C1;      else                  smdr <= gr[id_ir[10:8]];   end     endend//wire flag_mem;reg [15:0]mem_ir,smdr1;reg [15:0]reg_C;reg [15:0]ALUo;reg zf,nf,cf,dw;reg cin;//************************* EX *****************************//always@(posedge clock)begin   if(!reset)   begin      mem_ir<= 16'b0000_0000_0000_0000;      smdr1 <= 16'b0000_0000_0000_0000;      reg_C <= 16'b0000_0000_0000_0000;      dw    <= 1'b0;      zf    <= 1'b0;      nf    <= 1'b0;   end   else if (state == `exec)   begin      mem_ir <= ex_ir;      smdr1  <= smdr;      reg_C  <= ALUo;            if ((ex_ir[15:11] == `ADDC) || (ex_ir[15:11] == `CMP) || (ex_ir[15:11] == `SUBC)|| (ex_ir[15:11] == `SUB) || (ex_ir[15:11] == `ADDI)|| (ex_ir[15:11] == `SUBI)        || (ex_ir[15:11] == `LDIH)|| (ex_ir[15:11] == `ADD) || (ex_ir[15:11] == `SLL)        || (ex_ir[15:11] == `SRL) || (ex_ir[15:11] == `SLA) || (ex_ir[15:11] == `SRA)|| (ex_ir[15:11] == `BZ)  || (ex_ir[15:11] == `BNZ) || (ex_ir[15:11] == `BN)        || (ex_ir[15:11] == `BNN) || (ex_ir[15:11] == `BC)  || (ex_ir[15:11] == `BNC)) //ADD和CMP指令中,nf为1当最高位为1时,此时结果是一个负数。      begin                                             //zf为1,当ALU输出结果为0时。      if (ALUo == 16'b0000_0000_0000_0000)zf <= 1'b1;      else        zf <= 1'b0;      if (ALUo[15] == 1'b1)        nf <= 1'b1;      elsenf <= 1'b0;      end      else      beginzf <= zf;nf <= nf;      end      if (ex_ir[15:11] == `STORE)             //如果指令是STORE的话,那么数据内存的写入使能赋为1,否则为0dw <= 1'b1;      elsedw <= 1'b0;      endend//--------------------------------ALU--------------------------------always @(reg_A or reg_B or ex_ir[15:11])            case(ex_ir[15:11])    `ADD:                                                   {cf,ALUo} <= reg_A + reg_B;                       //add    `ADDI:                                                   {cf,ALUo} <= reg_A + reg_B;                         //addi`ADDC:                                                     {cf,ALUo} <= reg_A + reg_B + cin;                   //addc`SUB:                                                 {cf,ALUo} <= reg_A - reg_B;                         //sub`SUBI:                                                 {cf,ALUo} <= reg_A - reg_B;                         //subi`SUBC:                                                {cf,ALUo} <= reg_A - reg_B - cin;                   //subc`CMP:     {cf,ALUo} <=  reg_A - reg_B;                        //cmp。计算a-b,根据结果得出flag的值`LOAD:                                                       {cf,ALUo} <= reg_A + reg_B;                         //load`STORE:                                                 {cf,ALUo} <= reg_A + reg_B;                       //store`LDIH:                                                    {cf,ALUo} <= reg_A + reg_B;                       //ldih                                          `AND:                   ALUo <= (reg_A & reg_B);                     //and         `OR:                   ALUo <= (reg_A | reg_B);                     //or                                              `XOR:                           ALUo <= (reg_A ^ reg_B);                     //xor        `SLL:                  ALUo <= (reg_A << reg_B[3:0]);               //ex_ir[3:0]);                                               //sll,使用的是指令中传过来的数据        `SLA:                                                        ALUo <= (reg_A <<< reg_B[3:0]);              //ex_ir[3:0]);              //sla        `SRL:           ALUo <= (reg_A >> reg_B[3:0]);               //ex_ir[3:0]);               //srl                 `SRA:                                               ALUo <= (reg_A >>> reg_B[3:0]);              //ex_ir[3:0]);         //sra         `BZ:                                   {cf,ALUo} <= reg_A + reg_B;                         //bz        `BNZ:                                   {cf,ALUo} <= reg_A + reg_B;                         //bnz  `BN:                                   {cf,ALUo} <= reg_A + reg_B;                         //bn`BNN:                                   {cf,ALUo} <= reg_A + reg_B;                         //bnn`BC:                                   {cf,ALUo} <= reg_A + reg_B;                         //bc`BNC:                                   {cf,ALUo} <= reg_A + reg_B;                         //bnc`JMPR:                                   {cf,ALUo} <= reg_A + reg_B;                         //jmprdefault:  begin                      ALUo <= ALUo;              cf <= cf;        end     endcasereg [15:0]wb_ir,reg_C1;//**************************************** MEM ************************************//always@(posedge clock)begin         if(!reset)      begin      cin      <= 1'b0;      wb_ir    <= 16'b0000_0000_0000_0000;      reg_C1   <= 16'b0000_0000_0000_0000;      d_we     <= 0;      d_addr   <= 8'b0;      d_dataout<= 16'b0;      end    else if (state == `exec)      begin      cin      <= cf;      wb_ir    <= mem_ir;      begin d_we     <= dw;         d_addr   <= reg_C[7:0];         d_dataout<= smdr1;      end      if (mem_ir[15:11] == `LOAD)            //除了LOAD指令外,reg_C1均来自reg_C reg_C1 <= d_datain; else//ADD,ADDC,SUB,SUBC,ADDI,SUBI,AND,OR,XOR,SLL,SRL,SLA,SRA(CMP应该要特殊考虑) reg_C1 <= reg_C;       endend//*********************************** WB *****************************************//always@(posedge clock)if(!reset)begin      gr[7] <= 16'b0000_0000_0000_0000;      gr[6] <= 16'b0000_0000_0000_0000;      gr[5] <= 16'b0000_0000_0000_0000;      gr[4] <= 16'b0000_0000_0000_0000;      gr[3] <= 16'b0000_0000_0000_0000;      gr[2] <= 16'b0000_0000_0000_0000;      gr[1] <= 16'b0000_0000_0000_0000;      gr[0] <= 16'b0000_0000_0000_0000;endelse if (state == `exec)begin   if ((wb_ir[15:11] == `LOAD)|| (wb_ir[15:11] == `ADD) || (wb_ir[15:11] == `ADDC)    || (wb_ir[15:11] == `SUB) || (wb_ir[15:11] == `SUBC)|| (wb_ir[15:11] == `LDIH)    || (wb_ir[15:11] == `ADDI)|| (wb_ir[15:11] == `SUBI)|| (wb_ir[15:11] == `AND)     || (wb_ir[15:11] == `OR)  || (wb_ir[15:11] == `XOR) || (wb_ir[15:11] == `SLL)    || (wb_ir[15:11] == `SLA) || (wb_ir[15:11] == `SRL) || (wb_ir[15:11] == `SRA)  )gr[wb_ir[10:8]] <= reg_C1;   elsegr[wb_ir[10:8]] <= gr[wb_ir[10:8]];endelse;endmodule

仿真文件:

`timescale 1ns / 1ps////////////////////////////////////////////////////////////////////////////////// Company: // Engineer://// Create Date:   20:53:17 10/25/2013// Design Name:   CPU// Module Name:   F:/Digital_Practice/Practice/CPU/stimulus2.v// Project Name:  CPU// Revision 0.01 - File Created////////////////////////////////////////////////////////////////////////////////// state macro define`define idle1'b0`define exec1'b1// instruction macro define`define NOP5'b00000`define HALT5'b00001`define LOAD5'b00010`define STORE5'b00011`define SLL5'b00100`define SLA5'b00101`define SRL5'b00110`define SRA5'b00111`define ADD5'b01000`define ADDI5'b01001`define SUB5'b01010`define SUBI5'b01011`define CMP5'b01100`define AND5'b01101`define OR5'b01110`define XOR5'b01111`define LDIH5'b10000`define ADDC5'b10001`define SUBC5'b10010`define JUMP5'b11000`define JMPR5'b11001`define BZ5'b11010`define BNZ5'b11011`define BN5'b11100`define BNN5'b11101`define BC5'b11110`define BNC5'b11111// general register `define gr03'b000`define gr13'b001`define gr23'b010`define gr33'b011`define gr43'b100`define gr53'b101`define gr63'b110`define gr73'b111module stimulus2;// Inputsreg reset;reg enable;reg start;reg clock;reg [15:0] i_datain;reg [15:0] d_datain;// Outputswire d_we;wire [7:0] i_addr;wire [7:0] d_addr;wire [15:0] d_dataout;// Instantiate the Unit Under Test (UUT)CPU uut (.reset(reset), .enable(enable), .start(start), .clock(clock), .i_datain(i_datain), .d_datain(d_datain), .d_we(d_we), .i_addr(i_addr), .d_addr(d_addr), .d_dataout(d_dataout));initial begin$dumpfile("CPU.vcd");                $dumpvars(1,stimulus2.uut);// Initialize Inputsclock = 0;reset = 0;start = 0;enable = 0;d_datain = 0;i_datain = 0;// Wait 100 ns for global reset to finish#10;        // Add stimulus here//************* test pattern *************//$display("LOAD,ADD,HALT,SUB,STORE");$display("pc:     id_ir      :reg_A:reg_B:ALUo:reg_C:da:dd  :w:reC1:gr1 :gr2 :gr3 :exir:mmir:wbir:smdr");$monitor("%h:%b:%h :%h :%h :%h :%h:%h:%b:%h:%h:%h:%h:%h:%h:%h:%h:%b", uut.pc, uut.id_ir, uut.reg_A, uut.reg_B, uut.ALUo,uut.reg_C,d_addr, d_dataout, d_we, uut.reg_C1, uut.gr[1], uut.gr[2], uut.gr[3],uut.ex_ir,uut.mem_ir,uut.wb_ir,uut.smdr,uut.zf);enable <= 1; start <= 0; i_datain <= 0; d_datain <= 0; /*select_y <= 0;*/#10 reset  <= 0;#10 reset  <= 1;#10 enable <= 1;#10 start  <= 1;#10 start  <= 0;    i_datain <= {`LOAD, `gr1, 1'b0, `gr0, 4'b0000};  d_datain <= 16'hfC00;  // 3 clk later from LOAD#10  i_datain <= {`LOAD, `gr2, 1'b0, `gr0, 4'b0001};            #10;//阻塞相当于延迟一个周期取i_datain                #10  i_datain <= {`ADD, `gr3, 1'b0, `gr1, 1'b0, `gr2};                #10  i_datain <= {`ADD, `gr3, 1'b0, `gr1, 1'b0, `gr2};     d_datain <=   16'h10AB; #10 i_datain <= {`ADDC, `gr3, 1'b0, `gr2, 1'b0, `gr1};#10 i_datain <= {`SUB, `gr3, 1'b0, `gr2, 1'b0, `gr1};#10 i_datain <= {`SUBC, `gr3, 1'b0, `gr2, 1'b0, `gr1};                #10 i_datain <= {`STORE, `gr3, 1'b0, `gr0, 4'b0010};//#10 i_datain <= {`HALT, 11'b000_0000_0000};//#10 start <= 1;#10 start <= 0;$display("SLL,SRA,SLA,SRL");$display("pc:     id_ir      :reg_A:reg_B:ALUo:reg_C:da:dd  :w:reC1:gr1 :gr2 :gr3 :ddin:exir:mmir:wbir:smdr"); i_datain <= {`SLL, `gr3, 1'b0, `gr1, 4'b0010};#10 i_datain <= {`SRA, `gr3, 1'b0, `gr3, 4'b0010};#10 i_datain <= {`SLA, `gr3, 1'b0, `gr2, 4'b011};#10 i_datain <= {`SRL, `gr3, 1'b0, `gr2, 4'b0001};//#10 i_datain <= {`HALT, 11'b000_0000_0000};//#10 start <= 1;#10 start <= 0;$display("LDIH,SUBI,BZ,AND,OR,XOR");$display("pc:     id_ir      :reg_A:reg_B:ALUo:reg_C:da:dd  :w:reC1:gr1 :gr2 :gr3 :ddin:exir:mmir:wbir:smdr:zf"); i_datain <= {`LDIH, `gr1, 8'b0000_0100 };#10 i_datain <= {`BZ, `gr3, 4'b0000, 4'b0001 };#10 i_datain <= {`ADDI, `gr1, 4'b1111, 4'b1111 };#10 i_datain <= {`AND, `gr3, 1'b0,`gr1, 1'b0,`gr2 };#10 i_datain <= {`OR, `gr3,1'b0, `gr1,1'b0, `gr2 };#10 i_datain <= {`XOR, `gr3, 1'b0,`gr1, 1'b0,`gr2 };#10 i_datain <= {`HALT, 11'b000_0000_0000};#10 i_datain <= {`BZ, `gr3, 4'b0000, 4'b0001 };#10 i_datain <= {`ADDI, `gr1, 4'b1111, 4'b1111 };#10 i_datain <= {`AND, `gr3, 1'b0,`gr1, 1'b0,`gr2 };#10 i_datain <= {`OR, `gr3,1'b0, `gr1,1'b0, `gr2 };#10 i_datain <= {`XOR, `gr3, 1'b0,`gr1, 1'b0,`gr2 };#10 i_datain <= {`HALT, 11'b000_0000_0000};#10 i_datain <= {`BZ, `gr3, 4'b0000, 4'b0001 };#10 i_datain <= {`ADDI, `gr1, 4'b1111, 4'b1111 };#10 i_datain <= {`AND, `gr3, 1'b0,`gr1, 1'b0,`gr2 };#10 i_datain <= {`OR, `gr3,1'b0, `gr1,1'b0, `gr2 };#10 i_datain <= {`XOR, `gr3, 1'b0,`gr1, 1'b0,`gr2 };#10 i_datain <= {`HALT, 11'b000_0000_0000};end      always #5 clock = ~clock;      endmodule

综合结果:



仿真结果:


0 0
原创粉丝点击