Verilog课程设计.docx_第1页
Verilog课程设计.docx_第2页
Verilog课程设计.docx_第3页
Verilog课程设计.docx_第4页
Verilog课程设计.docx_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1 实验目的(1)学习risc_cpu的基本结构和原理;(2)了解verilog hdl仿真和综合工具的潜力;(3)展示verilog设计方法对软/硬件联合设计和验证的意义;(4)学习并掌握一些常用的 verilog语法和验证方法。二实验原理 cpu即中央处理单元的英文缩写,它是计算机的核心部件。计算机进行信息处理可分为两个步骤:(1)将数据和程序(即指令序列)输入计算机的存储器中。(2)从第一条指令的地址起开始执行该程序,得到所需结果,结束运行。cpu的作用是协调并控制计算机的各个部件并执行程序的指令序列,使其有条不紊地进行。因此它必须具有以下基本功能。取指令当程序忆在存储器中时,首先根据程序入口地址取出一条程序,为此要发出指令地址及控制信号。分析指令即指令译码,这是对当前取得的指令进行分析,指出它要求什么操作,并产生相应的操作控制命令。执行指令根据分析指令时产生的“操作命令”形成相应的操作控制信号序列,通过运算器、存储器及输入/输出设备的执行,实现每条指令的功能,其中包括对运算结果的处理以及下条指令地址的形成。将cpu的功能进一步细化,可概括如下:(1)能对指令进行译码并执行规定的动作;(2)可以进行算术和逻辑运算;(3)能与存储器和外设交换数据;(4)提供整个系统所需要的控制。尽管各种cpu的性能指标和结构细节各不相同,但它们所能完成的基本功能相同。由功能分析,可知任何一种cpu内部结构至少应包含下面这些部件:(1)算术逻辑运算部件(alu);(2)累加器;(3)程序计数器;(4)指令寄存器和译码器; (5)时序和控制部件。三.实验内容通过我们自己动手,设计出一个cpu的软核和固核。这个cpu是一个简化的专门为教学目的而设计的risc_cpu。在设计中我们不但关心cpu总体设计的合理性,而且还使得构成这个risc_cpu的每一个模块不仅是可仿真的也都可以综合成门级网表。因而从物理意义上说,这也是一个能真正通过具体电路结构而实现的cpu。为了能在这个虚拟的cpu上运行较为复杂的程序并进行仿真,把寻址空间规定为8k(即13们地址线)字节。四实验代码1.源代码/-clk_gen.v-timescale 1ns/1ns /时间单位1ns,时间单位1nsmodule clk_gen(clk,reset,fetch,alu_ena); /模块名clk_gen,参数列表(clk,reset,fetch,alu_ena)input clk,reset; /输入clk,resetoutput fetch,alu_ena; /输出fetch,alu_enawire clk,reset; /wire型变量clk,resetreg fetch,alu_ena; /reg寄存器型变量fetch,alu_enareg7:0state; /reg寄存器型变量8位的stateparameter s1=8b00000001,s2=8b00000010,s3=8b00000100,s4=8b00001000,s5=8b00010000,s6=8b00100000,s7=8b01000000,s8=8b10000000,idle=8b00000000; /参数型定义8位二进制常量s1,s2,s3,s4,s5,s6,s7,s8,idlealways(posedge clk) /always块时钟触发if(reset) /如果reset为真begin /执行begin,and顺序块fetch=0; /fetch非阻塞赋值赋为0alu_ena=0; /alu_ena非阻塞赋值赋为0state=idle; /idle非阻塞赋值给stateendelse /reset为假执行下面begin语句begincase(state) /case表达式(state)s1:beginalu_ena=1; /alu_ena非阻塞赋值赋为1state=s2; /state非阻塞赋值赋为s2ends2:begin alu_ena=0; /alu_ena非阻塞赋值赋为0state=s3; /state非阻塞赋值赋为s3ends3:beginalu_ena=1; /alu_ena非阻塞赋值赋为1state=s4; /state非阻塞赋值赋为s4ends4:beginstate=s5; /state非阻塞赋值赋为s5ends5:state=s6; /state非阻塞赋值赋为s6s6:state=s7; /state非阻塞赋值赋为s7s7:beginfetch=0; /fetch非阻塞赋值赋为0state=s8; /state非阻塞赋值赋为s8ends8:beginstate=s1; /state非阻塞赋值赋为s1endidle:state=s1; /idle_state非阻塞赋值赋为s1default:state=idle; /default_state非阻塞赋值赋为idleendcaseendendmodule /结束module模块/-register.v-timescale 1ns/1ns /时间单位1ns,时间精度1nsmodule register(opc_iraddr,data,ena,clk,rst); /模块名register参数链表(变量名) output15:0 opc_iraddr; /输出16位的opc_iraddr input7:0data; /输入8位的datainput ena,clk,rst; /输入ena,clk,rstreg15:0opc_iraddr; /定义16位的寄存器型变量opc_iraddrreg state; /定义寄存器型变量statealways(posedge clk) /always时钟触发beginif(rst) /判断rst是否为真beginopc_iraddr=16b0000_0000_0000_0000; /opc_iraddr非阻塞赋值赋为16位的二进制数state=1b0; /state非阻塞赋值赋为1位的二进制数 end elsebeginif(ena) /如果加载指令寄存器信号load_ir begin /分两个时钟,每次8位加载指令寄存器casex(state) /先高字节后低字节1b0:beginopc_iraddr15:8=data; /后8位的opc_iraddr非阻塞赋值赋为data state=1; /state非阻塞赋值赋为1end1b1:beginopc_iraddr7:0=data; /8位的opc_iraddr非阻塞赋值赋为data state=0; /state非阻塞赋值赋为0enddefault:beginopc_iraddr15:0=16bxxxxxxxxxxxxxxxx; /16位的opc_iraddr非阻塞赋值赋为16位的二进制数state=1bx; /state非阻塞赋值赋为1位的二进制数endendcaseendelsestate=1b0; /state非阻塞赋值赋为1位的二进制数endendendmodule-accum.v-module accum(accum,data,ena,clk,rst); /模块名accum参数列表()output7:0 accum; /输出8位的accuminput7:0data; /输入8位的datainput ena,clk,rst; /输入为ena,clk,rstreg7:0accum; /定义一个寄存器型变量accumalways(posedge clk) /always时钟触发beginif(rst) /判断rst是否为真accum=8b0000_0000; /resetelseif(ena) /cpu状态控制器发出load_acc信号accum=data; /aaccumulateendendmodule-alu.v-timescale 1ns/1ns /时间单位1ns,时间精度1nsmodule alu(clk,alu_out,zero,data,accum,alu_ena,opcode); /模块名alu参数列表()output7:0data,accum,alu_out,zero; /输出8位的data,accum,alu_out,zeroinput2:0opcode; /输入3位的opcodeinput alu_ena,clk; /输入为alu_ena,clkreg7:0alu_out; /定义一个8位的寄存器型变量alu_out parameter hlt =3b000, /参数定义一个常量 hlt阻塞赋值为3位的二进制数0 skz =3b001, /skz阻塞赋值为3位的二进制数1 add =3b010, /add阻塞赋值为3位的二进制数2 andd=3b011, /andd阻塞赋值为3位的二进制数3 xorr=3b100, /xorr阻塞赋值为3位的二进制数4 lda =3b101, /lda阻塞赋值为3位的二进制数5 sto =3b110, /sto阻塞赋值为3位的二进制数6 jmp =3b111; /jmp阻塞赋值为3位的二进制数7 assign zero=!accum; / always(posedge clk) /always时钟触发模块 if(alu_ena) /判断alu_ena是否为真 begin /操作码来自指令寄存器的输出opc_iaddr(15.0)的低三位 casex(opcode) /casex(变量名) hlt:alu_out=accum; skz:alu_out=accum; add:alu_out=data+accum; andd:alu_out=data&accum; xorr:alu_out=dataaccum; lda:alu_out=data; sto:alu_out=accum; jmp:alu_out=8bxxxx_xxxx; /以上都不是则alu_out非阻塞赋值赋为8位的二进制数 endcase endendmodule-datactl.v-module datactl(data,in,data_ena); /模块名datactl参数列表() output7:0data; /输出8位的data input7:0in; /输入8位的in input data_ena; /输入data_ena assign data=(data_ena)?in:8bzzzz_zzzz; /data_ena是否为1,如果为1就把in赋给data,为0则把高阻态赋给dataendmodule-adr.v-module adr(addr,fetch,ir_addr,pc_addr); /模块名adr参数列表() output12:0addr; /输出13位的addr input12:0ir_addr,pc_addr; /输入13位的ir_addr,pc_addr input fetch; /输入fetch assign addr=fetch? pc_addr:ir_addr; /fetch是否为1,如果为1就把pc_addr赋给addr,为0则把ir_addr赋给addrendmodule-counter.v-module counter(pc_addr,ir_addr,load,clock,rst); /模块名counter参数列表() output12:0pc_addr; /输出13位的pc_addr input12:0ir_addr; /输入13位的ir_addr input load,clock,rst; /输入load,clock,rst reg12:0pc_addr; /定义13位的寄存器型变量pc_addr always(posedge clock or posedge rst) / always时钟或复位触发模块 begin if(rst) pc_addr=13b0_0000_0000_0000; /reset else if(load) pc_addr=ir_addr; /load else pc_addr=pc_addr+1; /把pc_addr+1非阻塞赋值给pc_addr endendmodule-machinectl.v-timescale 1ns/1nsmodule machinectl(ena,fetch,rst,clk); /machinectl模块输入输出列表 input fetch,rst,clk; /输入为fetch,rst,clk output ena; /输出ena reg ena; /定义寄存器型变量ena reg state; /定义寄存器型变量state always(posedge clk) /上升沿触发 begin if(rst) /如果rst为真 begin ena=0; /把0非阻塞赋值给ena end /结束 else /否则 if(fetch) /如果fetch为真 begin ena=1; /把1非阻塞赋值给ena end /结束 end /结束 endmodule /结束模块-machine.v-timescale 1ns/1nsmodule machine(inc_pc,load_acc,load_pc,rd,wr,load_ir,datactl_ena,halt,clk,zero,ena,opcode); /模块名machine,参数列表output inc_pc,load_acc,load_pc,rd,wr,load_ir; /输出为inc_pc,load_acc,load_pc,rd,wr,load_iroutput datactl_ena,halt; /输出为datactl_ena,haltinput clk,zero,ena; /输入为clk,zero,enainput2:0opcode; /输入为3位的opcodereg inc_pc,load_acc,load_pc,rd,wr,load_ir /定义寄存器型变量 reg datactl_ena,halt; /定义寄存器型变量 datactl_ena,haltreg2:0state; /定义3位的寄存器型变量stateparameter hlt=3b000,skz=3b001,add=3b010,andd=3b011,xorr=3b100,lda=3b101,sto=3b110,jmp=3b111; /参数定义常量always(negedge clk) /时钟触发begin if(!ena) /接收复位信号rst,进行复位操作beginstate=3b000; /state非阻塞赋值为3位的二进制数inc_pc,load_acc,load_pc,rd=4b0000; /非阻塞赋值4位的0wr,load_ir,datactl_ena,halt=4b0000; /非阻塞赋值4位的0end elsectl_cycle; /否则进入ctl_cycle任务endtask ctl_cycle; /ctl_cycle任务begin casex(state)3b000: /载入高8位到structionbegininc_pc,load_acc,load_pc,rd=4b0001; /非阻塞赋值4位的0wr,load_ir,datactl_ena,halt=4b0100; /非阻塞赋值4位的0state=3b001; /state非阻塞赋值赋为3位的1end3b001: /pc增加来自低8位instructionbegin/inc_pc,load_acc,load_pc,rd=4b1001; /非阻塞赋值wr,load_ir,datactl_ena,halt=4b0100; /非阻塞赋值state=3b010; /非阻塞赋值end3b010: /idlebegininc_pc,load_acc,load_pc,rd=4b0000; /非阻塞赋值wr,load_ir,datactl_ena,halt=4b0000; /非阻塞赋值state=3b011; /非阻塞赋值end3b011: /分析指令从这里开始begin if(opcode=hlt) /指令为暂停hltbegininc_pc,load_acc,load_pc,rd=4b1000; /非阻塞赋值wr,load_ir,datactl_ena,halt=4b0001; /非阻塞赋值endelsebegininc_pc,load_acc,load_pc,rd=4b1000; /非阻塞赋值wr,load_ir,datactl_ena,halt=4b0000; /非阻塞赋值endstate=3b100; /非阻塞赋值end3b100: /fetch oprandbeginif(opcode=jmp) /指令为暂停jmp begin inc_pc,load_acc,load_pc,rd=4b0010; /非阻塞赋值 wr,load_ir,datactl_ena,halt=4b0000; /非阻塞赋值 end else if(opcode=add|opcode=andd|opcode=xorr|opcode=lda) /如果指令为暂停add,或者指令为暂停andd,或者指令为暂停xorr,或者指令为暂停lda begin inc_pc,load_acc,load_pc,rd=4b0001; /非阻塞赋值 wr,load_ir,datactl_ena,halt=4b0000; /非阻塞赋值 end else if(opcode=sto) /如果指令为暂停sto begin inc_pc,load_acc,load_pc,rd=4b0001; /非阻塞赋值 wr,load_ir,datactl_ena,halt=4b0000; /非阻塞赋值 end else begin inc_pc,load_acc,load_pc,rd=4b0000; /非阻塞赋值 wr,load_ir,datactl_ena,halt=4b0000; /非阻塞赋值 end state=3b101; /非阻塞赋值 end 3b101: begin if(opcode=add|opcode=andd|opcode=xorr|opcode=lda) /如果指令为暂停add,或者指令为暂停andd,或者指令为暂停xorr,或者指令为暂停lda begin /过一个时钟后与累加内容进行运算 inc_pc,load_acc,load_pc,rd=4b0101; /非阻塞赋值 wr,load_ir,datactl_ena,halt=4b0000; /非阻塞赋值 end else if(opcode=skz&zero=1) /如果指令为暂停skz并且zero为1 begin inc_pc,load_acc,load_pc,rd=4b1000; /非阻塞赋值 wr,load_ir,datactl_ena,halt=4b0000; /非阻塞赋值 end else if(opcode=jmp) /如果指令为暂停jmp begin inc_pc,load_acc,load_pc,rd=4b1001; /非阻塞赋值 wr,load_ir,datactl_ena,halt=4b0000; /非阻塞赋值 end else if(opcode=sto) /如果指令为暂停sto begin /过一个时钟后把wr变1就可以写到ram中 inc_pc,load_acc,load_pc,rd=4b0000;/非阻塞赋值 wr,load_ir,datactl_ena,halt=4b1010; /非阻塞赋值 end else begin inc_pc,load_acc,load_pc,rd=4b0000;/非阻塞赋值 wr,load_ir,datactl_ena,halt=4b0000;/非阻塞赋值 end state=3b110; /非阻塞赋值 end 3b110: begin if(opcode=sto) /指令为暂停sto begin inc_pc,load_acc,load_pc,rd=4b0000; /非阻塞赋值 wr,load_ir,datactl_ena,halt=4b0010; /非阻塞赋值 end else if(opcode=add|opcode=andd|opcode=xorr|opcode|lda) /如果指令为暂停add,或者指令为暂停andd,或者指令为暂停xorr,或者指令为暂停lda begin inc_pc,load_acc,load_pc,rd=4b0001; /非阻塞赋值 wr,load_ir,datactl_ena,halt=4b0000; /非阻塞赋值 end else begin inc_pc,load_acc,load_pc,rd=4b0000; /非阻塞赋值 wr,load_ir,datactl_ena,halt=4b0000; /非阻塞赋值 end state=3b111; /非阻塞赋值 end 3b111: begin if(opcode=skz&zero=1) /如果指令为暂停skz并且zero为1 begin inc_pc,load_acc,load_pc,rd=4b1000; /非阻塞赋值 wr,load_ir,datactl_ena,halt=4b0000; /非阻塞赋值 end else begin inc_pc,load_acc,load_pc,rd=4b0000; /非阻塞赋值 wr,load_ir,datactl_ena,halt=4b0000; /非阻塞赋值 end state=3b000; /非阻塞赋值 end default: begin inc_pc,load_acc,load_pc,rd=4b0000; /非阻塞赋值 wr,load_ir,datactl_ena,halt=4b0000; /非阻塞赋值 state=3b000; /非阻塞赋值 end endcase end endtaskendmodule-addr_decode.v-module addr_decode( addr ,rom_sel,ram_sel); /模块名addr_decode参数列表()output rom_sel,ram_sel; /输出rom-sel,ram_selinput12:0 addr; /输入13位的addrreg rom_sel,ram_sel; /定义2个寄存器型变量rom_sel,ram_selalways (addr) /always模块addr触发begincasex(addr) /casex(变量名)13b1_1xxx_xxxx_xxxx:rom_sel,ram_sel=2b01;13b0_xxxx_xxxx_xxxx:rom_sel,ram_sel=2b10;13b1_0xxx_xxxx_xxxx:rom_sel,ram_sel=2b10;default:rom_sel,ram_sel=2b00; /以上都不是则将0非阻塞赋值给(rom_sel,ram_sel)endcaseendendmodule-ram.v-module ram(data,addr,ena,read,write); /模块名ram参数列表()inout7:0data; /输入8位的datainput9:0addr; /输入10位的addrinput ena; /输入enainput read,write; /输入read,writereg7:0ram10h3ff:0; /定义一个8位的寄存器型变量ramassign data=(read&ena)?ramaddr:8hzz; /若read&ena为1,就把ramaddr赋给data,否则就把高阻态赋给dataalways(posedge write) /always写触发模块beginramaddr=data; /data非阻塞赋值赋给ramaddrendendmodule-rom.v-module rom(data,addr,read,ena); /模块名rom参数列表()output7:0data; /输出8位的datainput12:0addr; /输入13位的addrinput read,ena; /输入read,enareg7:0memory12h1fff:0; /定义一个8位的寄存器型变量memorywire7:0data; /定义一个8位的wire型变量dataassign data=(read&ena)?memoryaddr:8bzzzzzzzz; /若read&ena为1,就把memoryaddr赋给data,否则就把高阻态赋给dataendmodule2.测试代码-cputop.v-includeaddr_decode.vincludeaccum.vincludemachinect1.vtimescale 1ns/1nsdefine period 100 / matches clk_gen.vmodule cputop; /cputop模块reg reset_req,clock; /定义寄存器型变量integer test; /变量为有符号数reg (3*8):0mnemonic; /array that holds 3 8 bit ascii charactersreg12:0pc_addr,ir_addr; /寄存器型变量wire7:0data; /定义wire型变量wire12:0addr;/定义wire型变量wire rd,wr,halt,ram_sel,rom_sel; /定义wire型变量wire2:0opcode; /为布线后仿真做的专门添加的cpu内部信号线wire12:0ir_addr,pc_addr; /为布线后仿真做的专门添加的cpu内部信号线cpu t_cpu(.clk(clock),.reset(reset_req),.halt(halt),.rd(rd),.wr(wr),.addr(addr),.data(alu_out),.opcode(opcode),.fetch(fetch),.ir_addr(ir_addr),.pc_addr(pc_addr);ram t_ram(.addr(addr9:0),.read(rd),.write(wr),.ena(ram_sel),.data(data);rom t_rom(.addr(addr),.read(rd),.ena(rom_sel),.data(data);addr_decode t_addr_decode(.addr(addr),.ram_sel(ram_sel),.rom_sel(rom_sel);initialbeginclock=1;$timeformat(-9,1,ns,12);/设定当前的时间格式display_debug_message; /展示调试信息sys_reset;test1;$stop;test2;$stop;test3;$f

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论