verilog——简单cpu

一、简单Cpu的程序
1.顶层设计


module top(input clock,input reset,output sum,output [15:0]instruction,output [3:0]u,output [3:0]s);//顶层程序,将后面每一个模块进行连线
wire  [15:0]instruction;
wire [3:0]sum;

wire a;
wire[7:0]c;
wire d,e,f;
wire [3:0]g;
wire h;
wire [3:0]i;
wire j;
wire [3:0]k;
wire l,o;
wire [2:0]m;
wire [3:0]q;
wire [3:0]r;
wire [3:0]t;
wire w;
 
 control U1(.clock(clock),.reset(reset),.D_addr(c),.D_rd(d),.D_wr(e),.RF_s(f),.RF_W_addr(g),.RF_W_wr(h),.RF_Rp_addr(i),. RF_Rp_rd(j),
.RF_Rq_addr(k),
.RF_Rq_rd(l),
.alu_s0(m),.pc_en(o),
.instruction(instruction),.alu_en(w));
 
 choose U2(.RF_s(f),.sum(sum),.R_data(q), .W_data(r) );
 
 ALU U3(.A(s),.B(t),.alu_s0(m),.sum(sum), .alu_en(w) );
 
 pc U4(.clock(clock),.reset(reset),.en(o),.pc(u),.ins_en(a));
 
 memory U5(.clock(clock),.reset(reset),.addr(c),.wr(e),.rd(d),.wdata(s),.rdata(q));
 
 rf U6(.clock(clock),.reset(reset),.W_addr(g),.W_wr(h),.Rp_addr(i),.Rp_rd(j),.Rq_addr(k),
.Rq_rd (l),.Rp_data(s),.Rq_data(t),.W_data(r));
 
 instmemory U7(.clock(clock),.reset(reset),.addr(u),.data(instruction),.en(a));
 
endmodule

2.控制单元

module control(clock,reset,D_addr,D_rd,D_wr,RF_s,RF_W_addr,RF_W_wr,RF_Rp_addr, RF_Rp_rd,RF_Rq_addr,RF_Rq_rd,alu_s0,instruction,pc_en,alu_en);//控制单元
    input clock;//输入时序
    input reset;//重置
input [15:0]instruction;//输入从PC取出的代码
 output reg pc_en;//输出使得下一次的PC 使能
    reg [3:0]opcode;
    reg[3:0]ra;
     reg[3:0]rb;
    reg[3:0]rc;
    reg[7:0]d;

    output reg [7:0]D_addr;
    output reg D_rd;
    output reg D_wr;
    output reg RF_s;
    output reg [3:0]RF_W_addr;
    output reg RF_W_wr;
    output reg [3:0]RF_Rp_addr;
    output reg RF_Rp_rd;
    output reg [3:0]RF_Rq_addr;
    output reg RF_Rq_rd;
    output reg[2:0] alu_s0;
    output reg alu_en;
     always@(clock)
     begin//译指过程
    opcode[3:0]<=instruction[15:12];//opcode决定做什么运算
    ra[3:0]<=instruction[11:8];
    rb[3:0]<=instruction[7:4];
    rc[3:0]<=instruction[3:0];
    d[7:0]<=instruction[7:0];
    end
    
    always@(posedge clock or posedge reset)
    begin
     if(reset)//如果重置
    begin
    opcode[3:0]<=4'b0000;//使得opcode置于一个稳定的数
    alu_en=0;//alu模块使能置零
    end
    else if(clock)//如果时钟为1
  begin
    if(opcode[3:0]==4'b0000)//如果opcode=4’0000,开始load
     begin
     D_addr[7:0]=d[7:0];
     D_rd=1;
     RF_s=1;
     RF_W_addr[3:0]=ra[3:0];
     RF_W_wr=1;
     alu_en=0;
     end
    else if(opcode[3:0]==4'b0001)如果opcode=4’b0001开始store
    begin
    D_addr[7:0]=d[7:0];
    D_wr=1;
    RF_s=0;
    RF_Rp_addr[3:0]=ra[3:0];
    RF_Rp_rd=1;
     alu_en=0;
    end
    else if(opcode[3:0]==4'b0010)如果opcode=4’b0010,开始运算,此时运算的是alu中alu_s0=3’b000的操作
    begin
     RF_Rp_addr[3:0]=rb[3:0];
    RF_Rp_rd=1;
    RF_s=0;
     RF_Rq_addr[3:0]=rc[3:0];
    RF_Rq_rd=1;
    RF_W_addr[3:0]=ra[3:0];
    RF_W_wr=1;
    alu_s0=3'b000;
     alu_en=1;
    end
    else if(opcode[3:0]==4'b0011)
    begin
     RF_Rp_addr[3:0]=rb[3:0];
    RF_Rp_rd=1;
    RF_s=0;
     RF_Rq_addr[3:0]=rc[3:0];
    RF_Rq_rd=1;
    RF_W_addr[3:0]=ra[3:0];
    RF_W_wr=1;
    alu_s0=3'b001;
     alu_en=1;
    end
    else if(opcode[3:0]==4'b0100)
    begin
     RF_Rp_addr[3:0]=rb[3:0];
    RF_Rp_rd=1;
    RF_s=0;
     RF_Rq_addr[3:0]=rc[3:0];
    RF_Rq_rd=1;
    RF_W_addr[3:0]=ra[3:0];
    RF_W_wr=1;
    alu_s0=3'b010;
     alu_en=1;
    end
    else if(opcode[3:0]==4'b0101)
    begin
     RF_Rp_addr[3:0]=rb[3:0];
    RF_Rp_rd=1;
    RF_s=0;
     RF_Rq_addr[3:0]=rc[3:0];
    RF_Rq_rd=1;
    RF_W_addr[3:0]=ra[3:0];
    RF_W_wr=1;
    alu_s0=3'b011;
     alu_en=1;
    end
    else if(opcode[3:0]==4'b0110)
    begin
     RF_Rp_addr[3:0]=rb[3:0];
    RF_Rp_rd=1;
    RF_s=0;
     RF_Rq_addr[3:0]=rc[3:0];
    RF_Rq_rd=1;
    RF_W_addr[3:0]=ra[3:0];
    RF_W_wr=1;
    alu_s0=3'b100;
     alu_en=1;
    end
    else if(opcode[3:0]==4'b0111)
    begin
     RF_Rp_addr[3:0]=rb[3:0];
    RF_Rp_rd=1;
    RF_s=0;
     RF_Rq_addr[3:0]=rc[3:0];
    RF_Rq_rd=1;
    RF_W_addr[3:0]=ra[3:0];
    RF_W_wr=1;
    alu_s0=3'b101;
     alu_en=1;
    end
    else if(opcode[3:0]==4'b1000)
    begin
     RF_Rp_addr[3:0]=rb[3:0];
    RF_Rp_rd=1;
    RF_s=0;
     RF_Rq_addr[3:0]=rc[3:0];
    RF_Rq_rd=1;
    RF_W_addr[3:0]=ra[3:0];
    RF_W_wr=1;
    alu_s0=3'b110;
     alu_en=1;
     
    end
    else if(opcode==4'b1001)
    begin
     RF_Rp_addr[3:0]=rb[3:0];
    RF_Rp_rd=1;
    RF_s=0;
     RF_Rq_addr[3:0]=rc[3:0];
    RF_Rq_rd=1;
    RF_W_addr[3:0]=ra[3:0];
    RF_W_wr=1;
    alu_s0=3'b111;
     alu_en=1;
    end
   pc_en=1;
    end
end 

endmodule

3.ALU运算单元

module ALU(A,B,alu_s0,sum,alu_en);//ALU模块
input [2:0]alu_s0;//定义oper有三个数,相当于输入三个数
input [3:0]A;
input [3:0]B;
input alu_en;
 reg [3:0]ia;
  reg [3:0]ib;
  reg [3:0]cin;
output  reg [3:0]sum;
   always@(alu_s0  )//当oper变化,开始赋值
   if(alu_en==1)
   begin
case(alu_s0)//逻辑扩展器部分
    3'b000:{ia,ib,cin}<={A,B,4'b0};
    3'b001:{ia,ib,cin}<={A,~B,4'b1};
    3'b010:{ia,ib,cin}<={A,4'b0,4'b1};
    3'b011:{ia,ib,cin}<={A,4'b0,4'b0};
    3'b100:{ia,ib,cin}<={A&B,4'b0,4'b0};
    3'b101:{ia,ib,cin}<={A|B,4'b0,4'b0};
    3'b110:{ia,ib,cin}<={(~A&B)|(A&~B),4'b0,4'b0};
    3'b111:{ia,ib,cin}<={~A,4'b0,4'b0};
endcase
end
always@(*)
begin
    sum=ia+ib+cin;//用加法器实现的内容
   end

endmodule

4.选择器部分

module choose(RF_s,sum,R_data, W_data

    );//选择器
    input RF_s;
    input [3:0]sum;
     input [3:0]R_data;
    output reg [3:0]W_data;
    always@(*)
    begin
    if(RF_s==0)
    W_data=sum;
    else
    W_data=R_data;
    end
endmodule

5.PC指针

module pc(clock,reset,en,pc,ins_en);指针
input clock,reset,en;
output reg [3:0] pc;
output reg ins_en;
reg [3:0]pc_next;
always@(posedge clock or posedge reset)
begin
if(reset)
pc<=0;
else
if(en)
pc<=pc_next;
else
pc<=pc;
end
always@(posedge clock or posedge reset)
begin
if(reset)
pc_next<=0;
else if(en)
pc_next<=pc+1;
else
pc_next<=pc_next;
end
always@(*)
begin
 pc_next=pc+1;
 ins_en=1;
 end
endmodule

6.数据寄存器

module memory(clock,reset,addr,wr,rd,wdata,rdata);数据存储器
input[7:0] addr;
input [3:0]wdata;
output reg[3:0]rdata;
input rd,wr;
input clock,reset;
reg[7:0]mem[0:31];
always@(posedge clock or posedge reset)
  if(reset)
  begin
  mem[0]<='b0001;
  mem[1]<='b0000;
  mem[2]<='b0011;
  mem[3]<='b0001;
  mem[4]<='b1001;
  mem[5]<='b0010;
  mem[6]<='b0000;
  mem[7]<='b0100;
  mem[8]<='b0011;
  mem[9]<='b1000;
  mem[10]<='b1001;
  mem[11]<='b1101;
  mem[12]<='b0101;
  end
  else
  if(wr==1)
  mem[addr]<=wdata;
 else if(rd==1)
  rdata<=mem[addr];
  endmodule

7.寄存器

module rf(clock,reset,W_addr,W_wr,Rp_addr,Rp_rd,Rq_addr,
Rq_rd,Rp_data,Rq_data,W_data);//寄存器
input [3:0]W_data;
input clock,reset;
input [3:0] W_addr;
input W_wr;
input [3:0] Rp_addr;
input  Rp_rd;
input [3:0] Rq_addr;
input Rq_rd;
 output reg [3:0]Rp_data;
 output reg [3:0] Rq_data;
 reg[7:0]RF[4'b0000:4'b1111];
 always@(posedge clock or posedge reset)
  if(reset)
  begin
 RF[0000]<='b0000;
  RF[0001]<='b0000;
  RF[0002]<='b0000;
  RF[0003]<='b0010;
  RF[0004]<='b0010;
  RF[0005]<='b0001;
  RF[0006]<='b0000;
  RF[0007]<='b0110;
  RF[0008]<='b0010;
  RF[0009]<='b1010;
  end
 else if(clock)
 begin
 if(Rp_rd==1)
Rp_data[3:0]=RF[Rp_addr][3:0];
if(Rq_rd==1)
Rq_data[3:0]=RF[Rq_addr][3:0];
if(W_wr==1)
RF[W_addr][3:0]=W_data[3:0];

end
endmodule

8.指令寄存器


module instmemory(clock,reset,addr,data,en);指令寄存器
input[3:0] addr;
output reg [15:0]data;
input clock,reset,en;
reg[15:0]me[0:16];
always@(posedge clock or posedge reset)
  if(reset)
  begin
  me[0000]<='b0000000000000101;
  me[0001]<='b0000000100000110;
  me[0002]<='b0010001000000001;
  me[0003]<='b0001001000001001;
  me[0004]<='b0010001000000001;
  me[0005]<='b0011001000000001;
  me[0006]<='b0100001000000001;
  me[0007]<='b0101001000000001;
  me[0008]<='b0111001000000001;
  me[0009]<='b1000001000000001;
   me[0010]<='b1001001000000001;
    me[0011]<='b1010001000000001;
    me[0012]<='b1011001000000001;
  end
else if(en)
 data[15:0]=me[addr];
 endmodule

2.仿真——testbench文件

module cpup_test;

reg clock;
reg reset;
wire [3:0]sum;
wire [15:0]instruction;
wire [3:0]u;
 wire [3:0]s;
top unit(.clock(clock),.reset(reset),.instruction(instruction),.sum(sum),.u(u),.s(s));


initial
begin
clock=1'b0;
reset=1'b1;
#10
reset=1'b0;
#500
reset=1'b1;
end
always
begin
#10 clock=~clock;
End

二、仿真结果
仿真结果

图中sum是指到alu的两个数运算之后的值,instruction是指从存储器里面取出来的指令(提前在指令寄存器里面设置好指令的顺序,u是指pc指针此时的位置,用这几个数来检测cpu内部的运行。可以看出,pc一直在增加,instruction随着pc的变化在指令寄存器模块中将指令所对应的值取出,是正确的。译码之后通过译码的值判断A、B以及做什么运算。在这个过程中从数据寄存器中取出所对应的值(提前在数据寄存器设置好的)进行运算。
三、设计思路
先将CPU的原理进行分析,cpu的指令存储在指令存储器之中,先用pc从指令存储器中取出指令,然后将取出的指令进行解码,再根据解码的内容进行相应的运算。在之前学过的三指令处理器有着很大的启示。于是将cpu分为7部分,分解逐一解决。第一部分pc,用于取指的指针变换,第二部分,control,用于译指,然后控制后面的数据路径。第三部分,alu,运算部分,这部分之前写过,所以直接用即可。第四部分,寄存器部分。第五部分,选择器部分,第六部分,存储器部分,第七部分,pc,指针变换部分。然后逐一进行每一个模块的设计。

在三指令处理器中将ALU的输入s0扩展为三位,即可将之前的可进行八种运算的ALU引用,而与此同时,ALU的功能也相较之前有所增加。

在这里插入图片描述

如图,便是最终的电路图,输入时钟与重置,输出的是为了检测cpu的运行是否正确。
1.pc
在这里插入图片描述

输入时钟和重置,以及时钟使能,然后输出指令存储器的使能,以及此时的pc。
内部设置一个pc_next,用来存储pc的下一个值。在每一次pc取值之后,将pc_next的值赋给pc。
2.control
在这里插入图片描述

这是cpu的控制单元,用来控制取指,alu的使能,并在内部实现译码。
四、感悟
在cpu的练习中,领悟了什么是顶层文件,怎么设计顶层文件,将一个个模块连立起来。更加深刻理解了CPU的内部构造。了解了部分存储器的设计,并在cpu的设计中进行简单的应用。除此之外,搞懂了verilog中运行时错误是什么问题。

  • 10
    点赞
  • 112
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值