1、第 5 章,单周期CPU及其Verilog HDL实现,学习指南,执行一条指令所需的硬件电路 与取指令有关有电路 寄存器计算类型指令执行所需的电路 立即数计算类型指令执行所需的电路 访问存储器类型指令执行所需的电路 条件转移类型指令执行所需的电路 跳转和子程序调用及返回类型指令执行所需的电路 寄存器堆设计 寄存器堆的硬件电路设计 结构描述风格的寄存器堆Verilog HDL代码 功能描述风格的寄存器堆Verilog HDL代码,数据路径设计 多路选择器的使用 单周期CPU的总体电路 单周期CPU的Verilog HDL代码 控制部件设计 控制部件的逻辑设计 控制部件的Verilog HDL代码
2、 存储器及测试程序设计 数据存储器设计 指令存储器及测试程序设计 单周期CPU测试结果及说明,处理器的工作过程简介,CPU的执行过程:首先将程序和数据输入计算机的存储器中,然后从主存中“程序入口(程序执行的第一条指令的地址)”开始依次取出指令和数据,并根据指令的要求对数据进行加工处理,得到需要的结果后,结束运行。 因此,控制器控制程序的执行过程实际上是控制指令的执行过程。,由于程序(指令序列)预先存放在存储器中,所以指令执行的过程分为取指令和执行指令,如下图。,假设程序和数据已经存放在主存中,执行指令执行步骤如下(要求记下来): 根据程序计数器PC的内容从主存中取出一条指令,放置于指令寄存器I
3、R中。 分析IR中的操作码,决定应执行的操作。 根据IR的地址码取出参加运算的操作数。 对操作数进行运算。 根据IR的地址码把运算结果存放指定地址。 本条指令执行完毕,修改PC内容决定下一条指令所在的地址。,目前的计算机都属于“同步”计算机。 同步计算机是指在计算机系统中有一个时钟(Clock),计算机所有的动作都 以这个时钟为基准。 如下图的单周期波形。,单周期CPU是指一条指令的执行在一个时钟周期内完成,然后开始下一条指令的执行,即一条指令用一个时钟周期。,5.1 执行一条指令所需的硬件电路,计算机的程序一般存在硬盘等辅存中。当计算机执行一个程序时,首先由操作系统把要执行的程序从硬盘调入内
4、存,然后CPU从内存读出指令开始执行。注意:前提是操作系统已经调入内存并运行。 设计CPU硬件电路的目的是使其能够从存储器中读取一条指令并执行指令所描述的操作,且这个过程是循环的,自动的。,注意 从存储器中读取指令的动作与指令本身的操作无关,所以可以对所有的指令以同样的方法从内存中取出。 执行指令则与指令本身的意义密切相关。 因此最重要的是首先要搞清楚CPU要执行的每一条指令的意义(功能)。 以第5章列出的20条整数指令为例来对每一条指令的执行进行说明。 指令格式寄存器、立即数、跳转等格式。 指令意义计算、访存、条件转移、无条件转移等类型。,5.1.1 与取指令有关的电路,CPU要执行指令,必
5、须先把它从存储器中读出来,然后才能知道指令究竟要干什么。 而一般程序是连续执行的,且存放在内存中也是连续存放的,所以读取并执行本条指令后,最有可能执行的是在本条件指令后的下一条指令,即地址+“1”条指令的长度。 注意:这里的“1”是指一条指令所占用的存储空间。 为了指出下一条指令的位置(地址),最简单的办法是设置一个计数器用来指定指令的位置。该计数器称为程序计数器PC(Program Counter)。,CPU取指令时是把PC的内容作为存储器地址,根据它来访问存储器,从指定的存储器单元中取出一条指令。 如果取出的指令执行时没有引起转移,则PC的值要+“1”。 如果转移,则要将目标地址写入PC,
6、以便在下一个时钟周期取出下一条指令。 下图是与取指令有关的电路。,字节,地址,PC+4,指令n,指令n+1,PC,地址,指令存储器 Inst Mem,说明: PC32位寄存器,由32个D触发器构成。 a是地址输入端。 do数据输出端,即指令。 加法器完成PC+4运算。 多路选择器用于选择地址之一。 为什么要PC+4? 因为这里假定指令的长度是固定的,即32位(个字节),所以每取一条指令后,PC都要加才能取互下一条指令。,不考虑转移时取指令的流程,取指令,start,Inst Mem-PC Read,PC-PC+4 Data out,5.1.2 寄存器计算类型指令执行时所需的电路,指令从存储器取
7、出来后,要进行分析,分析该指令的操作什么?操作数如何获取?等等。 根据设定的指令,可以画出分析指令类型的流程图如下。,分析指令类型的流程,取指令(已讲),分析指令类型,寄存器 算术逻辑,寄存器 移位,立即数 置高位、加法,立即数 逻辑运算,条件转移,无条件转移,下面分类来说明每类指令的执行过程及所需的电路。先说明寄存器计算类指令。 add,sub,and,or,xor这5条寄存器算术逻辑类型指令除了运算不同外,其他操作均相同。 sll,srl,sra寄存器移位类型指令除了移位方向不同外,其他操作均相同。,寄存器算术逻辑类型指令,寄存器算术逻辑类型指令格式从指令中可以看出,寄存器堆的数目为253
8、2个 所以rd,rt,rs是从这32个寄存器堆中选择一个。 功能:从寄存器堆中读出的2个数据(由rs,rt指定)分别被送到ALU的a和b的输入端,结果存入由rd指定的寄存器中。,寄存器算术逻辑运算类型指令执行流程,rd-rs op rt,start,Regfile-IR(rs) Regfile-IR(rt) Read,a-Regfile(rs) b-Regfile(rt),aluc-func,Regfile-IR(rd) d-alu write,表示将指令中的rs部分的代码送到寄存器堆,end,说明 Control Unit的输入信号是op和func,输出信号: ALU的操作控制码aluc 计
9、算结果是否写入寄存器堆的控制信号wreg 下一条指令的地址选择信号pcsource ALU结果写入的寄存器由rd指定。 有关Control Unit的具体设计将在后面描述。,寄存器移位类型指令,寄存器移位类型指令格式其中sa指定了移位的位数。 功能:把从寄存器rt中读出的32位数据进行左移或右移sa位后,结果写入由rd指定的寄存器。 移位的方向由func决定。,寄存器移位类型指令执行流程,start,Regfile-IR(rt) Read,a-IR(sa) b-Regfile(rt),aluc-func,Regfile-IR(rd) d-alu write,end,rd-rt shift sa
10、,执行寄存器移位类型指令所需的电路,由于sa只有5位,而a输入端是32位,所以把sa必须放在低位,高27位可以是任何数据。 将上面2个电路结合在一起,只需要在ALU的a输入端前加一个二选一的多路选择器即可。具体是选择qa还是sa,由取出来的指令确定。,5.1.3 立即数计算类型指令执行时所需的电路,指令格式包括addi,andi,ori,xori和lui,由op进行区分。 共同特点是ALU的操作数b来自于立即数。 由于立即数只有16位,所以需要扩展到32位(符号位扩展 or 零扩展)。,立即数计算类型指令执行流程,start,Regfile-IR(rs) Read,b-IR(imm,扩展) a
11、-Regfile(rs),aluc-decode(op),Regfile-IR(rt) d-alu write,end,rt-rs op imm(扩展) lui: rt-imm16,P C,+,a do Inst Mem,地址,4,0 1 2 3,Clock,指令,PC+4,pcsource,执行立即数计算类型指令所需的电路,Control Unit,op,rs,we rna qa rnb wn d qb,rt,rt,Regfile,a aluc ALUz b,aluc,wreg,imm,e,sext,从上面可以看出,b输入端为imm,再加上算术逻辑类型指令的输入,所以b输入端的前面也必须有一
12、个二选一的多路选择器。 符号扩展和零扩展是通过组件e来实现的。 sext=1,符号扩展。 sext=0,零扩展。 计算结果写入由rt指定的寄存器中。,5.1.4 访问存储器类型的指令执行时所需电路,访问存储器的指令格式有2条: 读指令(lw)-从数据存储器中读数据,写入由rt指定的寄存器中。 写指令(sw)-把rt寄存器的数据写入存储器中。 共同点是都要计算存储器地址。 操作数来源: 一个数是使用rs从寄存器堆中读出的。 另一个数是把指令中的16位立即数imm进行符号扩展得到。两个数相加是通过ALU完成的。,访问存储器类型指令执行的流程,start,Regfile-IR(rs) Read,b-
13、IR(imm,扩展) a-Regfile(rs),aluc-decode(op),Regfile-IR(rt) d-mem(addr) write,end,lw:rt-memory(rs +imm(扩展) sw: memory(rs +imm(扩展) - rt,Read,R/W,Write,mem(addr)-alu Read,mem(addr)-alu mem(d)- Regfile(rt) write,Regfile-IR(rt) Read,注意 由于这里讨论的是单周期CPU的设计,所以需要 2个分开的存储器模块,即指令存储器和数据存储器。 如果使用一个存储器模块且存储器模块只有一个访问端
14、口,就无法在一个时钟周期既读取指令,又访问数据。 这里暂且“认为”2个存储器模块是 2个Cache模块。,5.1.5 条件转移型指令执行时所需电路,指令格式条件转移指令这里只讲beq和bne,功能如下: beq-if(rs=rt) PC-pc+4+imm2(符号扩展) bne-if(rs!=rt) PC-pc+4+imm2(符号扩展) PC的来源有 2个: 一个是PC+“1”。 另一个是pc+4+imm2(符号扩展) 。 此时需要对PC的输入进行控制,即设置pcsource。 pcsource=00,pc-pc+“1” pcsource=01,pc-label,条件转移型指令执行流程,star
15、t,Regfile-IR(rs) Regfile-IR(rt) Read,b-Regfile(rs) a-Regfile(rt),aluc- decode(op) mux4x32-p4+imm2 (符号扩展),end,beq:if(rs=rt) pc-p4+imm2(符号扩展) bne:if(rs!=rt) pc-p4+imm2(符号扩展),y,z=1&beq|z=0&bne?,n,pcsource=01,pc-mux4x32,pcsource=00,用一个加法器完成 Imm符号扩展,用一个移位器完成,P C,+,a do Inst Mem,地址,4,0 1 2 3,Clock,指令,p4,p
16、csource,执行条件转移类型指令所需的电路,Control Unit,op,rs,we rna qa rnb wn d qb,rt,Regfile,a alucz ALU r b,aluc,wreg,imm,e,sext,z,+,5.1.6 跳转和子程序调用与返回类型指令执行时所需电路,无条件转移指令也能改变程序执行的流程,且是无条件的。 指令格式有3条 j指令功能: pc-p431:28,(address2)27:0 jal指令功能:r31-pc+8,pc-p431:28 ,(address2)27:0 jr指令功能: pc-rs,从上面分析可以看出,PC的来源又增加了二个: pc-p4
17、31:28,(address2)27:0 pc-rs 故pcsource又要赋予新的意义: pcsource=11:pc-p431:28,(address2)27:0 pcsource=10: pc-rs 下面画出每条指令的流程图,j指令执行流程,start,mux4x32-p431:28,(address2)27:0 pcsource=11,end,pc-p431:28,(address2)27:0,P C,+,a do Inst Mem,地址,4,0 1 2 3,Clock,指令,p4,pcsource,执行 j指令所需的电路,Control Unit,op,addr,4,28,32,ja
18、l指令执行流程,start,r31-pc+4 mux4x32-p431:28,(address2)27:0 pcsource=11,end,r31-pc+4 pc-p431:28,(address2)27:0,jr指令执行流程,start,Regfile-IR(rs) pcsource=11 Mux4x32-regfile(rs),end,pc-rs,5.2 寄存器堆设计,MIPS指令格式中的寄存器号(地址)有5位,所以共有32个寄存器。这些寄存器“堆在一起”构成一个寄存器堆(Register File)。 如何设计这个寄存器堆? 当然是根据前面指令的执行流程来设计,下面列表说明。,从寄存器堆
19、中读写数据个数一览表,从表中可以看出 读数端口最多需要2个。 写数端口最多需要1。 给出的寄存器地址最多需要3个。 r0=0。 此外还给出下列信号 清零信号clrn-低电平有效。 时钟信号clk-上升沿有效。 寄存器的写使能we-we=0,读;we=1,写。,寄存器堆的电路符号及各信号的意义如下图所示。,除r0=0外,每一个寄存器由32个D触发器构成,它包括数据端d,时钟信号clk,使能信号e,清零信号clrn(rst),输出信号q。 由于有32个寄存器可供选择,所以必须有一个5-32的译码器dec5e和一个32位的32选1的多路选择器mux32x32。 这里32个32位的寄存器堆的输出采用二
20、维数组来描述。 q31:031:0-最左边的31:0表示有32个寄存器,右边的31:0表示每个寄存器有32位。,5.2.3 功能描述风格的寄存器堆Verilog HDL代码,module regfile32x32(rna,rnb,d,wn,we,clk,clrn,qa,qb);parameter data_width=32;parameter addr_width=5;parameter r_number=32;input addr_width-1:0 rna,rnb,wn;input data_width-1:0 d;input we,clk,clrn;/ we=0,读;we=1,写outp
21、ut data_width-1:0 qa,qb;reg data_width-1:0 register1:r_number-1;integer i;/2 read portassign qa=(rna=0)?0:registerrna;assign qb=(rnb=0)?0:registerrnb;/1 write portalways (posedge clk or negedge clrn)if(clrn=0) for(i=0;i32;i=i+1) registeri=0;else if (wn!=0) endmodule,5.3 数据路径设计,CPU的电路包括 数据路径 or 数据通路(
22、Datapath) 控制部件(Control Unit) 本节介绍单周期CPU的总体数据路径,并给出代码。,5.3.1 多路选择器的使用,通过前面介绍的每一条指令执行时所需的硬件电路。有些部件的输入源不止一个,解决这种输入源冲突问题的办法是使用多路选择器。 从前面的电路图可以看出: rs是从regfile中取出数据,送入ALU的a输入端。 rt是从regfile中取出数据,送入ALU的b输入端。 结果是写入regfile中的wn指定的寄存器。 下面介绍使用多路选择器的情况和场合。,1、下一条指令地址的选择,控制信号pcsource 除程序不转移时下一条指令的地址是PC+4外,还有5条指令会引起
23、程序转移。 beq/bne rs,rt,label #ifpc-label jr rs #pc-rs j/jal address #pc-address*4 按理讲应该有6个输入,一个输出,即应该设计一个6选1的多路选择器。但是beq/bne和j/jal计算转移地址的方法是一样的,只需要控制好,可以减少为4个输入源。 具体情况如下表所示,下面的问题是如何形成pcsource? 根据前面的表格,可以得到如下pcsource形成的表格。 注:助记符为op的二进制代码相与为1。,P C,+,a do Inst Mem,地址,4,0 1 2 3,Clock,指令,p4,pcsource,下一条指令地址
24、选择(4个数据源),Control Unit,op,rs,we rna qa rnb wn d qb,rt,Regfile,a aluc z ALU r b,aluc,wreg,imm,e,sext,z,+,func,0:pc+4 1:BranchAddr 2:RegAddr 3:JumpAddr,addr,2、ALU的a输入端,控制信号shift 以下面2条寄存器操作指令为例说明。 add rd,rs,rt ;rd-rs+rt sll rd,rt,sa ;rd-rtsa 从上面的注释中可以看出,rd,rt是相同的,而rs,sa是不同的。 根据前面设计的ALU32可知,移位运算时,sa是从a输
25、入端输入,寄存器算术逻辑时a输入端输入1个数,故a输入端有2个数据源。而rt作为ALU的b输入端,两者皆可用。,因此使用了一个2选1的多路选择器从2个数据源中选择1个送到ALU的a输入端。 控制信号shift的设置如下。,3、ALU的b输入端和寄存器堆的wn输入端,以下面2条指令为例说明。 add rd,rs,rt ;rd-rs+rt addi rt,rs,imm ;rt-rs+imm(符号扩展) 从上面注释中可以看出, rs是相同的,送入ALU的a输入端。 add指令的rt数据要送到ALU的b输入端,addi指令的imm (符号扩展)也要送到ALU的b输入端,所以ALU的b输入端有2个数据源
26、。 另外寄存器堆的wn也有2个数据源 add指令的rd addi指令的rt,因此使用了一个2选1的多路选择器从2个数据源中选择1个送到ALU的b输入端。控制信号为aluimm。 使用了一个2选1的多路选择器从2个数据源中选择1个送到寄存器堆的wn端。控制信号为regrt。 控制信号aluimm和regrt的设置如下。,4、寄存器堆的d输入端,以下面3条指令为例说明。 add rd,rs,rt ; rd-rs+rt lw rt,offset(rs) ; rt-mem(rs+offset) jal address ; r31-pc+4,pc-address2 这里主要看写入寄存器堆: 数据来源-A
27、LU输出 or mem or pc+4 控制信号m2reg。 地址wn-rd,rt,r31(11111) 控制信号jal,实现 数据来源使用2个2选1的多路器从三个数据源中选出一个。多路选器的选择信号分别为m2reg和jal。 由于jal指令总是把返回地址写入r31(11111b),因此在电路中增加了一个小模块f,该模块的功能如下: assign wn=reg_dest 5jal 电路图如下。,P C,+,a do Inst Mem,4,0 1 2 3,Clock,p4,pcsource,寄存器堆输入端d的3个数据源,Control Unit,op,rs,we rna qa rnb Regfi
28、le wn qb d,rt,aaluc z ALU r b,aluc,wreg,sa,func,0 1,shift,rt,0 1,regrt,e,sext,imm,0 1,aluimm,rd,f,0 1,jal,we a do Data Mem di,wmem,0 1,m2reg,alu_b,alu_a,result,nextpc,pcplus4,npc,link,reg_wn,5.3.2 单周期CPU总体电路,综合以上讨论的各种情况,可以得到如下图所示的单周期CPU的总体电路。 该电路必须能够执行前面列出的20条指令。,pcplus4,br_adr,reg_wn,link,alu_a,alu
29、_b,nextpc,result,npc,offset,jpc,从概念上讲,CPU并不包括存储器。如果将指令存储器和数据存储器抽出来,并把CPU部分用一个器件符号表示,则可得到下图所示的结构。 最好称为单周期计算机(sc,Single cycle)。,5.3.3 单周期CPU的Verilog HDL代码,下面是单周期计算机的Verilog HDL代码。它调用 了: 单周期CPU模块sccpu_dataflow 指令存储器模块scinstmeme 数据存储器模块scdatameme 将在稍后讨论控制部分和存储器模块的设计方法,include “sccpu_dataflow.v“ module s
30、ccomp_dataflow(clock,resetn,inst,pc,aluout,memout,mem_clk);parameter width=32;input clock,resetn,mem_clk;output width-1:0 inst,pc,aluout,memout;wire width-1:0 data;wire wmem;sccpu_dataflow s(clock,resetn,inst,memout,pc,wmem,aluout,data);scinstmem imem(pc,inst);scdatamem dmem(clock,memout,data,aluout
31、,wmem,mem_clk,mem_clk); endmodule,单周期CPU模块的代码sccpu_dataflow.v,include “scinstmem.v“ include “scdatamem.v“ include “sccu_dataflow.v“ include “mux2x32.v“ include “dff32.v“ include “cla32.v“ include “mux2x5.v“ include “regfile32x32.v“ include “alu32.v“ module sccpu_dataflow(clock,resetn,inst,mem,pc,wme
32、m,alu,data);parameter width=32;input width-1:0 inst,mem;input clock,resetn;output width-1:0 pc,alu,data;output wmem;,wire width-1:0 p4,bpc,npc,adr,ra,alua,alub,res,alu_mem;wire 3:0 aluc;wire 4:0 reg_dest,wn;wire 1:0 pcsource;wire zero,wmem,wreg,regrt,m2reg,shift,aluimm,jal,sext,carry_out;wire width-
33、1:0 sa=27b0,inst10:6;wire width-1:0 offset=imm13:0,inst15:0,2b00;sccu_dataflow cu(inst31:26,inst5:0,zero,wmem,wreg,regrt,m2reg,aluc,shift,aluimm,pcsource,jal,sext);wire e=sext,dff32 ip(npc,clock,resetn, pc);cla32 pcplus4(pc,32h4,1b0,p4,carry_out);cla32 br_adr(p4,offset,1b0,adr,carry_out);wire width-
34、1:0 jpc=p431:28,inst25:0,2b00;mux2x32 alu_b(data,immediate,aluimm,alub);mux2x32 alu_a(ra,sa,shift,alua);mux2x32 result(alu,mem,m2reg,alu_mem);mux2x32 link(alu_mem,p4,jal,res);mux2x5 reg_wn(inst15:11,inst20:16,regrt,reg_dest);assign wn=reg_dest| 5jal;mux4x32 nextpc(p4,adr,ra,jpc,pcsource,npc);regfile
35、32x32 rf(inst25:21,inst20:16,res,wn,wreg,clock,resetn,ra,data);alu32 alu_unit(alua,alub,aluc,alu,zero); endmodule,5.4 控制部分设计,处理器CPU由运算部分(运算器)和控制部分(控制器)组成。 控制器向计算机中各个部件发出控制信号,指挥与协调各个部件工作,使数据沿指定的路径流动,从而完成整个指令的功能。 下面的问题是如何发出控制信号,如: pcsource jal 等等,5.4.1 控制部分的逻辑设计,首先根据指令中的6位操作码对指令进行译码,看是什么操作。 如果op=0,则需要
36、再检查6位的func。 如下表所示。,指令操作码一览表,根据上表可以得到以下典型指令的逻辑表达式(未化简,要保证逻辑表达式的值=1) r_type=op5&op4&op3&op2&op1&op0 i_add=r_type&func5&func4&func3&func2& func1&func0 i_sra=r_type&func5&func4&func3&func2& func1&func0 i_jr=r_type&func5&func4&func3&func2& func1&func0 i_xori= =op5&op4&op3&op2&op1&op0 i_sw=op5&op4&op3&op2
37、&op1&op0 i_beq=op5&op4&op3&op2&op1&op0 i_jal=op5&op4&op3&op2&op1&op0,加上i是为了防止与V_HDL语言的关键字冲突,下面开始重要的工作:确认每条指令执行时,控制信号应产生什么值。 根据前面分析每条指令的执行过程及所需电路,我们得到了10个控制信号。如下表所示。,然后现看一下哪些指令使用了上表中的信号。 根据前面指令执行的过程及所需电路,可以得到每条指令使用的信号如下表所示。 注:X为未使用。 仅列出add,sra,jr,xori,sw,beq,j,jal,其他指令暂未列出。,下面写出各个控制信号的逻辑表达式以wreg为例: w
38、reg=i_add | i_sra | i_xori | i_jal | ,单周期CPU控制部件是一个组合电路,所有的输出信号大致分为3类: 多路器的选择信号 写使能信号 ALU操作为控制信号 可以对逻辑表达式化简,但不是本课程的主要工作。,5.4.2 控制部件的Verilog HDL代码,module sccu_dataflow(op,func,z,wmem,wreg,regrt,m2reg,aluc,shift,aluimm,pcsource,jal,sext);input 5:0 op,func;input z;output wreg,regrt,jal,m2reg,shift,alui
39、mm,sext,wmem;output 3:0 aluc;output 1:0 pcsource;wire r_type=|op;wire i_add=r_type,wire i_addi=op5,assign wreg=i_add|i_sub|i_and|i_or|i_xor|i_sll|i_srl|i_sra|i_addi|i_andi|i_ori|i_xori|i_lw|i_lui|i_jal;assign regrt=i_addi|i_andi|i_ori|i_xori|i_lw|i_lui;assign jal=i_jal;assign m2reg=i_lw;assign shift
40、=i_sll|i_srl|i_sra;assign aluimm=i_addi|i_andi|i_ori|i_xori|i_lw|i_lui|i_sw;assign sext=i_addi|i_lw|i_sw|i_beq|i_bne;assign aluc3=i_sra;assign aluc2=i_sub|i_or|i_srl|i_sra|i_ori|i_lui;assign aluc1=i_xor|i_sll|i_srl|i_sra|i_xori|i_beq|i_bne|i_lui;assign aluc0=i_and|i_or|i_sll|i_srl|i_sra|i_andi|i_ori
41、;assign wmem=i_sw;assign pcsource1=i_jr|i_j|i_jal;assign pcsource0=i_beq endmodule,5.5 存储器及测试程序设计,5.5.1 数据存储器设计 采用使用数组来实现,数据及代码如下。,module scdatamem(clk,dataout,datain,addr,we,inclk,outclk);parameter data_width=32;parameter addr_width=32;input data_width-1:0 datain;input addr_width-1:0 addr;input clk
42、,we,inclk,outclk;output data_width-1:0 dataout;reg data_width-1:0 ram0:addr_width-1;integer i; assign dataout=ramaddr6:2;always (posedge clk) begin if(we) ramaddr6:2=datain; endinitial beginfor(i=0;i32;i=i+1) rami=0;ram5h14=32h000000a3;ram5h15=32h00000027;ram5h16=32h00000079;ram5h17=32h00000115;end
43、endmodule,书上错误,5.5.2 指令存储器及测试程序设计,module scinstmem(a,inst);parameter data_width=32;parameter inst_width=32;parameter addr_width=32;input addr_width-1:0 a;output inst_width-1:0 inst;wire data_width-1:0 rom 0:31;assign rom5h00=32h3c010000;/(00)main:lui r1,0assign rom5h01=32h34240050;/(04) ori r4,r1,80
44、assign rom5h02=32h20050004;/(08) addi r5,r0,4assign rom5h03=32h0c000018;/(0c)call:jal sumassign rom5h04=32hac820000;/(10) sw r2,0(r4)assign rom5h05=32h8c890000;/(14) lw r9,0(r4)assign rom5h06=32h01244022;/(18) sub r8,r9,r4assign rom5h07=32h20050003;/(1c) addi r5,r0,3,assign rom5h08=32h20a5ffff;/(20)
45、loop2:addi r5,r5,-1assign rom5h09=32h34a8ffff;/(24) ori r8,r5,0xffffassign rom5h0a=32h39085555;/(28) xori r8,r8,0x5555assign rom5h0b=32h2009ffff;/(2c) addi r9,r0,-1assign rom5h0c=32h312affff;/(30) andi r10,r9,0xffffassign rom5h0d=32h01493025;/(34) or r6,r10,r9assign rom5h0e=32h01494026;/(38) xor r8,
46、r10,r9assign rom5h0f=32h01463824;/(3c) and r7,r10,r6assign rom5h10=32h10a00001;/(40) beq r5,r0,shiftassign rom5h11=32h08000008;/(44) j loop2assign rom5h12=32h2005ffff;/(48)shift:addi r5,r0,-1assign rom5h13=32h000543c0;/(4c) sll r8,r5,15assign rom5h14=32h00084400;/(50) sll r8,r8,16assign rom5h15=32h0
47、0084403;/(54) sra r8,r8,16,assign rom5h16=32h000843c2;/(58) srl r8,r8,15assign rom5h17=32h08000017;/(5c)finish: j finish assign rom5h18=32h00004020;/(60)sum: add r8,r0,r0assign rom5h19=32h8c890000;/(64)loop:lw r9,0(r4)assign rom5h1a=32h20840004;/(68) addi r4,r4,4assign rom5h1b=32h01094020;/(6c) add r8,r8,r9assign rom5h1c=32h20a5ffff;/(70) addi r5,r5,-1assign rom5h1d=32h14a0fffb;/(74) bne r5,r0,loopassign rom5h1e=32h00081001;/(78) sll r2,r8,0assign rom5h1f=32h03e00008;/(7c) jr r31assign inst=roma6:2; endmodule,