五段式流水线_cpu流水线工作原理

五段式流水线_cpu流水线工作原理一.实验目的:1.使用verilog语言写一个CPU。包含老师给的指令,并且在此基础上加入自己的想法。把之前学过的知识都用上,尽量学会design一个东西,而不仅仅是把老师的代码修改。学习写cpu,为之后的提升打基础,比如学习编译原理的时候可以试着自己做一个编译器;学习操作系统的时候可以在cpu的基础上写一个操作系统;学习嵌入式电路的时候可以自己写一些驱动。所以学习写cpu只是打开了一扇窗,把

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

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

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

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

• 实验步骤

1.先写好CPU的指令集。

 五段式流水线_cpu流水线工作原理

     五段式流水线_cpu流水线工作原理

         五段式流水线_cpu流水线工作原理 

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

      五段式流水线_cpu流水线工作原理

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

五段式流水线_cpu流水线工作原理

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 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

综合结果:

五段式流水线_cpu流水线工作原理

仿真结果:

五段式流水线_cpu流水线工作原理

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/170397.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 银行家算法C++实现

    银行家算法C++实现网上有很多银行家算法的源代码,下面是本人自己写的,基本算法模型参考教材。介绍银行家算法(Banker’sAlgorithm)是一个避免死锁(Deadlock)的著名算法,是由艾兹格·迪杰斯特拉(EdsgerWybeDijkstra)在1965年为T.H.E系统设计的一种避免死锁产生的算法。它以银行借贷系统的分配策略为基础,判断并保证系统的安全运行。背景简介在银行中…

  • 区块链名词解释_区块链公司起什么名字好

    区块链名词解释_区块链公司起什么名字好区块链名词解释

  • [Python人工智能] 九.gensim词向量Word2Vec安装及《庆余年》中文短文本相似度计算

    [Python人工智能] 九.gensim词向量Word2Vec安装及《庆余年》中文短文本相似度计算从本专栏开始,作者正式开始研究Python深度学习、神经网络及人工智能相关知识。前一篇详细讲解了卷积神经网络CNN原理,并通过TensorFlow编写CNN实现了MNIST分类学习案例。本篇文章将分享gensim词向量Word2Vec安装、基础用法,并实现《庆余年》中文短文本相似度计算及多个案例。本专栏主要结合作者之前的博客、AI经验和相关文章及论文介绍,后面随着深入会讲解更多的Python人工智能案例及应用。基础性文章,希望对您有所帮助~

  • dos2unix命令将dos文件转换为unix格式

    dos2unix命令将dos文件转换为unix格式使用git的时候碰到git将unix换行符转换为windows换行符的问题,需要使用dos2unix命令将文件转换为unix格式。dos2unix命令用来将DOS格式的文本文件转换成UNIX格式的(DOS/MACtoUNIXtextfileformatconverter)。DOS下的文本文件是以\r\n作为断行标志的,表示成十六进制就是0D0A。而Unix下的文本文件是以\n作为断行

  • js原生判断是否是数字类型[通俗易懂]

    js原生判断是否是数字类型[通俗易懂]js判断数字类型汇总最近在写代码的时候,有些逻辑需要判断数字类型,等用到的时候才发现自己了解的方法不太严密,然后就决心查资料汇总了解下有哪些方法比较严密第一种:typeof+isNaN使用typeof可以判断是否是一个数字类型,但是NaN也是数字类型,为了筛除这个可能,进一步通过isNaN来筛除。这种方法会遗漏InfinityfunctionisNumber(num){ retu…

  • vscode设置快捷键删除行

    vscode设置快捷键删除行开发中习惯的快捷键删除:ctrl+Dvscode的删除快捷键:ctrl+shift+K修改方式:默认ctrl+D被addselectiontonextfindmatch使用, 先修改调它的快捷键,如图改为ctrl+shift+alt+D,按回车键保存 在修改DeleteLine的快捷键为ctrl+D,按回车键保存 完成…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号