Verilog硬件描述语言cpu设计实例
verilog hdl语言100例详解

verilog hdl语言100例详解Verilog HDL语言是一种硬件描述语言,用于描述数字电路和系统的行为和结构。
它是硬件设计工程师在数字电路设计中的重要工具。
本文将介绍100个例子,详细解释Verilog HDL语言的应用。
1. 基本门电路:Verilog HDL可以用于描述基本门电路,如与门、或门、非门等。
例如,下面是一个描述与门电路的Verilog HDL代码:```verilogmodule and_gate(input a, input b, output y);assign y = a & b;endmodule```2. 多路选择器:Verilog HDL也可以用于描述多路选择器。
例如,下面是一个描述2:1多路选择器的Verilog HDL代码:```verilogmodule mux_2to1(input a, input b, input sel, output y);assign y = sel ? b : a;endmodule```3. 寄存器:Verilog HDL可以用于描述寄存器。
例如,下面是一个描述8位寄存器的Verilog HDL代码:```verilogmodule register_8bit(input [7:0] d, input clk, input reset, output reg [7:0] q);always @(posedge clk or posedge reset)if (reset)q <= 0;elseq <= d;endmodule```4. 计数器:Verilog HDL可以用于描述计数器。
例如,下面是一个描述8位计数器的Verilog HDL代码:```verilogmodule counter_8bit(input clk, input reset, output reg [7:0] count);always @(posedge clk or posedge reset)if (reset)count <= 0;elsecount <= count + 1;endmodule```5. 加法器:Verilog HDL可以用于描述加法器。
verilog的15个经典设计实例

begin b=a; c=b; end endmodule
【例 5.11】模为 60 的 BCD 码加法计数器
module count60(qout,cout,data,load,cin,reset,clk);
【例 5.6】用 fork-join 并行块产生信号波形
`timescale 10ns/1ns module wave2; reg wave; parameter cycle=5; initial
fork wave=0;
#(cycle) wave=1; #(2*cycle) wave=0; #(3*cycle) wave=1; #(4*cycle) wave=0; #(5*cycle) wave=1; #(6*cycle) $finish; join initial $monitor($time,,,"wave=%b",wave); endmodule
else
out<=out+1;
end
endmodule
//同步复位 //计数
【例 3.3】4 位全加器的仿真程序
`timescale 1ns/1ns `include "adder4.v" module adder_tp; reg[3:0] a,b; reg cin; wire[3:0] sum; wire cout; integer i,j;
output[7:0] qout;
output cout;
input[7:0] data;
input load,cin,clk,reset;
第5章单周期CPU及其Verilog HDL设计

op 6 bits
rs 5 bits
rt 5 bits
rd 5 bits
sa 5 bits
funct 6 bits
I Format
31
(rs, rt: Register Numbers, imm: Immediate)
26 25 21 20 16 15 0
时钟上升沿(0到 1的变化) 一个周期
Clock
下降沿
指令1
指令2
指令3
指令4
在时钟上升沿保存指令的结果和下一条指令的地址
c
5.1 执行指令所需的硬件电路
• 指令的执行过程
取指令 执行指令
—读取指令
程序计数器的值作为地址从存储器中 取指令 形 成 下 一 条 指 令 地 址
—分析指令 —按指令规定内容执行指令 —检查有无中断请求
c
取指部件(Instruction Fetch Unit)
• 每条指令都有的公共操作
– 取指令: M[PC] – 更新PC:PC ← PC + 4
转移(Branch and Jump)时,PC内容再次被更新为 “转移目标地址 ” 下地址 逻辑
Next Address Logic Address Instruction Word
rs rt P C a do Inst mem
we rna
rnb qa wn Regfile d clk qb b ALU
rd
a
aluc z r
clock
c
Sll指令 (Shift Left Logical)
sll rd, rt, sa ; rd <-- rt << sa
Verilog的135个经典设计实例

Verilog的135个经典设计实例王金明:《Verilog HDL程序设计教程》【例3.1】4位全加器module adder4(cout,sum,ina,inb,cin);output[3:0] sum;output cout;input[3:0] ina,inb;input cin;assign {cout,sum}=ina+inb+cin;endmodule【例3.2】4位计数器module count4(out,reset,clk);output[3:0] out;input reset,clk;reg[3:0] out;always @(posedge clk)beginif (reset) out<=0; //同步复位else out<=out+1; //计数endendmodule【例3.3】4位全加器的仿真程序`timescale 1ns/1ns`include "adder4.v"module adder_tp; //测试模块的名字reg[3:0] a,b; //测试输入信号定义为reg型reg cin;wire[3:0] sum; //测试输出信号定义为wire型wire cout;integer i,j;adder4 adder(sum,cout,a,b,cin); //调用测试对象always #5 cin=~cin; //设定cin的取值initialbegina=0;b=0;cin=0;for(i=1;i<16;i=i+1)#10 a=i; //设定a的取值end- 1 - 程序文本initialbeginfor(j=1;j<16;j=j+1)#10 b=j; //设定b的取值endinitial //定义结果显示格式begin$monitor($time,,,"%d + %d + %b={%b,%d}",a,b,cin,cout,sum);#160 $finish;endendmodule【例3.4】4位计数器的仿真程序`timescale 1ns/1ns`include "count4.v"module coun4_tp;reg clk,reset; //测试输入信号定义为reg型wire[3:0] out; //测试输出信号定义为wire型parameter DELY=100;count4 mycount(out,reset,clk); //调用测试对象always #(DELY/2) clk = ~clk; //产生时钟波形initialbegin //激励信号定义clk =0; reset=0;#DELY reset=1;#DELY reset=0;#(DELY*20) $finish;end//定义结果显示格式initial $monitor($time,,,"clk=%d reset=%d out=%d", clk, reset,out);endmodule【例3.5】“与-或-非”门电路module AOI(A,B,C,D,F); //模块名为AOI(端口列表A,B,C,D,F)input A,B,C,D; //模块的输入端口为A,B,C,Doutput F; //模块的输出端口为F- 2 -王金明:《Verilog HDL程序设计教程》wire A,B,C,D,F; //定义信号的数据类型assign F= ~((A&B)|(C&D)); //逻辑功能描述endmodule【例5.1】用case语句描述的4选1数据选择器module mux4_1(out,in0,in1,in2,in3,sel);output out;input in0,in1,in2,in3;input[1:0] sel;reg out;always @(in0 or in1 or in2 or in3 or sel) //敏感信号列表case(sel)2'b00: out=in0;2'b01: out=in1;2'b10: out=in2;2'b11: out=in3;default: out=2'bx;endcaseendmodule【例5.2】同步置数、同步清零的计数器module count(out,data,load,reset,clk);output[7:0] out;input[7:0] data;input load,clk,reset;reg[7:0] out;always @(posedge clk) //clk上升沿触发beginif (!reset) out = 8'h00; //同步清0,低电平有效else if (load) out = data; //同步预置else out = out + 1; //计数endendmodule【例5.3】用always过程语句描述的简单算术逻辑单元`define add 3'd0`define minus 3'd1`define band 3'd2`define bor 3'd3`define bnot 3'd4- 3 - 程序文本module alu(out,opcode,a,b);output[7:0] out;reg[7:0] out;input[2:0] opcode; //操作码input[7:0] a,b; //操作数always@(opcode or a or b) //电平敏感的always块begincase(opcode)`add: out = a+b; //加操作`minus: out = a-b; //减操作`band: out = a&b; //求与`bor: out = a|b; //求或`bnot: out=~a; //求反default: out=8'hx; //未收到指令时,输出任意态endcaseendendmodule【例5.4】用initial过程语句对测试变量A、B、C赋值`timescale 1ns/1nsmodule test;reg A,B,C;initialbeginA = 0;B = 1;C = 0;#50 A = 1; B = 0;#50 A = 0; C = 1;#50 B = 1;#50 B = 0; C = 0;#50 $finish ;endendmodule【例5.5】用begin-end串行块产生信号波形`timescale 10ns/1nsmodule wave1;reg wave;parameter cycle=10;initialbegin- 4 -王金明:《Verilog HDL程序设计教程》wave=0;#(cycle/2) wave=1;#(cycle/2) wave=0;#(cycle/2) wave=1;#(cycle/2) wave=0;#(cycle/2) wave=1;#(cycle/2) $finish ;endinitial $monitor($time,,,"wave=%b",wave); endmodule【例5.6】用fork-join并行块产生信号波形`timescale 10ns/1nsmodule wave2;reg wave;parameter cycle=5;initialforkwave=0;#(cycle) wave=1;#(2*cycle) wave=0;#(3*cycle) wave=1;#(4*cycle) wave=0;#(5*cycle) wave=1;#(6*cycle) $finish;initial $monitor($time,,,"wave=%b",wave); endmodule【例5.7】持续赋值方式定义的2选1多路选择器module MUX21_1(out,a,b,sel);input a,b,sel;output out;assign out=(sel==0)?a:b;//持续赋值,如果sel为0,则out=a ;否则out=b endmodule【例5.8】阻塞赋值方式定义的2选1多路选择器module MUX21_2(out,a,b,sel);input a,b,sel;- 5 - 程序文本output out;reg out;always@(a or b or sel)beginif(sel==0) out=a; //阻塞赋值else out=b;endendmodule【例5.9】非阻塞赋值module non_block(c,b,a,clk);output c,b;input clk,a;reg c,b;always @(posedge clk)beginb<=a;endendmodule【例5.10】阻塞赋值module block(c,b,a,clk);output c,b;input clk,a;reg c,b;always @(posedge clk)beginb=a;c=b;endendmodule【例5.11】模为60的BCD码加法计数器module count60(qout,cout,data,load,cin,reset,clk); output[7:0] qout;output cout;input[7:0] data;input load,cin,clk,reset;reg[7:0] qout;always @(posedge clk) //clk上升沿时刻计数- 6 - 王金明:《Verilog HDL程序设计教程》beginif (reset) qout<=0; //同步复位else if(load) qout<=data; //同步置数else if(cin)beginif(qout[3:0]==9) //低位是否为9,是则beginqout[3:0]<=0; //回0,并判断高位是否为5if (qout[7:4]==5) qout[7:4]<=0;elseqout[7:4]<=qout[7:4]+1; //高位不为5,则加1endelse //低位不为9,则加1qout[3:0]<=qout[3:0]+1;endendassign cout=((qout==8'h59)&cin)?1:0; //产生进位输出信号endmodule【例5.12】BCD码—七段数码管显示译码器module decode4_7(decodeout,indec);output[6:0] decodeout;input[3:0] indec;reg[6:0] decodeout;always @(indec)begincase(indec) //用case语句进行译码4'd0:decodeout=7'b1111110;4'd1:decodeout=7'b0110000;4'd2:decodeout=7'b1101101;4'd3:decodeout=7'b1111001;4'd4:decodeout=7'b0110011;4'd5:decodeout=7'b1011011;4'd6:decodeout=7'b1011111;4'd7:decodeout=7'b1110000;4'd8:decodeout=7'b1111111;4'd9:decodeout=7'b1111011;default: decodeout=7'bx;endcaseend- 7 - 程序文本endmodule【例5.13】用casez描述的数据选择器module mux_casez(out,a,b,c,d,select); output out;input a,b,c,d;input[3:0] select;reg out;always @(select or a or b or c or d) begincasez(select)4'b1: out = a;4'b??1?: out = b;4'b?1??: out = c;4'b1: out = d;endcaseendendmodule【例5.14】隐含锁存器举例module buried_ff(c,b,a);output c;input b,a;reg c;always @(a or b)beginif((b==1)&&(a==1)) c=a&b;endendmodule【例5.15】用for语句描述的七人投票表决器module voter7(pass,vote);output pass;input[6:0] vote;reg[2:0] sum;integer i;reg pass;always @(vote)beginsum=0;- 8 -王金明:《Verilog HDL程序设计教程》for(i=0;i<=6;i=i+1) //for语句if(vote[i]) sum=sum+1;if(sum[2]) pass=1; //若超过4人赞成,则pass=1 else pass=0;endendmodule【例5.16】用for语句实现2个8位数相乘module mult_for(outcome,a,b);parameter size=8;input[size:1] a,b; //两个操作数output[2*size:1] outcome; //结果reg[2*size:1] outcome;integer i;always @(a or b)beginoutcome=0;for(i=1; i<=size; i=i+1) //for语句if(b[i]) outcome=outcome +(a << (i-1));endendmodule【例5.17】用repeat实现8位二进制数的乘法module mult_repeat(outcome,a,b);parameter size=8;input[size:1] a,b;output[2*size:1] outcome;reg[2*size:1] temp_a,outcome;reg[size:1] temp_b;always @(a or b)beginoutcome=0;temp_a=a;temp_b=b;repeat(size) //repeat语句,size为循环次数beginif(temp_b[1]) //如果temp_b的最低位为1,就执行下面的加法outcome=outcome+temp_a;temp_a=temp_a<<1; //操作数a左移一位- 9 - 程序文本temp_b=temp_b>>1; //操作数b右移一位endendendmodule【例5.18】同一循环的不同实现方式module loop1; //方式1integer i;initialfor(i=0;i<4;i=i+1) //for语句begin$display(“i=%h”,i);endendmodulemodule loop2; //方式2integer i;initial begini=0;while(i<4) //while语句begin$display ("i=%h",i);i=i+1;endendendmodulemodule loop3; //方式3integer i;initial begini=0;repeat(4) //repeat语句begin$display ("i=%h",i);i=i+1;endendendmodule【例5.19】使用了`include语句的16位加法器- 10 -王金明:《Verilog HDL程序设计教程》`include "adder.v" module adder16(cout,sum,a,b,cin);output cout;parameter my_size=16;output[my_size-1:0] sum;input[my_size-1:0] a,b;input cin;adder my_adder(cout,sum,a,b,cin); //调用adder模块endmodule//下面是adder模块代码module adder(cout,sum,a,b,cin);parameter size=16;output cout;output[size-1:0] sum;input cin;input[size-1:0] a,b;assign {cout,sum}=a+b+cin;endmodule【例5.20】条件编译举例module compile(out,A,B);output out;input A,B;`ifdef add //宏名为addassign out=A+B;`elseassign out=A-B;`endifendmodule【例6.1】加法计数器中的进程module count(data,clk,reset,load,cout,qout);output cout;output[3:0] qout;reg[3:0] qout;input[3:0] data;input clk,reset,load;- 11 - 程序文本always @(posedge clk) //进程1,always过程块beginif (!reset) qout= 4'h00; //同步清0,低电平有效else if (load) qout= data; //同步预置else qout=qout + 1; //加法计数endassign cout=(qout==4'hf)?1:0; //进程2,用持续赋值产生进位信号endmodule【例6.2】任务举例module alutask(code,a,b,c);input[1:0] code;input[3:0] a,b;output[4:0] c;reg[4:0] c;task my_and; //任务定义,注意无端口列表input[3:0] a,b; //a,b,out名称的作用域范围为task任务内部output[4:0] out;integer i;beginfor(i=3;i>=0;i=i-1)out[i]=a[i]&b[i]; //按位与endendtaskalways@(code or a or b)begincase(code)2'b00: my_and(a,b,c);/* 用任务my_and,需注意端口列表的顺序应与任务定义中的一致,这里的a,b,c分别对应任务定义中的a,b,out */2'b01: c=a|b; //或2'b10: c=a-b; //相减2'b11: c=a+b; //相加endcaseendendmodule- 12 -王金明:《Verilog HDL程序设计教程》【例6.3】测试程序`include "alutask.v"module alu_tp;reg[3:0] a,b;reg[1:0] code;wire[4:0] c;parameter DELY = 100;alutask ADD(code,a,b,c); //调用被测试模块initial begincode=4'd0; a= 4'b0000; b= 4'b1111;#DELY code=4'd0; a= 4'b0111; b= 4'b1101;#DELY code=4'd1; a= 4'b0001; b= 4'b0011;#DELY code=4'd2; a= 4'b1001; b= 4'b0011;#DELY code=4'd3; a= 4'b0011; b= 4'b0001;#DELY code=4'd3; a= 4'b0111; b= 4'b1001;#DELY $finish;endinitial $monitor($time,,,"code=%b a=%b b=%b c=%b", code,a,b,c);endmodule【例6.4】函数function[7:0] get0;input[7:0] x;reg[7:0] count;integer i;begincount=0;for (i=0;i<=7;i=i+1)if (x[i]=1'b0) count=count+1;get0=count;endendfunction【例6.5】用函数和case语句描述的编码器(不含优先顺序)module code_83(din,dout);input[7:0] din;output[2:0] dout;- 13 - 程序文本function[2:0] code; //函数定义input[7:0] din; //函数只有输入,输出为函数名本身casex (din)8'b1xxx_xxxx : code = 3'h7;8'b01xx_xxxx : code = 3'h6;8'b001x_xxxx : code = 3'h5;8'b0001_xxxx : code = 3'h4;8'b0000_1xxx : code = 3'h3;8'b0000_01xx : code = 3'h2;8'b0000_001x : code = 3'h1;8'b0000_000x : code = 3'h0;default: code = 3'hx;endcaseendfunctionassign dout = code(din) ; //函数调用endmodule【例6.6】阶乘运算函数module funct(clk,n,result,reset);output[31:0] result;input[3:0] n;input reset,clk;reg[31:0] result;always @(posedge clk) //在clk的上升沿时执行运算beginif(!reset) result<=0; //复位else beginresult <= 2 * factorial(n); //调用factorial函数endendfunction[31:0] factorial; //阶乘运算函数定义(注意无端口列表)input[3:0] opa; //函数只能定义输入端,输出端口为函数名本身reg[3:0] i;beginfactorial = opa ? 1 : 0;for(i= 2; i <= opa; i = i+1) //该句若要综合通过,opa应赋具体的数值factorial = i* factorial; //阶乘运算end- 14 -王金明:《Verilog HDL程序设计教程》endfunction【例6.7】测试程序`define clk_cycle 50`include "funct.v"module funct_tp;reg[3:0] n;reg reset,clk;wire[31:0] result;initial //定义激励向量beginn=0; reset=1; clk=0;for(n=0;n<=15;n=n+1)#100 n=n;endinitial $monitor($time,,,"n=%d result=%d",n,result);//定义输出显示格式always # `clk_cycle clk=~clk; //产生时钟信号funct funct_try(.clk(clk),.n(n),.result(result),.reset(reset)); //调用被测试模块endmodule【例6.8】顺序执行模块1module serial1(q,a,clk);output q,a;input clk;reg q,a;always @(posedge clk)beginq=~q;a=~q;end【例6.9】顺序执行模块2 module serial2(q,a,clk); output q,a;- 15 - 程序文本input clk;reg q,a;always @(posedge clk) begina=~q;q=~q;endendmodule【例6.10】并行执行模块1 module paral1(q,a,clk); output q,a;input clk;reg q,a;always @(posedge clk) beginq=~q;endalways @(posedge clk) begina=~q;endendmodule【例6.11】并行执行模块2 module paral2(q,a,clk); output q,a;input clk;reg q,a;always @(posedge clk)begina=~q;endalways @(posedge clk)beginq=~q;endendmodule【例7.1】调用门元件实现的4选1 MUX- 16 -王金明:《Verilog HDL程序设计教程》module mux4_1a(out,in1,in2,in3,in4,cntrl1,cntrl2);output out;input in1,in2,in3,in4,cntrl1,cntrl2;wire notcntrl1,notcntrl2,w,x,y,z;not notcntrl1,cntrl2),(notcntrl2,cntrl2);and (w,in1,notcntrl1,notcntrl2),(x,in2,notcntrl1,cntrl2),(y,in3,cntrl1,notcntrl2),(z,in4,cntrl1,cntrl2);or (out,w,x,y,z);endmodule【例7.2】用case语句描述的4选1 MUXmodule mux4_1b(out,in1,in2,in3,in4,cntrl1,cntrl2);output out;input in1,in2,in3,in4,cntrl1,cntrl2;reg out;always@(in1 or in2 or in3 or in4 or cntrl1 or cntrl2)case({cntrl1,cntrl2})2'b00:out=in1;2'b01:out=in2;2'b10:out=in3;2'b11:out=in4;default:out=2'bx;endcaseendmodule【例7.3】行为描述方式实现的4位计数器module count4(clk,clr,out);input clk,clr;output[3:0] out;reg[3:0] out;always @(posedge clk or posedge clr)beginif (clr) out<=0;else out<=out+1;endendmodule- 17 - 程序文本【例7.4】数据流方式描述的4选1 MUXmodule mux4_1c(out,in1,in2,in3,in4,cntrl1,cntrl2);output out;input in1,in2,in3,in4,cntrl1,cntrl2;assign out=(in1 & ~cntrl1 & ~cntrl2)|(in2 & ~cntrl1 & cntrl2)|(in3 & cntrl1 & ~cntrl2)|(in4 & cntrl1 & cntrl2);endmodule【例7.5】用条件运算符描述的4选1 MUXmodule mux4_1d(out,in1,in2,in3,in4,cntrl1,cntrl2); output out;input in1,in2,in3,in4,cntrl1,cntrl2;assign out=cntrl1 ? (cntrl2 ? in4:in3):(cntrl2 ? in2:in1); endmodule【例7.6】门级结构描述的2选1MUXmodule mux2_1a(out,a,b,sel);output out;input a,b,sel;not (sel_,sel);and a1,a,sel_),(a2,b,sel);or (out,a1,a2);endmodule【例7.7】行为描述的2选1MUXmodule mux2_1b(out,a,b,sel);output out;input a,b,sel;reg out;always @(a or b or sel)beginif(sel) out = b;else out = a;endendmodule【例7.8】数据流描述的2选1MUXmodule MUX2_1c(out,a,b,sel);output out;- 18 -王金明:《Verilog HDL程序设计教程》input a,b,sel;assign out = sel ? b : a; endmodule【例7.9】调用门元件实现的1位半加器module half_add1(a,b,sum,cout); input a,b;output sum,cout;and cout,a,b);xor sum,a,b);endmodule【例7.10】数据流方式描述的1位半加器module half_add2(a,b,sum,cout); input a,b;output sum,cout;assign sum=a^b;assign cout=a&b;endmodule【例7.11】采用行为描述的1位半加器module half_add3(a,b,sum,cout); input a,b;output sum,cout;reg sum,cout;always @(a or b)begincase ({a,b}) //真值表描述2'b00: begin sum=0; cout=0; end2'b01: begin sum=1; cout=0; end2'b10: begin sum=1; cout=0; end2'b11: begin sum=0; cout=1; end endcaseendendmodule【例7.12】采用行为描述的1位半加器module half_add4(a,b,sum,cout); input a,b;output sum,cout;- 19 - 程序文本reg sum,cout;always @(a or b)beginsum= a^b;cout=a&b;endendmodule【例7.13】调用门元件实现的1位全加器module full_add1(a,b,cin,sum,cout); input a,b,cin;output sum,cout;wire s1,m1,m2,m3;and m1,a,b),(m2,b,cin),(m3,a,cin);xor s1,a,b),(sum,s1,cin);or (cout,m1,m2,m3);endmodule【例7.14】数据流描述的1位全加器module full_add2(a,b,cin,sum,cout); input a,b,cin;output sum,cout;assign sum = a ^ b ^ cin;assign cout = (a & b)|(b & cin)|(cin & a);endmodule【例7.15】1位全加器module full_add3(a,b,cin,sum,cout);input a,b,cin;output sum,cout;assign {cout,sum}=a+b+cin;endmodule【例7.16】行为描述的1位全加器module full_add4(a,b,cin,sum,cout);input a,b,cin;output sum,cout;- 20 -王金明:《Verilog HDL程序设计教程》reg sum,cout; //在always块中被赋值的变量应定义为reg型reg m1,m2,m3;always @(a or b or cin)beginsum = (a ^ b) ^ cin;m1 = a & b;m2 = b & cin;m3 = a & cin;cout = (m1|m2)|m3;endendmodule【例7.17】混合描述的1位全加器module full_add5(a,b,cin,sum,cout);input a,b,cin;output sum,cout;reg cout,m1,m2,m3; //在always块中被赋值的变量应定义为reg型wire s1;xor x1(s1,a,b); //调用门元件always @(a or b or cin) //always块语句beginm1 = a & b;m2 = b & cin;m3 = a & cin;cout = (m1| m2) | m3;endassign sum = s1 ^ cin; //assign持续赋值语句endmodule【例7.18】结构描述的4位级连全加器`include "full_add1.v"module add4_1(sum,cout,a,b,cin);output[3:0] sum;output cout;input[3:0] a,b;input cin;full_add1 f0(a[0],b[0],cin,sum[0],cin1); //级连描述full_add1 f1(a[1],b[1],cin1,sum[1],cin2);full_add1 f2(a[2],b[2],cin2,sum[2],cin3);- 21 - 程序文本full_add1 f3(a[3],b[3],cin3,sum[3],cout); endmodule【例7.19】数据流描述的4位全加器module add4_2(cout,sum,a,b,cin);output[3:0] sum;output cout;input[3:0] a,b;input cin;assign {cout,sum}=a+b+cin;endmodule【例7.20】行为描述的4位全加器module add4_3(cout,sum,a,b,cin);output[3:0] sum;output cout;input[3:0] a,b;input cin;reg[3:0] sum;reg cout;always @(a or b or cin)begin{cout,sum}=a+b+cin;endendmodule【例8.1】$time与$realtime的区别`timescale 10ns/1nsmodule time_dif;reg ts;parameter delay=2.6;initialbegin#delay ts=1;#delay ts=0;#delay ts=1;#delay ts=0;endinitial $monitor($time,,,"ts=%b",ts); //使用函数$time- 22 - 王金明:《Verilog HDL程序设计教程》endmodule【例8.2】$random函数的使用`timescale 10ns/1nsmodule random_tp;integer data;integer i;parameter delay=10;initial $monitor($time,,,"data=%b",data);initial beginfor(i=0; i<=100; i=i+1)#delay data=$random; //每次产生一个随机数endendmodule【例8.3】1位全加器进位输出UDP元件primitive carry_udp(cout,cin,a,b);input cin,a,b;output cout;table//cin a b : cout //真值表0 0 0 : 0;0 1 0 : 0;0 0 1 : 0;0 1 1 : 1;1 0 0 : 0;1 0 1 : 1;1 1 0 : 1;1 1 1 : 1;endtableendprimitive【例8.4】包含x态输入的1位全加器进位输出UDP元件primitive carry_udpx1(cout,cin,a,b);input cin,a,b;output cout;table// cin a b : cout //真值表0 0 0 : 0;- 23 - 程序文本0 1 0 : 0;0 0 1 : 0;0 1 1 : 1;1 0 0 : 0;1 0 1 : 1;1 1 0 : 1;1 1 1 : 1;0 0 x : 0; //只要有两个输入为0,则进位输出肯定为0 0 x 0 : 0;x 0 0 : 0;1 1 x : 1; //只要有两个输入为1,则进位输出肯定为1 1 x 1 : 1;x 1 1 : 1;endtableendprimitive【例8.5】用简缩符“?”表述的1位全加器进位输出UDP元件primitive carry_udpx2(cout,cin,a,b);input cin,a,b;output cout;table// cin a b : cout //真值表0 0 : 0; //只要有两个输入为0,则进位输出肯定为00 ? 0 : 0;0 0 ? : 0;1 1 : 1; //只要有两个输入为1,则进位输出肯定为11 ? 1 : 1;1 1 ? : 1;endtableendprimitive【例8.6】3选1多路选择器UDP元件primitive mux31(Y,in0,in1,in2,s2,s1);input in0,in1,in2,s2,s1;output Y;table//in0 in1 in2 s2 s1 : Y0 ? ? 0 0 : 0; //当s2s1=00时,Y=in01 ? ? 0 0 : 1;0 ? 0 1 : 0; //当s2s1=01时,Y=in1 - 24 -王金明:《Verilog HDL程序设计教程》1 ? 0 1 : 1;0 1 ? : 0; //当s2s1=1?时,Y=in21 1 ? : 1;0 0 ? 0 ? : 0;1 1 ? 0 ? : 1;0 ? 0 ? 0 : 0;1 ? 1 ? 0 : 1;0 0 ? 1 : 0;1 1 ? 1 : 1;endtableendprimitive【例8.7】电平敏感的1位数据锁存器UDP元件primitive latch(Q,clk,reset,D);input clk,reset,D;output Q;reg Q;initial Q = 1'b1; //初始化table// clk reset D : state : Q1 ? : ? : 0 ; //reset=1,则不管其他端口为什么值,输出都为00 0 0 : ? : 0 ; //clk=0,锁存器把D端的输入值输出0 0 1 : ? : 1 ;1 0 ? : ? : - ; //clk=1,锁存器的输出保持原值,用符号“-”表示endtableendprimitive【例8.8】上升沿触发的D触发器UDP元件primitive DFF(Q,D,clk);output Q;input D,clk;reg Q;table//clk D : state : Q(01) 0 : ? : 0; //上升沿到来,输出Q=D(01) 1 : ? : 1;(0x) 1 : 1 : 1;(0x) 0 : 0 : 0;(?0) ? : ? : -; //没有上升沿到来,输出Q保持原值(??) : ? : - ; //时钟不变,输出也不变- 25 - 程序文本endtableendprimitive【例8.9】带异步置1和异步清零的上升沿触发的D触发器UDP 元件primitive DFF_UDP(Q,D,clk,clr,set);output Q;input D,clk,clr,set;reg Q;table// clk D clr et state : Q (01) 1 0 0 : ? : 0; (01) 1 0 x : ? : 0;0 x : 0 : 0;(01) 0 0 0 : ? : 1; (01) 0 x 0 : ? : 1;x 0 : 1 : 1;(x1) 1 0 0 : 0 : 0;(x1) 0 0 0 : 1 : 1;(0x) 1 0 0 : 0 : 0;(0x) 0 0 0 : 1 : 1;1 ? : ? : 1; //异步复位0 1 : ? : 0; //异步置1 n ? 0 0 : ? : -;* ? ? : ? : -;(?0) ? : ? : -;(?0): ? : -;: ? : x;endtableendprimitive【例8.12】延迟定义块举例module delay(out,a,b,c); output out;input a,b,c;and a1(n1,a,b);or o1(out,c,n1);specify(a=>out)=2;(b=>out)=3;(c=>out)=1;- 26 -王金明:《Verilog HDL程序设计教程》endspecifyendmodule【例8.13】激励波形的描述'timescale 1ns/1nsmodule test1;reg A,B,C;initialbegin //激励波形描述A = 0;B = 1;C = 0;#100 C = 1;#100 A = 1; B = 0;#100 A = 0;#100 C = 0;#100 $finish;endinitial $monitor($time,,,"A=%d B=%d C=%d",A,B,C); //显示endmodule【例8.15】用always过程块产生两个时钟信号module test2;reg clk1,clk2;parameter CYCLE = 100;alwaysbegin{clk1,clk2} = 2'b10;#(CYCLE/4) {clk1,clk2} = 2'b01;#(CYCLE/4) {clk1,clk2} = 2'b11;#(CYCLE/4) {clk1,clk2} = 2'b00;#(CYCLE/4) {clk1,clk2} = 2'b10;endinitial $monitor($time,,,"clk1=%b clk2=%b",clk1,clk2); endmodule【例8.17】存储器在仿真程序中的应用module ROM(addr,data,oe);output[7:0] data; //数据信号input[14:0] addr; //地址信号input oe; //读使能信号,低电平有效- 27 - 程序文本reg[7:0] mem[0:255]; //存储器定义parameter DELAY = 100;assign #DELAY data=(oe==0) ? mem[addr] : 8'hzz; initial $readmemh("rom.hex",mem); //从文件中读入数据endmodule【例8.18】8位乘法器的仿真程序`timescale 10ns/1nsmodule mult_tp; //测试模块的名字reg[7:0] a,b; //测试输入信号定义为reg型wire [15:0] out; //测试输出信号定义为wire型integer i,j;mult8 m1(out,a,b); //调用测试对象//激励波形设定initialbegina=0;b=0;for(i=1;i<255;i=i+1)#10 a=i;endinitialbeginfor(j=1;j<255;j=j+1)#10 b=j;endinitial //定义结果显示格式begin$monitor($time,,,"%d * %d= %d",a,b,out);#2560 $finish;endendmodulemodule mult8(out, a, b); //8位乘法器源代码parameter size=8;input[size:1] a,b; //两个操作数output[2*size:1] out; //结果assign out=a*b; //乘法运算符- 28 -王金明:《Verilog HDL程序设计教程》endmodule 【例8.19】8位加法器的仿真程序`timescale 1ns/1nsmodule add8_tp; //仿真模块无端口列表reg[7:0] A,B; //输入激励信号定义为reg型reg cin;wire[7:0] SUM; //输出信号定义为wire型wire cout;parameter DELY = 100;add8 AD1(SUM,cout,A,B,cin); //调用测试对象initial begin //激励波形设定A= 8'd0; B= 8'd0; cin=1'b0;#DELY A= 8'd100; B= 8'd200; cin=1'b1;#DELY A= 8'd200; B= 8'd88;#DELY A= 8'd210; B= 8'd18; cin=1'b0;#DELY A= 8'd12; B= 8'd12;#DELY A= 8'd100; B= 8'd154;#DELY A= 8'd255; B= 8'd255; cin=1'b1;#DELY $finish;end//输出格式定义initial $monitor($time,,,"%d + %d + %b = {%b, %d}",A,B,cin,cout,SUM);endmodulemodule add8(SUM,cout,A,B,cin); //待测试的8位加法器模块output[7:0] SUM;output cout;input[7:0] A,B;input cin;assign {cout,SUM}=A+B+cin;endmodule【例8.20】2选1多路选择器的仿真`timescale 1ns/1nsmodule mux_tp;reg a,b,sel;wire out;- 29 - 程序文本MUX2_1 m1(out,a,b,sel); //调用待测试模块initialbegina=1'b0; b=1'b0; sel=1'b0;#5 sel=1'b1;#5 a=1'b1; el=1'b0;#5 sel=1'b1;#5 a=1'b0; b=1'b1; el=1'b0;#5 sel=1'b1;#5 a=1'b1; b=1'b1; sel=1'b0;#5 sel=1'b1;endinitial $monitor($time,,,"a=%b b=%b sel=%b out=%b",a,b,sel,out);endmodulemodule MUX2_1(out,a,b,sel); //待测试的2选1MUX模块input a,b,sel;output out;not #(0.4,0.3) (sel_,sel); //#(0.4,0.3)为门延时and #(0.7,0.6) (a1,a,sel_);and #(0.7,0.6) (a2,b,sel);or #(0.7,0.6) (out,a1,a2);endmodule【例8.21】8位计数器的仿真`timescale 10ns/1nsmodule count8_tp;reg clk,reset; //输入激励信号定义为reg型wire[7:0] qout; //输出信号定义为wire型parameter DELY=100;counter C1(qout,reset,clk); //调用测试对象always #(DELY/2) clk = ~clk; //产生时钟波形initialbegin //激励波形定义clk =0; reset=0;- 30 -王金明:《Verilog HDL程序设计教程》#DELY reset=1;#DELY reset=0;#(DELY*300) $finish;end//结果显示initial $monitor($time,,,"clk=%d reset=%d qout=%d",clk,reset,qout);endmodulemodule counter(qout,reset,clk); //待测试的8位计数器模块output[7:0] qout;input clk,reset;reg[7:0] qout;always @(posedge clk)begin if (reset) qout<=0;else qout<=qout+1;endendmodule【例9.1】基本门电路的几种描述方法(1)门级结构描述module gate1(F,A,B,C,D);input A,B,C,D;output F;nand(F1,A,B); //调用门元件and(F2,B,C,D);or(F,F1,F2);endmodule(2)数据流描述module gate2(F,A,B,C,D);input A,B,C,D;output F;assign F=(A&B)|(B&C&D); //assign持续赋值endmodule(3)行为描述module gate3(F,A,B,C,D);input A,B,C,D;output F;- 31 - 程序文本reg F;always @(A or B or C or D) //过程赋值beginF=(A&B)|(B&C&D);endendmodule【例9.2】用bufif1关键字描述的三态门module tri_1(in,en,out);input in,en;output out;tri out;bufif1 b1(out,in,en); //注意三态门端口的排列顺序endmodule【例9.3】用assign语句描述的三态门module tri_2(out,in,en);output out;input in,en;assign out = en ? in : 'bz;//若en=1,则out=in;若en=0,则out为高阻态endmodule【例9.4】三态双向驱动器module bidir(tri_inout,out,in,en,b);inout tri_inout;output out;input in,en,b;assign tri_inout = en ? in : 'bz;assign out = tri_inout ^ b; endmodule【例9.5】三态双向驱动器module bidir2(bidir,en,clk);inout[7:0] bidir;input en,clk;reg[7:0] temp;assign bidir= en ? temp : 8'bz; always @(posedge clk)begin- 32 -王金明:《Verilog HDL程序设计教程》if(en) temp=bidir;else temp=temp+1;endendmodule【例9.6】3-8译码器module decoder_38(out,in);output[7:0] out;input[2:0] in;reg[7:0] out;always @(in)begincase(in)3'd0: out=8'b11111110;3'd1: out=8'b11111101;3'd2: out=8'b11111011;3'd3: out=8'b11110111;3'd4: out=8'b11101111;3'd5: out=8'b11011111;3'd6: out=8'b10111111;3'd7: out=8'b01111111;endcaseendendmodule【例9.7】8-3优先编码器module encoder8_3(none_on,outcode,a,b,c,d,e,f,g,h); output none_on;output[2:0] outcode;input a,b,c,d,e,f,g,h;reg[3:0] outtemp;assign {none_on,outcode}=outtemp;always @(a or b or c or d or e or f or g or h)beginif(h) outtemp=4'b0111;else if(g) outtemp=4'b0110;else if(f) outtemp=4'b0101;else if(e) outtemp=4'b0100;else if(d) outtemp=4'b0011;else if(c) outtemp=4'b0010;- 33 - 程序文本else if(b) outtemp=4'b0001;else if(a) outtemp=4'b0000;else outtemp=4'b1000;endendmodule【例9.8】用函数定义的8-3优先编码器module code_83(din, dout);input[7:0] din;output[2:0] dout;function[2:0] code; //函数定义input[7:0] din; //函数只有输入端口,输出为函数名本身if (din[7]) code = 3'd7;else if (din[6]) code = 3'd6;else if (din[5]) code = 3'd5;else if (din[4]) code = 3'd4;else if (din[3]) code = 3'd3;else if (din[2]) code = 3'd2;else if (din[1]) code = 3'd1;else code = 3'd0;endfunctionassign dout = code(din); //函数调用endmodule【例9.9】七段数码管译码器module decode47(a,b,c,d,e,f,g,D3,D2,D1,D0);output a,b,c,d,e,f,g;input D3,D2,D1,D0; //输入的4位BCD码reg a,b,c,d,e,f,g;always @(D3 or D2 or D1 or D0)begincase({D3,D2,D1,D0}) //用case语句进行译码4'd0: {a,b,c,d,e,f,g}=7'b1111110;4'd1: {a,b,c,d,e,f,g}=7'b0110000;4'd2: {a,b,c,d,e,f,g}=7'b1101101;4'd3: {a,b,c,d,e,f,g}=7'b1111001;4'd4: {a,b,c,d,e,f,g}=7'b0110011;4'd5: {a,b,c,d,e,f,g}=7'b1011011;- 34 -王金明:《Verilog HDL程序设计教程》4'd6: {a,b,c,d,e,f,g}=7'b1011111;。
电子科技大学CPU设计:《单周期CPU的设计与实现》-实验指导书

电子科技大学计算机科学与工程学院单周期CPU的设计与实现实验指导书[计算机组成原理实验]张建2013-12-13目录前言 (1)1.1 实验内容 (2)1.2实验要求 (2)2. 实验环境 (3)2.1 硬件平台 (3)2.2 软件平台 (3)2.3 实验主要仪器设备连接框图 (4)3. 实验原理 (5)3.1 概述 (5)3.2 单周期CPU的总体电路 (5)3.3 MIPS指令格式 (6)3.4 数据路径设计 (7)3.4.1 下一条指令地址的选择 (7)3.4.2 ALU的输入端 (8)3.4.3寄存器堆的输入端 (8)4. 基本功能部件的设计与实现 (10)4.1 32位2选1选择器的设计与实现 (10)4.2 32位4选1选择器的设计与实现 (18)4.3 5位2选1选择器的设计与实现 (19)4.4 带有异步清零的32位D触发器的设计与实现 (19)4.5 移位器的设计 (20)4.6 32位加/减法器的设计与实现 (20)5.运算器(ALU)的设计与实现 (21)6.寄存器堆(Register File)的设计与实现 (24)7.控制器(Control Unit)的设计与实现 (27)8. CPU的封装 (30)9. 测试 (32)9.1 指令存储器及测试程序 (32)9.2 数据存储器及测试数据 (33)9.3 仿真测试 (33)9.4 下载到开发板验证 (35)附件: (39)BTN_Anti_Jitter模块 (39)Hex7seg_decode模块 (39)前言《计算机组成原理》是计算机科学专业的一门重要专业基础课。
在该课程中的理论学习中系统地阐述了计算机各组成部件的工作原理、逻辑实现和设计方法及将各部件连接成整机的方法,计算机硬件与底层软件的接口,培养了学生对计算机硬件系统的分析、开发与设计的基本技能能力。
本实验开设的目的是让学生通过设计一个单周期的CPU,加深对计算机各组成部件功能的理解和掌握,更好地理解计算机的基本工作原理,培养和锻炼学生掌握计算机硬件设计的基本方法和技能。
基于VerilogHDL简单CPU设计

基于VerilogHDL的简单CPU设计摘要:本文实现了一个基于veriloghdl的简单cpu,系统由运算器、控制器、译码器、存储器、指令计数器五大模块构成。
在对各个模块时序仿真实验的基础上,系统整体功能测试成功。
系统具有良好的稳定性和灵活性,指令集易扩展。
关键词:veriloghdl;cpu;时序仿真中图分类号:tp3341 引言veriloghdl【1】是一种硬件描述语言(hdl:hardwarediscriptionlanguage),是一种以文本形式来描述数字系统硬件的结构和行为的语言,用它可以表示逻辑电路图、逻辑表达式,还可以表示数字逻辑系统所完成的逻辑功能。
由于verilog接近c语言的语言规则,适合进行fpga的开发和教学工作,得到了广泛的应用。
本文基于对cpu的研究,设计并实现了一个基于verilog的简单cpu,并成功进行了仿真实验。
2 cpu的功能和结构2.1 cpu的功能本cpu模型由五大部分组成,分别是运算器、控制器、译码器、存储器、指令计数器。
实现了一个简单指令集,包括停机指令,加,减,与,加载,存储等指令。
同时能进行数据的存储和管理【2】。
2.2 cpu的结构图2.2.1 cpu的架构图cpu的整体结构如上面两个图所示,各个模块协调工作,共同完成cpu的每一次任务。
指令格式为“op+0+opd1+opd2”其中op为3位操作码,0为固定位(或者说是没用的一位),opd1,opd2为6位操作数的地址(之前已经写入内存)。
寻址方式固定为立即数寻址。
3 cpu主要模块的实现3.1 运算器模块alu算术逻辑运算单元alu。
根据输入的6种不同操作码分别实现相应的加、减、与、加载,存储,停机等6种基本操作运算。
利用这几种基本运算可以实现很多种其它运算以及逻辑判断等操作:(1)hlt停机操作。
该操作将空一个指令周期,即6个时钟周期;(2)add相加。
该操作将取存储器中的两个数据相加;(3)and相与。
计算机组成原理实验报告-单周期CPU的设计与实现

1个时钟周期 Clock 电子科技大学计算机科学与工程学院标 准 实 验 报 告(实验)课程名称: 计算机组成原理实验 电子科技大学教务处制表电 子 科 技 大 学 实 验 报 告学生姓名: 郫县尼克杨 学 号: 2014 指导教师:陈虹 实验地点: 主楼A2-411 实验时间:12周-15周一、 实验室名称:主楼A2-411二、 实验项目名称:单周期CPU 的设计与实现。
三、 实验学时:8学时四、 实验原理:(一) 概述单周期(Single Cycle )CPU 是指CPU 从取出1条指令到执行完该指令只需1个时钟周期。
一条指令的执行过程包括:取指令→分析指令→取操作数→执行指令→保存结果。
对于单周期CPU 来说,这些执行步骤均在一个时钟周期内完成。
(二) 单周期cpu 总体电路本实验所设计的单周期CPU 的总体电路结构如下。
(三) MIPS 指令格式化MIPS 指令系统结构有MIPS-32和MIPS-64两种。
本实验的MIPS 指令选用MIPS-32。
以下所说的MIPS 指令均指MIPS-32。
MIPS 的指令格式为32位。
下图给出MIPS 指令的3种格式。
本实验只选取了9条典型的MIPS 指令来描述CPU 逻辑电路的设计方法。
下图列出了本实验的所涉及到的9条MIPS 指令。
五、 实验目的1、掌握单周期CPU 的工作原理、实现方法及其组成部件的原理和设计方法,如控制器、运算器等。
?2、认识和掌握指令与CPU 的关系、指令的执行过程。
?3、熟练使用硬件描述语言Verilog 、EDA 工具软件进行软件设计与仿真,以培养学生的分析和设计CPU 的能力。
六、 实验内容(一)拟定本实验的指令系统,指令应包含R 型指令、I 型指令和J 型指令,指令数为9条。
(二)CPU 各功能模块的设计与实现。
(三)对设计的各个模块的仿真测试。
(四)整个CPU 的封装与测试。
七、 实验器材(设备、元器件):(一)安装了Xilinx ISE Design Suite 的PC 机一台(二)FPGA 开发板:Anvyl Spartan6/XC6SLX45(三)计算机与FPGA 开发板通过JTAG (Joint Test Action Group )接口连接,其连接方式如图所示。
cpu设计实验报告

cpu设计实验报告CPU设计实验报告摘要:本实验旨在设计一个基本的中央处理器(CPU),并通过实验验证其性能和功能。
在设计过程中,我们使用了Verilog硬件描述语言和ModelSim仿真工具。
通过对CPU的设计和仿真实验,我们验证了CPU的正确性和性能,并对其进行了性能分析和优化。
1. 引言CPU是计算机系统中最核心的部件之一,它负责执行计算机指令和控制数据流动。
因此,设计一个高效、稳定的CPU对于计算机系统的性能至关重要。
本实验旨在通过Verilog硬件描述语言和ModelSim仿真工具,设计一个基本的CPU,并验证其性能和功能。
2. 设计过程我们首先对CPU的功能和性能进行了分析和规划,确定了CPU的基本架构和指令集。
然后,我们使用Verilog语言编写了CPU的硬件描述,并通过ModelSim进行了仿真验证。
在设计过程中,我们重点关注了CPU的时序逻辑、数据通路和控制逻辑,确保CPU能够正确地执行指令并保持稳定的性能。
3. 实验结果通过对CPU的设计和仿真实验,我们验证了CPU的正确性和性能。
我们使用了一系列的测试用例对CPU进行了功能和性能测试,并对其进行了性能分析和优化。
实验结果表明,我们设计的CPU能够正确地执行各种指令,并在性能上达到了预期的目标。
4. 总结和展望本实验通过Verilog硬件描述语言和ModelSim仿真工具,设计并验证了一个基本的CPU。
通过实验,我们对CPU的设计和性能有了更深入的了解,并对其进行了性能分析和优化。
未来,我们将进一步完善CPU的设计,提高其性能和功能,以满足计算机系统的需求。
综上所述,本实验为我们提供了一个宝贵的机会,通过实际设计和验证,深入了解了CPU的工作原理和性能特点,为我们今后的学习和研究打下了坚实的基础。
希望通过不懈的努力,我们能够设计出更加高效、稳定的CPU,为计算机系统的发展做出更大的贡献。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
LOAD_ACC RD\I WR\I LOAD_IR HALT\I
DATA_ENA
In<7..0>
DATA<7..0>\I
IR_ADDR<2..0>
fetch ir_addr<12..0> pc_addr<12..0>
addr<12..0> adr
ADDR<12..0>
PC_ADDR<12..0> ir_addr<12..0> load clock rst pc_addr<12..0>
什么是CPU?
CPU 即中央处理单元的英文缩写,它是计算机的核心部件。 计算机进行信息处理可分为两个步骤: 1) 将数据和程序(即指令序列)输入到计算机的存储器中。 2)从第一条指令的地址起开始执行该程序,得到所需结 果,结束运行。CPU的作用是协调并控制计算机的各个部 件执行程序的指令序列,使其有条不紊地进行。因此它必 须具有以下基本功能: a)取指令:当程序已在存储器中时,首先根据程序入 口地址取出一条程序,为此要发出指令地址及控制信号。 b)分析指令:即指令译码。是对当前取得的指令进行 分析,指出它要求什么操作,并产生相应的操作控制命令。
else begin if(ena) //如果加载指令寄存器信号load_ir 到来, begin //分两个时钟每次8位加载指令寄存器 casex(state) //先高字节,后低字节 1’b0: begin opc_iraddr[15:8]<=data; state<=1; end 1’b1: begin opc_iraddr[7:0]<=data; state<=0;end
module register(opc_iraddr,data,ena,clk1,rst); output [15:0] opc_iraddr; input [7:0] data; input ena, clk1, rst; reg [15:0] opc_iraddr; state 表示CPU取的是低八位还是高八位 reg state; always @(posedge clk1) begin if(rst) begin opc_iraddr<=16'b0000_0000_0000_0000; state<=1'b0; end
RISC CPU结构
RISC_CPU是一个复杂的数字逻辑电路,但是它的 基本部件的逻辑并不复杂。可把它分成八个基本 部件: 1) 时钟发生器 2) 指令寄存器 3) 累加器 4) RISC CPU算术逻辑运算单元 5) 数据控制器 6) 状态控制器 7) 程序计数器 8) 地址多路器
DATA<7..0>\I RST\I clk 1fetch CLK\I clk alu_clk clk_gen
OPCODE<2..0>
opcode<2..0> ZERO
CLK1 ZERO FETCH RST INC_PC LOAD_ACC LOAD_PC CONTROL WR OPCODE<2..0> LOAD_IR HALT DATACTL_ENA data<7..0> datactl data_ena INC_PC LOAD_PC RD
default: begin opc_iraddr[15:0]<=16'bxxxxxxxxxxxxxxxx; state<=1'bx; end endcase end else state<=1'b0; end end endmodule
3.累加器
ACCUMULATOR
ALU_O UT [7:0] D AT A[7:0] LO AD _ACC EN A CLK1 RS T RS T CLK1 ACCUM [7:0] ACCUM [7:0]
counter
RISC——CPU中各部件的相互连接关系
1 时钟发生器
CLK1
CLKGEN
CLK CLK RESET RESET
CLK1 ALU_CLK ALU_CLK
FETCH
FETCH
时钟发生器
时钟发生器 clkgen 利用外来时钟信号clk 来生成一系列时钟信号 clk1、fetch、alu_clk 送往CPU的其他部件。其中fetch是外来时钟 clk 的八分频信号。利用fetch的上升沿来触发CPU控制器开始执 行一条指令,同时fetch信号还将控制地址多路器输出指令地址和 数据地址。clk1信号用作指令寄存器、累加器、状态控制器的时 钟信号。alu_clk 则用于触发算术逻辑运算单元。
clk
clk1
clk2 clk4
fetch alu_clk
时钟发生器clkgen的波形
module clk_gen (clk,reset,clk1,clk2,clk4,fetch,alu_clk); input clk,reset; output clk1,clk2,clk4,fetch,alu_clk; wire clk,reset; reg clk2,clk4,fetch,alu_clk; reg[7:0] state; parameter S1 = 8'b00000001, S2 = 8'b00000010, S3 = 8'b00000100, S4 = 8'b00001000, S5 = 8'b00010000, S6 = 8'b00100000, S7 = 8'b01000000, S8 = 8'b10000000, idle = 8'b00000000;
S3: begin clk2 <= ~clk2; state <= S4; end S4: begin clk2 <= ~clk2; clk4 <= ~clk4; fetch <= ~fetch; state <= S5; end S5: begin clk2 <= ~clk2; state <= S6; end
c)执行指令:根据分析指令时产生的“操作 命令”形成相应的操作控制信号序列,通过 运算器,存储器及输入/输出设备的执行, 实现每条指令的功能,其中包括对运算结 果的处理以及下条指令地址的形成。 将其功能进一步细化,可概括如下: 1) 能对指令进行译码并执行规定的动作; 2) 可以进行算术和逻辑运算; 3) 能与存储器,外设交换数据; 4) 提供整个系统所需要的控制;
简化的RISC CPU设计简介
西安邮电学院计算机系 西安邮电学院计算机系
前言
这个CPU模型只是一个教学模型, 设计也不一定 合理,只是从原理上说明了一个简单的RISC_CPU 的构成。我们在这里介绍它的目的是想说明: Verilog HDL仿真和综合工具的潜力和本文介绍 的设计方法对软硬件联合设计是有重要意义的。 我们也希望这一章能引起对 CPU 原理和复杂数 字逻辑系统设计有兴趣的同学的注意,加入我们 的设计队伍。由于我们的经验与学识有限,不足 之处敬请读者指正。
S6: begin clk2 <= ~clk2; clk4 <= ~clk4; state <= S7; end S7: begin clk2 <= ~clk2; state <= S8; end
S8: begin clk2 clk4 fetch state end idle: default: endcase end endmodule state <= S1; state <= idle; <= <= <= <= ~clk2; ~clk4; ~fetch; S1;
2 指令寄存器
INSTRUCTION
DATA[7:0] DATA[7:0] LOAD_IR ENA CLK1 CLK1 RESET RST
REGISTER
OPCODE[2:0]
opc_iraddrs[15:0]
REGISTER
IR_ADDR[12:0]
顾名思义,指令寄存器用于寄存指令。 指令寄存器的触发时钟是clk1,在clk1的正沿触发下, 寄存器将数据总线送来的指令存入高8位或低8位寄存器 中。但并不是每个clk1的上升沿都寄存数据总线的数 据,因为数据总线上有时传输指令,有时传输数据。什 么 时 候 寄 存 , 什 么 时 候 不 寄 存 由 CPU 状 态 控 制 器 的 load_ir信号控制。load_ir信号通过ena 口输入到指令 寄存器。复位后,指令寄存器被清为零。 每条指令为2个字节,即16位。高3位是操作码,低13位 是地址。(CPU的地址总线为13位,寻址空间为8K字节。) 本设计的数据总线为8位,所以每条指令需取两次。先取 高8位,后取低8位。而当前取的是高8位还是低8位,由 变量state记录。state为零表示取的高8位,存入高8位 寄存器,同时将变量state置为1。下次再寄存时,由于 state为1,可知取的是低8位,存入低8位寄存器中。
4.算术运算器
D A T A [ 7 :0 ] ZERO D A T A [ 7 :0 ] ZERO
ALU
A L U _ O U T [ 7 :0 ] A L U _ O U T [ 7 :0 ]
A C C U M [ 7 :0 ] A C C U M [ 7 :0 ] ALU_C LO C K O P C O D E [ 2 :0 ] ALU_C LO C K O P C O D E [ 2 :0 ]
ACCUMULATOR
累加器用于存放当前的结果,它也是双目运算其中一个 数据来源。复位后,累加器的值是零。当累加器通过 ena口收到来自CPU状态控制器load_acc信号时,在clk1 时钟正跳沿时就收到来自于数据总线的数据。
module accum( accum, data, ena, clk1, rst); output[7:0]accum; input[7:0]data; input ena,clk1,rst; reg[7:0]accum; always@(posedge clk1) begin if(rst) accum<=8'b0000_0000; //Reset else if(ena)//当CPU状态控制器发出load_acc信号 accum<=data; //Accumulate end endmodule