当前位置:文档之家› Verilog课程设计

Verilog课程设计

一.实验目的(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_enareg[7:0]state; //reg寄存器型变量8位的stateparameterS1=8'b00000001,S2=8'b00000010,S3=8'b00000100,S4=8'b00001000,S5=8'b00010000,S6=8'b001 00000,S7=8'b01000000,S8=8'b10000000,idle=8'b00000000;//参数型定义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:beginalu_ena<=0; //alu_ena非阻塞赋值赋为0state<=S3; //state非阻塞赋值赋为S3endalu_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参数链表(变量名)output[15:0] opc_iraddr; //输出16位的opc_iraddrinput[7:0]data; //输入8位的datainput ena,clk,rst; //输入ena,clk,rstreg[15:0]opc_iraddr; //定义16位的寄存器型变量opc_iraddrreg state; //定义寄存器型变量statealways@(posedge clk) //always时钟触发beginif(rst) //判断rst是否为真beginopc_iraddr<=16'b0000_0000_0000_0000; //opc_iraddr非阻塞赋值赋为16位的二进制数state<=1'b0; //state非阻塞赋值赋为1位的二进制数endelsebeginif(ena) //如果加载指令寄存器信号load_irbegin //分两个时钟,每次8位加载指令寄存器casex(state) //先高字节后低字节opc_iraddr[15:8]<=data; //后8位的opc_iraddr非阻塞赋值赋为datastate<=1; //state非阻塞赋值赋为1end1'b1:beginopc_iraddr[7:0]<=data; //8位的opc_iraddr非阻塞赋值赋为datastate<=0; //state非阻塞赋值赋为0enddefault:beginopc_iraddr[15:0]<=16'bxxxxxxxxxxxxxxxx; //16位的opc_iraddr非阻塞赋值赋为16位的二进制数state<=1'bx; //state非阻塞赋值赋为1位的二进制数endendcaseendelsestate<=1'b0; //state非阻塞赋值赋为1位的二进制数endendEndmodule--------------------------------accum.v------------------------------module accum(accum,data,ena,clk,rst); //模块名accum参数列表()output[7:0] accum; //输出8位的accuminput[7:0]data; //输入8位的datainput ena,clk,rst; //输入为ena,clk,rstreg[7:0]accum; //定义一个寄存器型变量accumalways@(posedge clk) //always时钟触发beginif(rst) //判断rst是否为真accum<=8'b0000_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参数列表()output[7:0]data,accum,alu_out,zero; //输出8位的data,accum,alu_out,zeroinput[2:0]opcode; //输入3位的opcodeinput alu_ena,clk; //输入为alu_ena,clkreg[7:0]alu_out; //定义一个8位的寄存器型变量alu_outparameter HLT =3'b000, //参数定义一个常量HLT阻塞赋值为3位的二进制数0 SKZ =3'b001, //SKZ阻塞赋值为3位的二进制数1ADD =3'b010, //ADD阻塞赋值为3位的二进制数2ANDD=3'b011, //ANDD阻塞赋值为3位的二进制数3XORR=3'b100, //XORR阻塞赋值为3位的二进制数4LDA =3'B101, //LDA阻塞赋值为3位的二进制数5STO =3'b110, //STO阻塞赋值为3位的二进制数6JMP =3'b111; //JMP阻塞赋值为3位的二进制数7assign 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<=data^accum;LDA:alu_out<=data;STO:alu_out<=accum;JMP:alu_out<=8'bxxxx_xxxx; //以上都不是则alu_out非阻塞赋值赋为8位的二进制数endcaseendEndmodule-------------------------------------datactl.v----------------------------module datactl(data,in,data_ena); //模块名datactl参数列表()output[7:0]data; //输出8位的datainput[7:0]in; //输入8位的ininput data_ena; //输入data_enaassign data=(data_ena)?in:8'bzzzz_zzzz; //data_ena是否为1,如果为1就把in 赋给data,为0则把高阻态赋给dataEndmodule---------------------------adr.v----------------------------------module adr(addr,fetch,ir_addr,pc_addr); //模块名adr参数列表()output[12:0]addr; //输出13位的addrinput[12:0]ir_addr,pc_addr; //输入13位的ir_addr,pc_addrinput fetch; //输入fetchassign 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参数列表()output[12:0]pc_addr; //输出13位的pc_addrinput[12:0]ir_addr; //输入13位的ir_addrinput load,clock,rst; //输入load,clock,rstreg[12:0]pc_addr; //定义13位的寄存器型变量pc_addralways@(posedge clock or posedge rst) // always时钟或复位触发模块beginif(rst)pc_addr<=13'b0_0000_0000_0000; //Resetelseif(load)pc_addr<=ir_addr; //Loadelsepc_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,clkoutput ena; //输出enareg ena; //定义寄存器型变量enareg state; //定义寄存器型变量statealways@(posedge clk) //上升沿触发beginif(rst) //如果rst为真beginena<=0; //把0非阻塞赋值给enaend //结束else //否则if(fetch) //如果fetch为真beginena<=1; //把1非阻塞赋值给enaend //结束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_ir output datactl_ena,halt; //输出为datactl_ena,haltinput clk,zero,ena; //输入为clk,zero,enainput[2:0]opcode; //输入为3位的opcodereg inc_pc,load_acc,load_pc,rd,wr,load_ir //定义寄存器型变量reg datactl_ena,halt; //定义寄存器型变量datactl_ena,haltreg[2:0]state; //定义3位的寄存器型变量stateparameterHLT=3'b000,SKZ=3'B001,ADD=3'b010,ANDD=3'b011,XORR=3'b100,LDA=3'b101,STO=3'b110,JMP= 3'b111; //参数定义常量always@(negedge clk) //时钟触发beginif(!ena) //接收复位信号RST,进行复位操作beginstate<=3'b000; //state非阻塞赋值为3位的二进制数{inc_pc,load_acc,load_pc,rd}<=4'b0000; //非阻塞赋值4位的0{wr,load_ir,datactl_ena,halt}<=4'b0000; //非阻塞赋值4位的0endelsectl_cycle; //否则进入ctl_cycle任务endtask ctl_cycle; //ctl_cycle任务begincasex(state)3'b000: //载入高8位到structionbegin{inc_pc,load_acc,load_pc,rd}<=4'b0001; //非阻塞赋值4位的0{wr,load_ir,datactl_ena,halt}<=4'b0100; //非阻塞赋值4位的0state<=3'b001; //state非阻塞赋值赋为3位的1end3'b001: //pc增加来自低8位instructionbegin/{inc_pc,load_acc,load_pc,rd}<=4'b1001; //非阻塞赋值{wr,load_ir,datactl_ena,halt}<=4'b0100; //非阻塞赋值state<=3'b010; //非阻塞赋值end3'b010: //idlebegin{inc_pc,load_acc,load_pc,rd}<=4'b0000; //非阻塞赋值{wr,load_ir,datactl_ena,halt}<=4'b0000; //非阻塞赋值state<=3'b011; //非阻塞赋值end3'b011: //分析指令从这里开始beginif(opcode==HLT) //指令为暂停HLTbegin{inc_pc,load_acc,load_pc,rd}<=4'b1000; //非阻塞赋值{wr,load_ir,datactl_ena,halt}<=4'b0001; //非阻塞赋值endelsebegin{inc_pc,load_acc,load_pc,rd}<=4'b1000; //非阻塞赋值{wr,load_ir,datactl_ena,halt}<=4'b0000; //非阻塞赋值endstate<=3'b100; //非阻塞赋值end3'b100: //fetch oprandbeginif(opcode==JMP) //指令为暂停JMPbegin{inc_pc,load_acc,load_pc,rd}<=4'b0010; //非阻塞赋值{wr,load_ir,datactl_ena,halt}<=4'b0000; //非阻塞赋值endelseif(opcode==ADD||opcode==ANDD||opcode==XORR||opcode==LDA) //如果指令为暂停ADD,或者指令为暂停ANDD,或者指令为暂停XORR,或者指令为暂停LDAbegin{inc_pc,load_acc,load_pc,rd}<=4'b0001; //非阻塞赋值{wr,load_ir,datactl_ena,halt}<=4'b0000; //非阻塞赋值endelseif(opcode==STO) //如果指令为暂停STObegin{inc_pc,load_acc,load_pc,rd}<=4'b0001; //非阻塞赋值{wr,load_ir,datactl_ena,halt}<=4'b0000; //非阻塞赋值endelsebegin{inc_pc,load_acc,load_pc,rd}<=4'b0000; //非阻塞赋值{wr,load_ir,datactl_ena,halt}<=4'b0000; //非阻塞赋值endstate<=3'b101; //非阻塞赋值end3'b101:beginif(opcode==ADD||opcode==ANDD||opcode==XORR||opcode==LDA) //如果指令为暂停ADD,或者指令为暂停ANDD,或者指令为暂停XORR,或者指令为暂停LDAbegin //过一个时钟后与累加内容进行运算{inc_pc,load_acc,load_pc,rd}<=4'b0101; //非阻塞赋值{wr,load_ir,datactl_ena,halt}<=4'b0000; //非阻塞赋值endelseif(opcode==SKZ&&zero==1) //如果指令为暂停SKZ并且zero为1begin{inc_pc,load_acc,load_pc,rd}<=4'b1000; //非阻塞赋值{wr,load_ir,datactl_ena,halt}<=4'b0000; //非阻塞赋值endelseif(opcode==JMP) //如果指令为暂停JMPbegin{inc_pc,load_acc,load_pc,rd}<=4'b1001; //非阻塞赋值{wr,load_ir,datactl_ena,halt}<=4'b0000; //非阻塞赋值endelseif(opcode==STO) //如果指令为暂停STObegin //过一个时钟后把wr变1就可以写到RAM中{inc_pc,load_acc,load_pc,rd}<=4'b0000;//非阻塞赋值{wr,load_ir,datactl_ena,halt}<=4'b1010; //非阻塞赋值endelsebegin{inc_pc,load_acc,load_pc,rd}<=4'b0000;//非阻塞赋值{wr,load_ir,datactl_ena,halt}<=4'b0000;//非阻塞赋值endstate<=3'b110; //非阻塞赋值end3'b110:beginif(opcode==STO) //指令为暂停STObegin{inc_pc,load_acc,load_pc,rd}<=4'b0000; //非阻塞赋值{wr,load_ir,datactl_ena,halt}<=4'b0010; //非阻塞赋值endelseif(opcode==ADD||opcode==ANDD||opcode==XORR||opcode||LDA) //如果指令为暂停ADD,或者指令为暂停ANDD,或者指令为暂停XORR,或者指令为暂停LDAbegin{inc_pc,load_acc,load_pc,rd}<=4'b0001; //非阻塞赋值{wr,load_ir,datactl_ena,halt}<=4'b0000; //非阻塞赋值endelsebegin{inc_pc,load_acc,load_pc,rd}<=4'b0000; //非阻塞赋值{wr,load_ir,datactl_ena,halt}<=4'b0000; //非阻塞赋值endstate<=3'b111; //非阻塞赋值end3'b111:beginif(opcode==SKZ&&zero==1) //如果指令为暂停SKZ并且zero为1begin{inc_pc,load_acc,load_pc,rd}<=4'b1000; //非阻塞赋值{wr,load_ir,datactl_ena,halt}<=4'b0000; //非阻塞赋值endelsebegin{inc_pc,load_acc,load_pc,rd}<=4'b0000; //非阻塞赋值{wr,load_ir,datactl_ena,halt}<=4'b0000; //非阻塞赋值endstate<=3'b000; //非阻塞赋值enddefault:begin{inc_pc,load_acc,load_pc,rd}<=4'b0000; //非阻塞赋值{wr,load_ir,datactl_ena,halt}<=4'b0000; //非阻塞赋值state<=3'b000; //非阻塞赋值endendcaseendendtaskendmodule----------------------------addr_decode.v---------------------------module addr_decode( addr ,rom_sel,ram_sel); //模块名addr_decode参数列表()output rom_sel,ram_sel; //输出rom-sel,ram_selinput[12:0] addr; //输入13位的addrreg rom_sel,ram_sel; //定义2个寄存器型变量rom_sel,ram_selalways @(addr) //always模块addr触发begincasex(addr) //casex(变量名)13'b1_1xxx_xxxx_xxxx:{rom_sel,ram_sel}<=2'b01;13'b0_xxxx_xxxx_xxxx:{rom_sel,ram_sel}<=2'b10;13'b1_0xxx_xxxx_xxxx:{rom_sel,ram_sel}<=2'b10;default:{rom_sel,ram_sel}<=2'b00; //以上都不是则将0非阻塞赋值给(rom_sel,ram_sel)endcaseendEndmodule-------------------------ram.v--------------------------module ram(data,addr,ena,read,write); //模块名ram参数列表()inout[7:0]data; //输入8位的datainput[9:0]addr; //输入10位的addrinput ena; //输入enainput read,write; //输入read,writereg[7:0]ram[10'h3ff:0]; //定义一个8位的寄存器型变量ramassign data=(read&&ena)?ram[addr]:8'hzz; //若read&&ena为1,就把ram[addr]赋给data,否则就把高阻态赋给dataalways@(posedge write) //always写触发模块beginram[addr]<=data; //data非阻塞赋值赋给ram[addr]endEndmodule--------------------------------rom.v-----------------------module rom(data,addr,read,ena); //模块名rom参数列表()output[7:0]data; //输出8位的datainput[12:0]addr; //输入13位的addrinput read,ena; //输入read,enareg[7:0]memory[12'h1fff:0]; //定义一个8位的寄存器型变量memorywire[7:0]data; //定义一个8位的wire型变量dataassign data=(read&&ena)?memory[addr]:8'bzzzzzzzz; //若read&&ena为1,就把memory[addr]赋给data,否则就把高阻态赋给dataEndmodule2.测试代码-------------------------cputop.v---------------------`include"addr_decode.v"`include"accum.v"`include"machinect1.v"`timescale 1ns/1ns`define PERIOD 100 // matches clk_gen.vmodule cputop; //cputop模块reg reset_req,clock; //定义寄存器型变量integer test; //变量为有符号数reg [(3*8):0]mnemonic; //array that holds 3 8 bit ASCII charactersreg[12:0]PC_addr,IR_addr; //寄存器型变量wire[7:0]data; //定义wire型变量wire[12:0]addr;//定义wire型变量wire rd,wr,halt,ram_sel,rom_sel; //定义wire型变量wire[2:0]opcode; //为布线后仿真做的专门添加的CPU内部信号线wire[12:0]ir_addr,pc_addr; //为布线后仿真做的专门添加的CPU内部信号线cput_cpu(.clk(clock),.reset(reset_req),.halt(halt),.rd(rd),.wr(wr),.addr(addr),.data(alu_out),.opcode(o pcode),.fetch(fetch),.ir_addr(ir_addr),.pc_addr(pc_addr));ram t_ram(.addr(addr[9: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;$finish;endtask display_debug_message; //展示调试信息begin$display("\n********************"); //输出引用的附加的说明文字$display("* THE FOLLOWING DEBUG TASK ARE AVAILABLE:*"); //输出引用的附加的说明文字$display("*\”test1;\“to load the 1st diagnostic program.*"); //输出引用的附加的说明文字$display("*\”test2;\“to load the 2nd diagnostic program.*"); //输出引用的附加的说明文字$display("*\”test3;\“to load the Fibonacci program.*"); //输出引用的附加的说明文字endendtasktask test1;begintest=0;disable MONITOR;$readmemb("test1.pro",t_rom.memory);//从文件中读取数据到存储器中$display("rom loaded successfully!"); //输出引用的附加的说明文字$readmemb("test1.dat",t_ram.ram);//从文件中读取数据到存储器中$display("ram loaded successfully!"); //输出引用的附加的说明文字#1 test=1;#14800;sys_reset;endendtasktask test2;begintest=0;disable MONITOR;$readmemb("test2.pro",t_rom.memory);//从文件中读取数据到存储器中$display("rom loaded successfully!"); //输出引用的附加的说明文字$readmemb("test2.dat",t_ram.ram);//从文件中读取数据到存储器中$display("ram loaded successfully!"); //输出引用的附加的说明文字#1 test=2;#11600;sys_reset;endendtasktask test3;begintest=0;disable MONITOR;$readmemb("test3.pro",t_rom.memory);//从文件中读取数据到存储器中$display("rom loaded successfully!"); //输出引用的附加的说明文字$readmemb("test3.dat",t_ram.ram);//从文件中读取数据到存储器中$display("ram loaded successfully!"); //输出引用的附加的说明文字#1 test=3;#94000;sys_reset;endendtasktask sys_reset;beginreset_req=0;#(`PERIOD*0.7)reset_req=1;#(1.5*`PERIOD)reset_req=0;endendtaskalways @(test)//test触发begin:MONITORcase(test)1:begin$display("\n***RUNNING CUPtest1 - The Basic CPU Diagnostic Program ***"); //输出引用的附加的说明文字$display("\n TIME PC INSTR ADDR DATA"); //输出引用的附加的说明文字$display("--------------------"); //输出引用的附加的说明文字while(test==1) //当test为1时@(t_cpu.pc_addr)if((t_cpu.pc_addr%2==1)&&(t_cpu.fetch==1)) //如果t_cpu.pc_addr%2为1并且t_cpu.fetch==为1begin#60 PC_addr<=t_cpu.pc_addr-1; //非阻塞赋值IR_addr<=t_cpu.ir_addr; //非阻塞赋值#340 $strobe("%t %h %s %h %h",$time,PC_addr,mnemonic,IR_addr,data);//选通任务($strobe)要推迟到当前时阶结束时进行endend2:begin$display("\n***RUNNING CUPtest2 - The Basic CPU Diagnostic Program ***"); //输出引用的附加的说明文字$display("\n TIME PC INSTR ADDR DATA"); //输出引用的附加的说明文字$display("--------------------"); //输出引用的附加的说明文字while(test==2) //当test为2时@(t_cpu.pc_addr)if((t_cpu.pc_addr%2==1)&&(t_cpu.fetch==1)) //如果t_cpu.pc_addr%2为1并且t_cpu.fetch==为begin#60 PC_addr<=t_cpu.pc_addr-1; //非阻塞赋值IR_addr<=t_cpu.ir_addr; //非阻塞赋值#340 $strobe("%t %h %s %h %h",$time,PC_addr,mnemonic,IR_addr,data);//选通任务($strobe)要推迟到当前时阶结束时进行endend3:begin$display("\n***RUNNING CUPtest3 - The Basic CPU Diagnostic Program ***"); //输出引用的附加的说明文字$display("\n TIME PC INSTR ADDR DATA"); //输出引用的附加的说明文字$display("--------------------"); //输出引用的附加的说明文字while(test==3) //当test为3时beginwait(t_cpu.opcode!==3'h1)$strobe("%t %d",$time,t_ram.ram[10'h2]);//选通任务($strobe)要推迟到当前时阶结束时进行wait(t_cpu.opcode!=3'h1);endendendcaseendalways @(posedge halt) //当halt改变时触发模块begin#500$display("\n********************"); //输出引用的附加的说明文字$display("** A HALT INSTRUCTION WAS PROCESSED **"); //输出引用的附加的说明文字$display("********************\n"); //输出引用的附加的说明文字endalways#(`PERIOD/2)clock=~clock;always@(t_cpu.opcode) //当t_cpu.opcode改变时触发模块case(t_cpu.opcode)3'b000:mnemonic="HALT";3'h1:mnemonic="SKZ";3'h2:mnemonic="ADD";3'h3:mnemonic="AND";3'h4:mnemonic="XOR";3'h5:mnemonic="LDA";3'h6:mnemonic="STO";3'h7:mnemonic="JMP";default:mnemonic="";endcaseEndmodule-------------------------cpu.v-------------------------`timescale 1ns/1nsmodule cpu(clk,reset,halt,rd,wr,addr,data,opcode,fetch,ir_addr,pc_addr); //定义CPU模块input clk,reset; //输入变量为clk,resetoutput rd,wr,halt; //输出变量为rd,wr,haltoutput[12:0]addr; //13位输出变量addroutput[2:0]opcode; //3位输出变量opcodeoutput fetch; //输出变量fetchoutput [12:0]ir_addr,pc_addr; //定义13位输出变量inout[7:0]data; //8位输入变量datawire clk,reset,halt; //定义wire型变量wire[7:0] data; //定义wire型变量wire[12:0] addr; //定义wire型变量wire rd,wr; //定义wire型变量wire fetch,alu_ena; //定义wire型变量wire[2:0]opcode; //定义wire型变量wire[12:0]ir_addr,pc_addr; //定义wire型变量wire[7:0]alu_out,accum; //定义wire型变量wire zero,inc_pc,load_acc,load_pc,load_ir,data_ena,contr_ena; //定义wire型变量clk_gen m_clk_gen(.clk(clk),.reset(rest),.fetch(fetch),.alu_ena(alu_ena));register m_reister(.data(data),.ena(load_ir),.rst(reset), .clk(clk),.opc_iraddr({opcode,ir_addr})); accum m_accum(.data(alu_out),.ena(load_acc),.clk(clk),.rst(reset),.accum(accum));alum_alu(.data(data),.accum(accum),.clk(clk),.alu_ena(aln_ena),.opcode(opcode),.alu_out(alu_o ut),.zero(zero));machinectl m_machinectl(.clk(clk),.rst(reset),.fetch(fetch),.ena(control_ena));machinem_machine(.inc_pc(inc_pc),.load_acc(load_acc),.load_pc(load_pc),.rd(rd),.wr(wr),.load_i r(load_ir),.clk(clk),.datactl_ena(data_ena),.halt(halt),.zero(zero),.ena(contr_ena),.opcode(opcode) );datactl m_datactl (.in(alu_out),.data_ena(data_ena),.data(data));adr m_adr(.fetch(fetch),.ir_addr(ir_addr),.pc_addr(pc_addr),.addr(addr));counterm_counter (.clock(inc_pc),.rst(reset),.ir_addr(ir_addr),.load(load_pc),.pc_addr(pc_addr)); endmodule五.实验结果如图所示状态图:六.实验结论以上的报告文件中,揭示了综合器对综合过程和结果的分析,有及其重要意义。

相关主题