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

来源:互联网 发布:淘宝哪家店pa改正版 编辑:程序博客网 时间:2024/04/30 07:07

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

• 实验步骤

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代码:

[plain] view plaincopy
  1. `timescale 1ns / 1ps  
  2. // state macro define  
  3. `define idle    1'b0  
  4. `define exec    1'b1  
  5. // instruction macro define  
  6. `define NOP 5'b00000  
  7. `define HALT    5'b00001  
  8. `define LOAD    5'b00010  
  9. `define STORE   5'b00011  
  10. `define SLL 5'b00100  
  11. `define SLA 5'b00101  
  12. `define SRL 5'b00110  
  13. `define SRA 5'b00111  
  14. `define ADD 5'b01000  
  15. `define ADDI    5'b01001  
  16. `define SUB 5'b01010  
  17. `define SUBI    5'b01011  
  18. `define CMP 5'b01100  
  19. `define AND 5'b01101  
  20. `define OR  5'b01110  
  21. `define XOR 5'b01111  
  22. `define LDIH    5'b10000  
  23. `define ADDC    5'b10001  
  24. `define SUBC    5'b10010  
  25. `define JUMP    5'b11000  
  26. `define JMPR    5'b11001  
  27. `define BZ  5'b11010  
  28. `define BNZ 5'b11011  
  29. `define BN  5'b11100  
  30. `define BNN 5'b11101  
  31. `define BC  5'b11110  
  32. `define BNC 5'b11111  
  33. // general register  
  34. `define gr0 3'b000  
  35. `define gr1 3'b001  
  36. `define gr2 3'b010  
  37. `define gr3 3'b011  
  38. `define gr4 3'b100  
  39. `define gr5 3'b101  
  40. `define gr6 3'b110  
  41. `define gr7 3'b111  
  42.    
  43. module CPU(input wire  reset,  
  44.        input wire  enable,          //make the  
  45.        input wire  start,           //start CPU  
  46.        input wire  clock,           //clock  
  47.        input wire  [15:0]i_datain,  //instruction  
  48.        input wire  [15:0]d_datain,  //data from memory  
  49.        output reg  d_we,            //write enable  
  50.        output wire [7:0]i_addr,     //pc  
  51.        output reg  [7:0]d_addr,     //output adder for data memory  
  52.        output reg  [15:0]d_dataout  //output data to data memory  
  53. );  
  54.         
  55. reg [15:0]gr[7:0];             //register file  
  56. reg state,next_state;          //to control the CPU  
  57.   
  58. assign i_addr      =    pc;  
  59.   
  60. //************* CPU control *************//  
  61. always @(posedge clock)  
  62. begin  
  63.   if (!reset)  
  64.       state <= `idle;  
  65.   else  
  66.       state <= next_state;  
  67. end  
  68.       
  69. always@(*)  
  70. begin  
  71.    case (state)  
  72.    `idle :   
  73.     if ((enable == 1'b1) && (start == 1'b1))  
  74.     next_state <= `exec;  
  75.     else      
  76.     next_state <= `idle;  
  77.    `exec :  
  78.     if ((enable == 1'b0) || (wb_ir[15:11] == `HALT))  
  79.     next_state <= `idle;  
  80.     else  
  81.     next_state <= `exec;  
  82.    endcase  
  83. end  
  84. //_______________________________________________  
  85.   
  86. reg [15:0]id_ir;  
  87. reg [7:0]pc;  
  88. //************* IF *************//  
  89. always@(posedge clock or negedge reset)  
  90. begin  
  91.    if (!reset)  
  92.    begin  
  93.     id_ir <= 16'b0000_0000_0000_0000;  
  94.     pc <= 8'b0000_0000;  
  95.    end            
  96.    else if (state ==`exec)  
  97.    begin                  
  98.     if(((ex_ir[15:11] == `BZ) && (zf == 1'b1)) || ((ex_ir[15:11] == `BN) && (nf == 1'b1))||  
  99.      ((ex_ir[15:11] == `BNZ) && (zf == 1'b0)) || ((ex_ir[15:11] == `BNN) && (nf == 1'b0))||  
  100.       ((ex_ir[15:11] == `BC) && (cf == 1'b1)) || ((ex_ir[15:11] == `BNC) && (cf == 1'b0))||   
  101.         ex_ir[15:11] == `JMPR)  
  102.         begin  
  103.         pc <= ALUo[7:0];  
  104.         id_ir <= i_datain;  
  105.         end  
  106.     else if(id_ir[15:11] == `JUMP)//如果判断出指令是JUMP,直接跳转,就可以减少功耗,不必冒险  
  107.         begin  
  108.         pc <= id_ir[7:0];  
  109.         id_ir <= i_datain;  
  110.         end  
  111.          //------------------------------------------------对于LOAD的处理--------------------------------------                    
  112.     else if((id_ir[15:11] == `LOAD)&&(i_datain[15:11]!=`JUMP)&&(i_datain[15:11]!=`NOP)&&(i_datain[15:11]!=`HALT)  
  113.                 &&(i_datain[15:11]!=`LOAD))  
  114.         begin  
  115.         if((id_ir[10:8]==i_datain[2:0])&&((i_datain[15:11]==`ADD)||(i_datain[15:11]==`ADDC)||(i_datain[15:11]==`SUB)  
  116.          ||(i_datain[15:11]==`SUBC)||(i_datain[15:11]==`CMP)||(i_datain[15:11]==`AND)||(i_datain[15:11]==`OR)  
  117.                  ||(i_datain[15:11]==`XOR)))  
  118.             begin  
  119.             pc <= pc;  
  120.             id_ir <= 16'bx;  
  121.             end  
  122.         else if((id_ir[10:8]==i_datain[6:4])&&((i_datain[15:11]==`STORE)||(i_datain[15:11]==`ADD)||(i_datain[15:11]==`ADDC)  
  123.               ||(i_datain[15:11]==`SUB)||(i_datain[15:11]==`SUBC)||(i_datain[15:11]==`AND)||(i_datain[15:11]==`OR)  
  124.                       ||(i_datain[15:11]==`XOR)||(i_datain[15:11]==`CMP)||(i_datain[15:11]==`SLL)||(i_datain[15:11]==`SRL)  
  125.                       ||(i_datain[15:11]==`SLA)||(i_datain[15:11]==`SRA)  
  126.          ))  
  127.             begin  
  128.             pc <= pc;  
  129.             id_ir <= 16'bx;  
  130.             end  
  131.         else if((id_ir[10:8]==i_datain[10:8])&&((i_datain[15:11]==`STORE)||(i_datain[15:11]==`LDIH)||(i_datain[15:11]==`SUBI)  
  132.            ||(i_datain[15:11]==`JMPR)||(i_datain[15:11]==`BZ)||(i_datain[15:11]==`BNZ)||(i_datain[15:11]==`BN)  
  133.            ||(i_datain[15:11]==`BNN)||(i_datain[15:11]==`BNC)))  
  134.             begin  
  135.             pc <= pc;  
  136.             id_ir <= 16'bx;  
  137.             end  
  138.             end   
  139.         else  
  140.             begin  
  141.             pc <= pc + 1;  
  142.                     id_ir <= i_datain;             
  143.                 end  
  144.     end  
  145.     else if (state ==`idle)  
  146.         pc <= pc;  
  147.         else;  
  148. end  
  149. //----------------------------------------------------------------------------------------------------------------------------------------------------    
  150.   
  151. reg [15:0]ex_ir,reg_A,reg_B,smdr;  
  152. //************* ID *************//  
  153. always@(posedge clock or negedge reset)  
  154. begin  
  155.    if(!reset)  
  156.    begin  
  157.     ex_ir <= 16'b0000_0000_0000_0000;  
  158.     reg_A <= 16'b0000_0000_0000_0000;  
  159.     reg_B <= 16'b0000_0000_0000_0000;  
  160.     smdr  <= 16'b0000_0000_0000_0000;  
  161.    end  
  162.    else if (state == `exec)  
  163.    begin  
  164.     ex_ir <= id_ir;  
  165.         //------------------根据不同的操作,reg_A的赋值以处理hazard-------------------------------                  
  166.     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)  
  167.     || (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))  
  168.                begin    //处理ADD等hazard  
  169.            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指令是所需的内容还没有出来存  
  170.           reg_A <= ALUo;                    //后一条指令要用到前一条指令的结果  
  171.            else if((id_ir[10:8]==mem_ir[10:8])&&(mem_ir!=`NOP)&&(mem_ir!=`CMP)&&(mem_ir!=`JUMP)&&(mem_ir!=`HALT))  
  172.                //----------------------------------------------------------------------                   
  173.                    begin  
  174.            if(mem_ir==`LOAD)  
  175.            reg_A <= d_datain;  
  176.            else  
  177.                reg_A <= reg_C;                   //看看LOAD指令在这里会不会已经出结果了  
  178.                    end  
  179.                //----------------------------------------------------------------------  
  180.            else if((id_ir[10:8]== wb_ir[10:8])&&(wb_ir!=`NOP)&&(wb_ir!=`CMP)&&(wb_ir!=`JUMP)&&(wb_ir!=`HALT))  
  181.            reg_A <= reg_C1;  
  182.            else  
  183.                   //reg_A <= gr[id_ir[10:8]];  
  184.            begin  
  185.             if(id_ir[10:8] == 0)  
  186.             reg_A <= gr[0];  
  187.             else if(id_ir[10:8] == 1)  
  188.             reg_A <= gr[1];  
  189.             else if(id_ir[10:8] == 2)  
  190.             reg_A <= gr[2];  
  191.             else if(id_ir[10:8] == 3)  
  192.             reg_A <= gr[3];  
  193.             else if(id_ir[10:8] == 4)  
  194.             reg_A <= gr[4];  
  195.             else if(id_ir[10:8] == 5)  
  196.             reg_A <= gr[5];  
  197.             else if(id_ir[10:8] == 6)  
  198.             reg_A <= gr[6];  
  199.             else if(id_ir[10:8] == 7)  
  200.             reg_A <= gr[7];  
  201.             end  
  202.         end  
  203.     else 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)  
  204.              ||(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)  
  205.          ||(id_ir[15:11] == `SLL) ||(id_ir[15:11] == `SRL) ||(id_ir[15:11] == `SLA)  ||(id_ir[15:11] == `SRA))                   
  206.     //LAOD,STORE,CMP,ADD,ADDC,SUB,SUBC,AND,OR,XOR,SLL,SRL,SLA,SRA     
  207.     begin    //处理ADD等hazard  
  208.        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指令是所需的内容还没有出来存  
  209.         reg_A <= ALUo;                    //后一条指令要用到前一条指令的结果  
  210.        else if((id_ir[6:4]==mem_ir[10:8])&&(mem_ir!=`NOP)&&(mem_ir!=`CMP)&&(mem_ir!=`JUMP)&&(mem_ir!=`HALT))  
  211.            //----------------------------------------------------------------------                   
  212.                begin  
  213.                if(mem_ir[15:11]==`LOAD)  
  214.            reg_A <= d_datain;  
  215.            else  
  216.            reg_A <= reg_C;                     
  217.                end  
  218.             //----------------------------------------------------------------------  
  219.         else if((id_ir[6:4]== wb_ir[10:8])&&(wb_ir!=`NOP)&&(wb_ir!=`CMP)&&(wb_ir!=`JUMP)&&(wb_ir!=`HALT))  
  220.            reg_A <= reg_C1;  
  221.         else  
  222.                 begin  
  223.                 if(id_ir[6:4] == 0)  
  224.             reg_A <= gr[0];  
  225.                 else if(id_ir[6:4] == 1)  
  226.                     reg_A <= gr[1];  
  227.         else if(id_ir[6:4] == 2)  
  228.             reg_A <= gr[2];  
  229.         else if(id_ir[6:4] == 3)  
  230.             reg_A <= gr[3];  
  231.         else if(id_ir[6:4] == 4)  
  232.             reg_A <= gr[4];  
  233.         else if(id_ir[6:4] == 5)  
  234.             reg_A <= gr[5];  
  235.         else if(id_ir[6:4] == 6)  
  236.             reg_A <= gr[6];  
  237.         else if(id_ir[6:4] == 7)  
  238.             reg_A <= gr[7];                        
  239.             end  
  240.      end  
  241.          else if((( mem_ir[15:11] == `BZ) && (zf == 1'b1)) || ((mem_ir[15:11] == `BN) && (nf == 1'b1)) ||  
  242.          (( mem_ir[15:11] == `BNZ) && (zf == 1'b0))|| ((mem_ir[15:11] == `BNN) && (nf == 1'b0))||  
  243.           ((mem_ir[15:11] == `BC) && (cf == 1'b1)) || ((mem_ir[15:11] == `BNC) && (cf == 1'b0))||   
  244.                 mem_ir[15:11] == `JMPR)  
  245.         reg_A <= 16'b0000_0000_0000_0000;  
  246.          else;          
  247.          //------------------根据不同的操作,reg_B的赋值以处理hazard-------------------------------  
  248.      if (id_ir[15:11] == `LDIH)  
  249.         reg_B <= {id_ir[7:0], 8'b0000_0000};  
  250.      else if ((id_ir[15:11] == `LOAD) || (id_ir[15:11] == `STORE) || (id_ir[15:11] == `SLL)  
  251.            || (id_ir[15:11] == `SRL) || (id_ir[15:11] == `SLA)   || (id_ir[15:11] == `SRA))  
  252.         reg_B <= {12'b0000_0000_0000, id_ir[3:0]};  
  253.      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)  
  254.         || (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))  
  255.         reg_B <= {8'b0000_0000, id_ir[7:0]};  
  256.      else if ((id_ir[15:11] == `ADD)||(id_ir[15:11] == `ADDC)||(id_ir[15:11] == `SUB)||(id_ir[15:11] == `SUBC)  
  257.            ||(id_ir[15:11] == `CMP)||(id_ir[15:11] == `AND) ||(id_ir[15:11] == `OR) ||(id_ir[15:11] == `XOR))                  
  258.         //ADD,ADDC,SUB,SUBC,AND,OR,XOR,CMP    
  259.         begin    //处理ADD等hazard  
  260.         if((id_ir[2:0]==ex_ir[10:8])&&(ex_ir!=`NOP)&&(ex_ir!=`CMP)&&(ex_ir!=`JUMP)&&(ex_ir!=`LOAD)&&(ex_ir!=`HALT))//这些指令没有目的寄存器,LOAD指令是所需的内容还没有出来存  
  261.              reg_B <= ALUo;                    //后一条指令要用到前一条指令的结果  
  262.         else if((id_ir[2:0]==mem_ir[10:8])&&(mem_ir!=`NOP)&&(mem_ir!=`CMP)&&(mem_ir!=`JUMP)&&(mem_ir!=`HALT))  
  263.                 //----------------------------------------------------------------------                      
  264.                 begin  
  265.              if(mem_ir[15:11]==`LOAD)  
  266.              reg_B <= d_datain;  
  267.              else  
  268.              reg_B <= reg_C;                   //看看LOAD指令在这里会不会已经出结果了  
  269.                 end  
  270.                 //----------------------------------------------------------------------  
  271.         else if((id_ir[2:0]== wb_ir[10:8])&&(wb_ir!=`NOP)&&(wb_ir!=`CMP)&&(wb_ir!=`JUMP)&&(wb_ir!=`HALT))  
  272.              reg_B <= reg_C1;  
  273.         else  
  274.                 //reg_B <= gr[id_ir[2:0]];  
  275.                 begin  
  276.              if(id_ir[2:0] == 0)  
  277.              reg_B <= gr[0];  
  278.              else if(id_ir[2:0] == 1)  
  279.              reg_B <= gr[1];  
  280.              else if(id_ir[2:0] == 2)  
  281.              reg_B <= gr[2];  
  282.              else if(id_ir[2:0] == 3)  
  283.              reg_B <= gr[3];  
  284.              else if(id_ir[2:0] == 4)  
  285.              reg_B <= gr[4];  
  286.              else if(id_ir[2:0] == 5)  
  287.              reg_B <= gr[5];  
  288.              else if(id_ir[2:0] == 6)  
  289.              reg_B <= gr[6];  
  290.              else if(id_ir[2:0] == 7)  
  291.              reg_B <= gr[7];  
  292.          end  
  293.       end  
  294.       else if(((mem_ir[15:11] == `BZ) && (zf == 1'b1)) || ((mem_ir[15:11] == `BN) && (nf == 1'b1))||  
  295.           ((mem_ir[15:11] == `BNZ) && (zf == 1'b0)) || ((mem_ir[15:11] == `BNN) && (nf == 1'b0))||  
  296.           ((mem_ir[15:11] == `BC) && (cf == 1'b1)) || ((mem_ir[15:11] == `BNC) && (cf == 1'b0))||   
  297.             mem_ir[15:11] == `JMPR)  
  298.              reg_B <= 16'b0000_0000_0000_0000;  
  299.           else;  
  300.           //-----------------------------------------------------------------------------------------------------------------------------------  
  301.           //--------------------------------------------------------------------对smdr的赋值---------------------------------------------------  
  302.       if(id_ir[15:11] == `STORE)  
  303.       //  smdr <= gr[id_ir[10:8]];  
  304.           begin    //处理ADD等hazard  
  305.           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指令是所需的内容还没有出来存  
  306.           smdr <= ALUo;                    //后一条指令要用到前一条指令的结果  
  307.           else if((id_ir[10:8]==mem_ir[10:8])&&(mem_ir!=`NOP)&&(mem_ir!=`CMP)&&(mem_ir!=`JUMP)&&(mem_ir!=`HALT))  
  308.               //----------------------------------------------------------------------                    
  309.               begin  
  310.         if(mem_ir==`LOAD)  
  311.         smdr <= d_datain;  
  312.         else  
  313.         smdr <= reg_C;                    
  314.               end  
  315.               //----------------------------------------------------------------------  
  316.           else if((id_ir[10:8]== wb_ir[10:8])&&(wb_ir!=`NOP)&&(wb_ir!=`CMP)&&(wb_ir!=`JUMP)&&(wb_ir!=`HALT))  
  317.         smdr <= reg_C1;  
  318.           else  
  319.                   smdr <= gr[id_ir[10:8]];  
  320.        end  
  321.      end  
  322. end  
  323.   
  324. //wire flag_mem;  
  325. reg [15:0]mem_ir,smdr1;       
  326. reg [15:0]reg_C;  
  327. reg [15:0]ALUo;  
  328. reg zf,nf,cf,dw;  
  329. reg cin;  
  330. //************************* EX *****************************//    
  331. always@(posedge clock)  
  332. begin  
  333.    if(!reset)  
  334.    begin  
  335.       mem_ir<= 16'b0000_0000_0000_0000;  
  336.       smdr1 <= 16'b0000_0000_0000_0000;  
  337.       reg_C <= 16'b0000_0000_0000_0000;  
  338.       dw    <= 1'b0;  
  339.       zf    <= 1'b0;  
  340.       nf    <= 1'b0;  
  341.    end  
  342.    else if (state == `exec)  
  343.    begin  
  344.       mem_ir <= ex_ir;  
  345.       smdr1  <= smdr;  
  346.       reg_C  <= ALUo;        
  347.       if ((ex_ir[15:11] == `ADDC) || (ex_ir[15:11] == `CMP) || (ex_ir[15:11] == `SUBC)  
  348.     || (ex_ir[15:11] == `SUB) || (ex_ir[15:11] == `ADDI)|| (ex_ir[15:11] == `SUBI)  
  349.         || (ex_ir[15:11] == `LDIH)|| (ex_ir[15:11] == `ADD) || (ex_ir[15:11] == `SLL)  
  350.         || (ex_ir[15:11] == `SRL) || (ex_ir[15:11] == `SLA) || (ex_ir[15:11] == `SRA)  
  351.     || (ex_ir[15:11] == `BZ)  || (ex_ir[15:11] == `BNZ) || (ex_ir[15:11] == `BN)  
  352.         || (ex_ir[15:11] == `BNN) || (ex_ir[15:11] == `BC)  || (ex_ir[15:11] == `BNC))  
  353.      //ADD和CMP指令中,nf为1当最高位为1时,此时结果是一个负数。  
  354.       begin                                             //zf为1,当ALU输出结果为0时。  
  355.       if (ALUo == 16'b0000_0000_0000_0000)  
  356.     zf <= 1'b1;  
  357.       else  
  358.         zf <= 1'b0;  
  359.       if (ALUo[15] == 1'b1)  
  360.         nf <= 1'b1;  
  361.       else  
  362.     nf <= 1'b0;  
  363.       end  
  364.       else  
  365.       begin  
  366.     zf <= zf;  
  367.     nf <= nf;  
  368.       end  
  369.       if (ex_ir[15:11] == `STORE)             //如果指令是STORE的话,那么数据内存的写入使能赋为1,否则为0  
  370.     dw <= 1'b1;  
  371.       else  
  372.     dw <= 1'b0;  
  373.       end     
  374. end  
  375.   
  376. //--------------------------------ALU--------------------------------  
  377. always @(reg_A or reg_B or ex_ir[15:11])        
  378.       case(ex_ir[15:11])  
  379.         `ADD:                                                
  380.                      {cf,ALUo} <= reg_A + reg_B;                       //add  
  381.         `ADDI:                                                
  382.                      {cf,ALUo} <= reg_A + reg_B;                         //addi  
  383.         `ADDC:                                                  
  384.                      {cf,ALUo} <= reg_A + reg_B + cin;                   //addc  
  385.         `SUB:                                        
  386.                      {cf,ALUo} <= reg_A - reg_B;                         //sub  
  387.         `SUBI:                                       
  388.                      {cf,ALUo} <= reg_A - reg_B;                         //subi  
  389.         `SUBC:                                      
  390.                      {cf,ALUo} <= reg_A - reg_B - cin;                   //subc  
  391.         `CMP:  
  392.                      {cf,ALUo} <=  reg_A - reg_B;                        //cmp。计算a-b,根据结果得出flag的值  
  393.         `LOAD:                                               
  394.                       {cf,ALUo} <= reg_A + reg_B;                         //load  
  395.         `STORE:                                              
  396.                      {cf,ALUo} <= reg_A + reg_B;                          //store  
  397.         `LDIH:                                               
  398.                {cf,ALUo} <= reg_A + reg_B;                        //ldih                                                       
  399.         `AND:   
  400.                           ALUo <= (reg_A & reg_B);                     //and   
  401.         `OR:   
  402.                           ALUo <= (reg_A | reg_B);                     //or                                        
  403.         `XOR:   
  404.                                   ALUo <= (reg_A ^ reg_B);                     //xor  
  405.         `SLL:   
  406.                                      ALUo <= (reg_A << reg_B[3:0]);               //ex_ir[3:0]);               
  407.                                   //sll,使用的是指令中传过来的数据  
  408.         `SLA:                       
  409.                                    ALUo <= (reg_A <<< reg_B[3:0]);              //ex_ir[3:0]);              //sla  
  410.         `SRL:   
  411.                               ALUo <= (reg_A >> reg_B[3:0]);               //ex_ir[3:0]);               //srl           
  412.         `SRA:       
  413.                                           ALUo <= (reg_A >>> reg_B[3:0]);              //ex_ir[3:0]);                //sra   
  414.         `BZ:  
  415.                                      {cf,ALUo} <= reg_A + reg_B;                         //bz  
  416.         `BNZ:  
  417.                                      {cf,ALUo} <= reg_A + reg_B;                         //bnz                   
  418.         `BN:  
  419.                                      {cf,ALUo} <= reg_A + reg_B;                         //bn  
  420.         `BNN:  
  421.                                      {cf,ALUo} <= reg_A + reg_B;                         //bnn  
  422.         `BC:  
  423.                                      {cf,ALUo} <= reg_A + reg_B;                         //bc  
  424.         `BNC:  
  425.                                      {cf,ALUo} <= reg_A + reg_B;                         //bnc  
  426.         `JMPR:  
  427.                                      {cf,ALUo} <= reg_A + reg_B;                         //jmpr  
  428.         default:    
  429.         begin  
  430.                               ALUo <= ALUo;  
  431.                           cf <= cf;  
  432.             end  
  433.      endcase  
  434.   
  435.   
  436. reg [15:0]wb_ir,reg_C1;       
  437. //**************************************** MEM ************************************//  
  438. always@(posedge clock)  
  439. begin           
  440.    if(!reset)  
  441.       begin  
  442.       cin      <= 1'b0;  
  443.       wb_ir    <= 16'b0000_0000_0000_0000;  
  444.       reg_C1   <= 16'b0000_0000_0000_0000;  
  445.       d_we     <= 0;  
  446.       d_addr   <= 8'b0;  
  447.       d_dataout<= 16'b0;  
  448.       end  
  449.     else if (state == `exec)  
  450.       begin  
  451.       cin      <= cf;  
  452.       wb_ir    <= mem_ir;  
  453.       begin  
  454.      d_we     <= dw;  
  455.          d_addr   <= reg_C[7:0];  
  456.          d_dataout<= smdr1;  
  457.       end  
  458.       if (mem_ir[15:11] == `LOAD)            //除了LOAD指令外,reg_C1均来自reg_C  
  459.      reg_C1 <= d_datain;  
  460.      else//ADD,ADDC,SUB,SUBC,ADDI,SUBI,AND,OR,XOR,SLL,SRL,SLA,SRA(CMP应该要特殊考虑)  
  461.      reg_C1 <= reg_C;  
  462.        end    
  463. end   
  464.   
  465.   
  466. //*********************************** WB *****************************************//  
  467. always@(posedge clock)  
  468. if(!reset)  
  469. begin  
  470.       gr[7] <= 16'b0000_0000_0000_0000;  
  471.       gr[6] <= 16'b0000_0000_0000_0000;  
  472.       gr[5] <= 16'b0000_0000_0000_0000;  
  473.       gr[4] <= 16'b0000_0000_0000_0000;  
  474.       gr[3] <= 16'b0000_0000_0000_0000;  
  475.       gr[2] <= 16'b0000_0000_0000_0000;  
  476.       gr[1] <= 16'b0000_0000_0000_0000;  
  477.       gr[0] <= 16'b0000_0000_0000_0000;  
  478. end  
  479. else if (state == `exec)  
  480. begin  
  481.    if ((wb_ir[15:11] == `LOAD)|| (wb_ir[15:11] == `ADD) || (wb_ir[15:11] == `ADDC)  
  482.     || (wb_ir[15:11] == `SUB) || (wb_ir[15:11] == `SUBC)|| (wb_ir[15:11] == `LDIH)  
  483.     || (wb_ir[15:11] == `ADDI)|| (wb_ir[15:11] == `SUBI)|| (wb_ir[15:11] == `AND)   
  484.     || (wb_ir[15:11] == `OR)  || (wb_ir[15:11] == `XOR) || (wb_ir[15:11] == `SLL)  
  485.     || (wb_ir[15:11] == `SLA) || (wb_ir[15:11] == `SRL) || (wb_ir[15:11] == `SRA)  )  
  486.     gr[wb_ir[10:8]] <= reg_C1;  
  487.    else  
  488.     gr[wb_ir[10:8]] <= gr[wb_ir[10:8]];  
  489. end  
  490. else;  
  491.   
  492. endmodule  

仿真文件:

[plain] view plaincopy
  1. `timescale 1ns / 1ps  
  2.   
  3. ////////////////////////////////////////////////////////////////////////////////  
  4. // Company:   
  5. // Engineer:  
  6. //  
  7. // Create Date:   20:53:17 10/25/2013  
  8. // Design Name:   CPU  
  9. // Module Name:   F:/Digital_Practice/Practice/CPU/stimulus2.v  
  10. // Project Name:  CPU  
  11. // Revision 0.01 - File Created  
  12. ////////////////////////////////////////////////////////////////////////////////  
  13. // state macro define  
  14. `define idle    1'b0  
  15. `define exec    1'b1  
  16. // instruction macro define  
  17. `define NOP 5'b00000  
  18. `define HALT    5'b00001  
  19. `define LOAD    5'b00010  
  20. `define STORE   5'b00011  
  21. `define SLL 5'b00100  
  22. `define SLA 5'b00101  
  23. `define SRL 5'b00110  
  24. `define SRA 5'b00111  
  25. `define ADD 5'b01000  
  26. `define ADDI    5'b01001  
  27. `define SUB 5'b01010  
  28. `define SUBI    5'b01011  
  29. `define CMP 5'b01100  
  30. `define AND 5'b01101  
  31. `define OR  5'b01110  
  32. `define XOR 5'b01111  
  33. `define LDIH    5'b10000  
  34. `define ADDC    5'b10001  
  35. `define SUBC    5'b10010  
  36. `define JUMP    5'b11000  
  37. `define JMPR    5'b11001  
  38. `define BZ  5'b11010  
  39. `define BNZ 5'b11011  
  40. `define BN  5'b11100  
  41. `define BNN 5'b11101  
  42. `define BC  5'b11110  
  43. `define BNC 5'b11111  
  44. // general register   
  45. `define gr0 3'b000  
  46. `define gr1 3'b001  
  47. `define gr2 3'b010  
  48. `define gr3 3'b011  
  49. `define gr4 3'b100  
  50. `define gr5 3'b101  
  51. `define gr6 3'b110  
  52. `define gr7 3'b111  
  53.   
  54. module stimulus2;  
  55.   
  56.     // Inputs  
  57.     reg reset;  
  58.     reg enable;  
  59.     reg start;  
  60.     reg clock;  
  61.     reg [15:0] i_datain;  
  62.     reg [15:0] d_datain;  
  63.   
  64.     // Outputs  
  65.     wire d_we;  
  66.     wire [7:0] i_addr;  
  67.     wire [7:0] d_addr;  
  68.     wire [15:0] d_dataout;  
  69.   
  70.     // Instantiate the Unit Under Test (UUT)  
  71.     CPU uut (  
  72.         .reset(reset),   
  73.         .enable(enable),   
  74.         .start(start),   
  75.         .clock(clock),   
  76.         .i_datain(i_datain),   
  77.         .d_datain(d_datain),   
  78.         .d_we(d_we),   
  79.         .i_addr(i_addr),   
  80.         .d_addr(d_addr),   
  81.         .d_dataout(d_dataout)  
  82.     );  
  83.   
  84. initial begin  
  85.         $dumpfile("CPU.vcd");  
  86.                 $dumpvars(1,stimulus2.uut);  
  87.         // Initialize Inputs  
  88.         clock = 0;  
  89.         reset = 0;  
  90.         start = 0;  
  91.         enable = 0;  
  92.         d_datain = 0;  
  93.         i_datain = 0;  
  94.   
  95.         // Wait 100 ns for global reset to finish  
  96.         #10;  
  97.           
  98.         // Add stimulus here  
  99.         //************* test pattern *************//      
  100.         $display("LOAD,ADD,HALT,SUB,STORE");  
  101.         $display("pc:     id_ir      :reg_A:reg_B:ALUo:reg_C:da:dd  :w:reC1:gr1 :gr2 :gr3 :exir:mmir:wbir:smdr");  
  102.         $monitor("%h:%b:%h :%h :%h :%h :%h:%h:%b:%h:%h:%h:%h:%h:%h:%h:%h:%b",   
  103.             uut.pc, uut.id_ir, uut.reg_A, uut.reg_B, uut.ALUo,uut.reg_C,  
  104.             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);  
  105.               
  106.         enable <= 1; start <= 0; i_datain <= 0; d_datain <= 0; /*select_y <= 0;*/  
  107.   
  108.         #10 reset  <= 0;  
  109.         #10 reset  <= 1;  
  110.         #10 enable <= 1;  
  111.         #10 start  <= 1;  
  112.         #10 start  <= 0;  
  113.               i_datain <= {`LOAD, `gr1, 1'b0, `gr0, 4'b0000};  
  114.               d_datain <= 16'hfC00;  // 3 clk later from LOAD  
  115.         #10  i_datain <= {`LOAD, `gr2, 1'b0, `gr0, 4'b0001};                               
  116.         #10;//阻塞相当于延迟一个周期取i_datain                        
  117.                 #10  i_datain <= {`ADD, `gr3, 1'b0, `gr1, 1'b0, `gr2};  
  118.                 #10  i_datain <= {`ADD, `gr3, 1'b0, `gr1, 1'b0, `gr2};  
  119.              d_datain <=   16'h10AB;   
  120.   
  121.         #10 i_datain <= {`ADDC, `gr3, 1'b0, `gr2, 1'b0, `gr1};  
  122.         #10 i_datain <= {`SUB, `gr3, 1'b0, `gr2, 1'b0, `gr1};  
  123.         #10 i_datain <= {`SUBC, `gr3, 1'b0, `gr2, 1'b0, `gr1};  
  124.                 #10 i_datain <= {`STORE, `gr3, 1'b0, `gr0, 4'b0010};  
  125.           
  126.         //#10 i_datain <= {`HALT, 11'b000_0000_0000};  
  127.         //  
  128.         #10 start <= 1;  
  129.         #10 start <= 0;  
  130.         $display("SLL,SRA,SLA,SRL");  
  131.         $display("pc:     id_ir      :reg_A:reg_B:ALUo:reg_C:da:dd  :w:reC1:gr1 :gr2 :gr3 :ddin:exir:mmir:wbir:smdr");  
  132.              i_datain <= {`SLL, `gr3, 1'b0, `gr1, 4'b0010};  
  133.         #10 i_datain <= {`SRA, `gr3, 1'b0, `gr3, 4'b0010};  
  134.         #10 i_datain <= {`SLA, `gr3, 1'b0, `gr2, 4'b011};  
  135.         #10 i_datain <= {`SRL, `gr3, 1'b0, `gr2, 4'b0001};  
  136.         //#10 i_datain <= {`HALT, 11'b000_0000_0000};  
  137.         //  
  138.         #10 start <= 1;  
  139.           
  140.         #10 start <= 0;  
  141.         $display("LDIH,SUBI,BZ,AND,OR,XOR");  
  142.         $display("pc:     id_ir      :reg_A:reg_B:ALUo:reg_C:da:dd  :w:reC1:gr1 :gr2 :gr3 :ddin:exir:mmir:wbir:smdr:zf");  
  143.              i_datain <= {`LDIH, `gr1, 8'b0000_0100 };  
  144.         #10 i_datain <= {`BZ, `gr3, 4'b0000, 4'b0001 };  
  145.         #10 i_datain <= {`ADDI, `gr1, 4'b1111, 4'b1111 };  
  146.         #10 i_datain <= {`AND, `gr3, 1'b0,`gr1, 1'b0,`gr2 };  
  147.         #10 i_datain <= {`OR, `gr3,1'b0, `gr1,1'b0, `gr2 };  
  148.         #10 i_datain <= {`XOR, `gr3, 1'b0,`gr1, 1'b0,`gr2 };  
  149.         #10 i_datain <= {`HALT, 11'b000_0000_0000};  
  150.         #10 i_datain <= {`BZ, `gr3, 4'b0000, 4'b0001 };  
  151.         #10 i_datain <= {`ADDI, `gr1, 4'b1111, 4'b1111 };  
  152.         #10 i_datain <= {`AND, `gr3, 1'b0,`gr1, 1'b0,`gr2 };  
  153.         #10 i_datain <= {`OR, `gr3,1'b0, `gr1,1'b0, `gr2 };  
  154.         #10 i_datain <= {`XOR, `gr3, 1'b0,`gr1, 1'b0,`gr2 };  
  155.         #10 i_datain <= {`HALT, 11'b000_0000_0000};  
  156.         #10 i_datain <= {`BZ, `gr3, 4'b0000, 4'b0001 };  
  157.         #10 i_datain <= {`ADDI, `gr1, 4'b1111, 4'b1111 };  
  158.         #10 i_datain <= {`AND, `gr3, 1'b0,`gr1, 1'b0,`gr2 };  
  159.         #10 i_datain <= {`OR, `gr3,1'b0, `gr1,1'b0, `gr2 };  
  160.         #10 i_datain <= {`XOR, `gr3, 1'b0,`gr1, 1'b0,`gr2 };  
  161.         #10 i_datain <= {`HALT, 11'b000_0000_0000};  
  162.     end  
  163.         
  164.     always #5 clock = ~clock;  
  165.         
  166. endmodule  

综合结果:



仿真结果:

0 0
原创粉丝点击