这个流水线应该是我大二上的时候的最高水平了,现在看起来确实很简单,代码风格也不是很好,没有模块化,而且这些指令也不是严格的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为负数、B为0或正数:A[15]&&(~B[15])
若A、B符号相同,A-B为负:(A[15]~^B[15]) && sum[15]
则SLTResult=(A[15]&&(~B[15])) ||( (A[15]~^B[15]) && sum[15])
②在无符号数比较SLT运算中,判断A<B的方法为:
若A最高位为0、B最高位为1:(~A[15] )&&B[15]
若A、B最高位相同,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进行算术右移操作。
逻辑运算:
与、或、或非、异或、逻辑移位等运算较为简单,只是要注意一点,AND、XOR、OR三条指令的立即数为16位无符号数,应“0扩展”为32位无符号数,在运算的同时完成“0扩展”。
CPU的verilog代码:
- `timescale 1ns / 1ps
- // state macro define
- `define idle 1'b0
- `define exec 1'b1
- // instruction macro define
- `define NOP 5'b00000
- `define HALT 5'b00001
- `define LOAD 5'b00010
- `define STORE 5'b00011
- `define SLL 5'b00100
- `define SLA 5'b00101
- `define SRL 5'b00110
- `define SRA 5'b00111
- `define ADD 5'b01000
- `define ADDI 5'b01001
- `define SUB 5'b01010
- `define SUBI 5'b01011
- `define CMP 5'b01100
- `define AND 5'b01101
- `define OR 5'b01110
- `define XOR 5'b01111
- `define LDIH 5'b10000
- `define ADDC 5'b10001
- `define SUBC 5'b10010
- `define JUMP 5'b11000
- `define JMPR 5'b11001
- `define BZ 5'b11010
- `define BNZ 5'b11011
- `define BN 5'b11100
- `define BNN 5'b11101
- `define BC 5'b11110
- `define BNC 5'b11111
- // general register
- `define gr0 3'b000
- `define gr1 3'b001
- `define gr2 3'b010
- `define gr3 3'b011
- `define gr4 3'b100
- `define gr5 3'b101
- `define gr6 3'b110
- `define gr7 3'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 file
- reg state,next_state; //to control the CPU
- assign i_addr = pc;
- //************* CPU control *************//
- always @(posedge clock)
- begin
- if (!reset)
- state <= `idle;
- else
- state <= next_state;
- end
- always@(*)
- begin
- case (state)
- `idle :
- if ((enable == 1'b1) && (start == 1'b1))
- next_state <= `exec;
- else
- next_state <= `idle;
- `exec :
- if ((enable == 1'b0) || (wb_ir[15:11] == `HALT))
- next_state <= `idle;
- else
- next_state <= `exec;
- endcase
- end
- //_______________________________________________
- reg [15:0]id_ir;
- reg [7:0]pc;
- //************* IF *************//
- always@(posedge clock or negedge reset)
- begin
- if (!reset)
- begin
- id_ir <= 16'b0000_0000_0000_0000;
- pc <= 8'b0000_0000;
- end
- else if (state ==`exec)
- begin
- if(((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)
- begin
- pc <= ALUo[7:0];
- id_ir <= i_datain;
- end
- else if(id_ir[15:11] == `JUMP)//如果判断出指令是JUMP,直接跳转,就可以减少功耗,不必冒险
- begin
- pc <= 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))
- begin
- if((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)))
- begin
- pc <= pc;
- id_ir <= 16'bx;
- end
- 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)
- ||(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)
- ))
- begin
- pc <= pc;
- id_ir <= 16'bx;
- end
- 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)
- ||(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)))
- begin
- pc <= pc;
- id_ir <= 16'bx;
- end
- end
- else
- begin
- pc <= pc + 1;
- id_ir <= i_datain;
- end
- end
- else 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)
- begin
- ex_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)
- begin
- ex_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]];
- begin
- if(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];
- end
- end
- 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)
- ||(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,SRA
- begin //处理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,CMP
- begin //处理ADD等hazard
- 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指令是所需的内容还没有出来存
- 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))
- //----------------------------------------------------------------------
- begin
- if(mem_ir==`LOAD)
- smdr <= d_datain;
- else
- smdr <= 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
- end
- end
- //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;
- else
- nf <= 1'b0;
- end
- else
- begin
- zf <= zf;
- nf <= nf;
- end
- if (ex_ir[15:11] == `STORE) //如果指令是STORE的话,那么数据内存的写入使能赋为1,否则为0
- dw <= 1'b1;
- else
- dw <= 1'b0;
- end
- end
- //--------------------------------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; //jmpr
- default:
- begin
- ALUo <= ALUo;
- cf <= cf;
- end
- endcase
- reg [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;
- end
- end
- //*********************************** 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;
- end
- else 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;
- else
- gr[wb_ir[10:8]] <= gr[wb_ir[10:8]];
- end
- else;
- 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 idle 1'b0
- `define exec 1'b1
- // instruction macro define
- `define NOP 5'b00000
- `define HALT 5'b00001
- `define LOAD 5'b00010
- `define STORE 5'b00011
- `define SLL 5'b00100
- `define SLA 5'b00101
- `define SRL 5'b00110
- `define SRA 5'b00111
- `define ADD 5'b01000
- `define ADDI 5'b01001
- `define SUB 5'b01010
- `define SUBI 5'b01011
- `define CMP 5'b01100
- `define AND 5'b01101
- `define OR 5'b01110
- `define XOR 5'b01111
- `define LDIH 5'b10000
- `define ADDC 5'b10001
- `define SUBC 5'b10010
- `define JUMP 5'b11000
- `define JMPR 5'b11001
- `define BZ 5'b11010
- `define BNZ 5'b11011
- `define BN 5'b11100
- `define BNN 5'b11101
- `define BC 5'b11110
- `define BNC 5'b11111
- // general register
- `define gr0 3'b000
- `define gr1 3'b001
- `define gr2 3'b010
- `define gr3 3'b011
- `define gr4 3'b100
- `define gr5 3'b101
- `define gr6 3'b110
- `define gr7 3'b111
- module stimulus2;
- // Inputs
- reg reset;
- reg enable;
- reg start;
- reg clock;
- reg [15:0] i_datain;
- reg [15:0] d_datain;
- // Outputs
- wire 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 Inputs
- clock = 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
综合结果:
仿真结果: