Verilog语言教程逻辑及语法部分_第1页
Verilog语言教程逻辑及语法部分_第2页
Verilog语言教程逻辑及语法部分_第3页
Verilog语言教程逻辑及语法部分_第4页
Verilog语言教程逻辑及语法部分_第5页
已阅读5页,还剩209页未读 继续免费阅读

下载本文档

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

文档简介

1、Verilog 语言教程逻辑及语法,数字系统设计的核心知识,复杂数字系统的构成; 基本电路和 Verilog 的对应关系; 同步有限状态机在电路中的作用; 时钟树与自动综合技术,数字逻辑电路的构成,- 组合逻辑:输出只是输入逻辑电平的函数(有延时),与电路的原始状态无关。 时序逻辑:输出不只是输入的逻辑电平的函数,还与电路所处的状态有关。 同步时序逻辑是在同一时钟跳变节拍的前提下,如输入条件满足,则进入下一状态,否则仍留在原来的状态的状态机。,数字逻辑电路的构成,组合逻辑:由与、或、非门组成的网络。常用的有:多路器、数据通路开关、加法器、乘法器等,没有记忆功能。 时序逻辑: 由多个触发器和多个

2、组合逻辑块组成的网络。常用的有:计数器、复杂的数据流动控制逻辑、运算控制逻辑、指令分析和操作控制逻辑。同步时序逻辑的设计是设计复杂的数字逻辑系统的核心。 存储器和寄存器:用于暂时存储数据信息。,组合逻辑举例之一一个八位数据通路控制器,define ON 1 b 1 define OFF 1 b 0 wire ControlSwitch; wire 7:0 out, in; assign out = (ControlSwith= ON) ? in : 8 h00,一个八位数据通路控制器的波形:,带寄存器的八位数据通路控制器的波形,带寄存器的八位数据通路控制器的Verilog描述,define O

3、N 1 b 1 define OFF 1 b 0 wire ControlSwitch; wire clock wire 7:0 out, in; always (posedge clock) if (ControlSwith= ON) out = in ; else out = out;,带复位端和使能端的寄存器,module regena (clock,ena,reset,R,Q); parameter n=8; input n-1:0 R; input clock, ena reset; output n-1:0 Q; always (posedge clock or negedge r

4、eset) if (!reset) Q=0; else if (ena) Q=R; endmodule,ena,R,clock,D,Q,Q,reset,具有并行置数和使能控制输入的移位寄存器,具有并行置数和使能控制输入的移位寄存器,module shiftregs(R,load,ena,w,clock,Q,reset); input 3:0 R; input w, load, ena, reset, clock; output 3:0 Q; reg 3:0 Q; integer k; always(posedge clock or negedge reset) if (!reset) Q =0

5、; else if (load) Q=R; else if (ena) begin Q0 = W; for (k=1; k4; k+1) Qk =Qk-1; end endmodule,组合逻辑举例之二:一个八位三态数据通路控制器,define ON 1 b 1 define OFF 1 b 0 wire LinkBusSwitch; wire 7:0 outbuf; inout 7:0 bus; assign bus = (LinkBusSwitch= ON) ? outbuf : 8 hzz,.,.,八位三态数据通路控制器的波形:,静态随机存储器(SRAM),Sel信号必须维持一定时间,直

6、到经过两个反向器传递过来的Data信号可以自动保持; Data的驱动能力必须大于小反向器的驱动能力; 用的三极管很少,可以把密度做得很高。,静态随机存储器(SRAM)阵列,地址译码和SRAM块的读写,Data output,开关逻辑应用举例寄存器间数据流动的控制开关,开关逻辑应用举例寄存器间数据流动的控制开关,开关逻辑的时延问题控制数据运算和流动的开关的开启和关闭时序.,全局时钟网和平衡树结构,避免冒险和竞争,由于组合逻辑和布线的延迟引起,避免冒险和竞争与流水线,组合逻辑和布线的延迟在组合逻辑中的叠加,为什么要设计有限状态机?,如果能严格以时钟跳变沿为前提,按排好时时序,来操作逻辑系统中每一个

7、开关Si,则系统中数据的流动和处理会按同一时钟节拍有序地进行,可以控制冒险和竞争现象对逻辑运算的破坏,时延问题就能有效地加以解决。 利用同步有限状态机就能产生复杂的以时钟跳变沿为前提的同步时序逻辑,并提供操作逻辑系统的开关阵列所需要的复杂控制时序(具有信号互锁和先后次序等要求的)。,为什么要设计有限状态机?,如果我们能设计这样一个电路: 1)能记住自己目前所处的状态 ; 2)状态的变化只可能在同一个时钟的跳变沿时刻发生,而不可能发生在任意时刻; 3)在时钟跳变沿时刻,如输入条件满足,则进入下一状态,并记住自己目前所处的状态,否则仍保留原来的状态; 4)在进入不同的状态时刻,对系统的开关阵列做开

8、启或关闭的操作。,为什么要设计有限状态机?,clock,10ns,S2,开,关,S1,t,t,t,Sn,S3,t,t,t,S4,为什么要设计有限状态机?,有了以上电路,我们就不难设计出复杂的控制序列来操纵数字系统的控制开关阵列。能达到以上要求的电路就是时序和组合电路互相结合的产物:同步有限状态机和由状态和时钟共同控制的开关逻辑阵列。 我们只要掌握有限状态机的基本设计方法,加上对基本电路的掌握,再加上对数据处理的过程的细致了解,我们就可以避免由于逻辑器件和布线延迟产生的冒险竞争现象所造成的破坏,设计出符合要求的复杂数字逻辑系统。,数字系统的构成示意图,同步有限状态机的设计,什么是有限状态机( F

9、SM ) FSM的种类和不同点 设计举例,什么是有限状态机?,- 有限状态机是由寄存器组和组合逻辑构成的 硬件时序电路; - 其状态(即由寄存器组的1和0的组合状态所 构成的有限个状态)只能在同一时钟跳变沿 的 情况下才能从一个状态转向另一个状态; - 究竟转向哪一状态不但取决于各个输入值, 还取决于当前状态。 - 状态机可用于产生在时钟跳变沿时刻开关的 复杂的控制逻辑,是数字逻辑的控制核心。,Mealy 状态机下一个状态 = F(当前状态,输入信号); 输出信号 = G(当前状态,输入信号);,图1 . 时钟同步的状态机结构 (Mealy 状态机),Moor 状态机下一个状态 = F(当前状

10、态,输入信号)输出信号 = G(当前状态);,带流水线输出的 Mealy 状态机下一个状态 = F(当前状态,输入信号); 输出信号 = G(当前状态,输入信号);,输出,简单的状态机设计举例,状态转移图表示 RTL级可综合的 Verilog 模块表示,有限状态机的图形表示,图形表示:状态、转移、条件和逻辑开关,图3.4 状态转移图,有限状态机的Verilog描述,定义模块名和输入输出端口; 定义输入、输出变量或寄存器; 定义时钟和复位信号; 定义状态变量和状态寄存器; 用时钟沿触发的always块表示状态转移过程; 在复位信号有效时给状态寄存器赋初始值; 描述状态的转换过程:符合条件,从一个

11、状态到另外一个状态,否则留在原状态; 验证状态转移的正确性,必须完整和全面。,表示方法之一,module fsm (Clock, Reset, A, K2, K1); input Clock, Reset, A; /定义时钟、复位和输入信号 output K2, K1; /定义输出控制信号的端口 reg K2, K1; /定义输出控制信号的寄存器 reg 1:0 state ; /定义状态寄存器 parameter Idle = 2b00, Start = 2b01, Stop = 2b10, Clear = 2b11; /定义状态变量参数值 always (posedge Clock) if

12、 (!Reset) begin /定义复位后的初始状态和输出值 state = Idle; K2=0; K1=0; end,表示方法之一(续),else case (state) Idle: begin if (A) begin state = Start; K1=0; end else state = Idle; end Start: begin if (!A) state = Stop; else state = Start; end,表示方法之一(续),Stop: begin /符合条件进入新状态,否则留在原状态 if (A) begin state = Clear; K2= 1; en

13、d else state = Stop; end Clear: begin if (!A) begin state = Idle; K2=0; K1=1; end else state = Clear; end endcase endmodule,表示方法之二,我们还可以用另一个 Verilog HDL模型来表示同一个有限状态, 见下例。(用可综合的Verilog模块设计用独热码表示状态的状态机) module fsm (Clock, Reset, A, K2, K1); input Clock, Reset, A; output K2, K1; reg K2, K1; reg 3:0 sta

14、te ; parameter Idle = 4b1000, Start = 4b0100, Stop = 4b0010, Clear = 4b0001;,表示方法之二(续),always (posedge clock) if (!Reset) begin state = Idle; K2=0; K1=0; end else case (state) Idle: if (A) begin state = Start; K1=0; end else state = Idle;,表示方法之二(续),Start: if (!A) state = Stop; else state = Start; St

15、op: if (A) begin state = Clear; K2= 1; end else state = Stop; Clear: if (!A) begin state =Idle; K2=0; K1=1; end else state = Clear;,表示方法之二(续),default: state = Idle; endcase endmodule 例2与例1的主要不同点是状态编码,例2采用了独热编码,而例1则采用Gray码,究竟采用哪一种编码好要看具体情况而定。,表示方法之三,在比较复杂的状态机设计过程中,我们往往把状态的变化与输出开关的控制分成两部分来考虑。就象前面讲过的Me

16、aly状态机输出部分的组合逻辑。为了调试方便,还常常把每一个输出开关写成一个个独立的always组合块。在调试多输出状态机时,这样做比较容易发现问题和改正模块编写中出现的问题。建议同学们在设计复杂的多输出状态机时采用下面的风格举例,说明如下:,表示方法之三(续),module fsm (Clock, Reset, A, K2, K1); input Clock, Reset, A; output K2, K1; reg K2, K1; reg 1:0 state, nextstate ; parameter Idle = 2b00, Start = 2b01, Stop = 2b10, Cle

17、ar = 2b11;,表示方法之三(续),/- 每一个时钟沿产生一次可能的状态变化- always (posedge Clock) begin if (!Reset) state = Idle; else state = nextstate; end /-,表示方法之三(续),/- 产生下一状态的组合逻辑 - always (state or A) case (state) Idle: if (A) nextstate = Start; else nextstate = Idle; Start: if (!A) nextstate = Stop; else nextstate = Start;

18、 Stop: if (A) nextstate = Clear; else nextstate = Stop; Clear: if (!A) nextstate = Idle; else nextstate = Clear; default: nextstate =2bxx; endcase,表示方法之三(续),/- 产生输出K1的组合逻辑 - always (state or Reset or A) if (!Reset) K1=0; else if (state = Clear /- endmodule,表示方法之四用输出指定的码表示状态的状态机,方法四采用了另一种方法:直接把状态码定义为

19、输出。也就是把状态码的指定与状态机控制的输出联系起来,把状态的变化直接用作输出,这样做可以提高输出信号的开关速度并节省电路器件。这种设计方法常用在高速状态机中。建议同学们在设计高速状态机时采用方法四的风格。例中state3 和state0分别表示前面两个例子中的输出K2和K1。,表示方法之四(续),module fsm (Clock, Reset, A, K2, K1, state); input Clock, Reset, A; output K2, K1; output 4:0 state; reg 4:0 state ; assign K2= state4; / 把状态变量的最高位用作输

20、出K2 assign K1= state0; / 把状态变量的最低位用作输出K1,表示方法之四(续),parameter /-output coded state assignment - /- K2_i_j_n_K1 Idle = 5b0_0_0_0_0, Start = 5b0_0_0_1_0, Stop = 5b0_0_1_0_0, StopToClear = 5b1_1_0_0_0, Clear = 5b0_1_0_1_0, ClearToIdle = 5b0_0_1_1_1;,表示方法之四(续),always (posedge Clock) if (!Reset) begin sta

21、te = Idle; end else case (state) Idle : if (A) state = Start; else state = Idle; Start: if (!A) state = Stop; else state = Start;,表示方法之四(续),Stop: if (A) state = StopToClear; else state = Stop; StopToClear: state = Clear; Clear: if (!A) state = ClearToIdle; else state = Clear; ClearToIdle: state = Id

22、le; default: state = Idle; endcase endmodule,状态机的测试,不同风格的描述适合不同规模的状态机和不同的综合工具,有的风格查错和修改较容易,但写简单的状态机时比较麻烦。Synopsys公司的综合器建议使用这种风格来描述状态机。 上面四个例子是同一个状态机的四种不同的Verilog HDL模型,它们都是可综合的,在设计复杂程度不同的状态机时有它们各自的优势。如用不同的综合器对这四个例子进行综合,综合出的逻辑电路可能会有些不同,但逻辑功能是相同的。下面列出测试这些不同风格状态机的测试模块,供同学们参考:,状态机的测试模块,timescale 1ns/1ns

23、 module t; reg a; reg clock,rst; wire k2,k1; initial / initial常用于仿真时信号的给出。 begin a=0; rst = 1; /给复位信号变量赋初始值 clock = 0; /给时钟变量赋初始值 #22 rst = 0; /使复位信号有效 #133 rst = 1; /经过一个多周期后使复位信号无效 end,状态机的测试模块,always #50 clock = clock; /产生周期性的时钟 always (posedge clock) /在每次时钟正跳变沿时刻产生不同的a begin #30 a = $random%2; /

24、 每次a是 0还是1是随机的。 #(3*50+12); / a 的值维持一段时间 end initial begin #100000 $stop; end /系统任务,暂停仿真以便观察仿真波形。 /- 调用被测试模块t.m - fsm m(.Clock(clock), .Reset(rst),.A(a),.K2(k2),.K1(k1); endmodule,状态机设计的总结:,有限状态机设计的一般步骤: 1)逻辑抽象,得出状态转换图 2)状态化简 3)状态分配 在触发器资源丰富的FPGA或ASIC设计中采用独热编码(one-hot-coding)既可以使电路性能得到保证又可充分利用其触发器数量

25、多的优势,也可以采取输出编码的状态指定来简化电路结构,并提高状态机的运行速度。 4) 选定触发器的类型并求出状态方程、驱动方程和输出方程。 5)按照方程得出逻辑图,状态机设计的总结:,用Verilog HDL来描述有限状态机,可以充分发挥硬件描述语言的抽象建模能力,使用always块语句和case(if)等条件语句及赋值语句即可方便地实现。具体的逻辑化简及逻辑电路到触发器映射均可由计算机自动完成,上述设计步骤中的第2步及4、5步不再需要很多的人为干预,使电路设计工作得到简化,效率也有很大的提高。,逻辑电路的测试,故障模型 测试集合的复杂性 路径的激活 树状结构的电路 随机测试 时序电路的测试

26、电路内部自测试(Build-in Self-Test) 线路板的测试,逻辑电路的测试故障模型,信号无法变化的模型 信号 w 总是固定在0 或 1: stuck_at_0 表示为:w/0 stuck_at_1 表示为:w/1 单个故障和多个故障 把多个故障问题简化为许多个单个故障问题来处理。 CMOS电路的故障特点 晶体三极管的开路或短路:stuck_at_0 或stuck_at_1 复杂的情形,不定态;组合逻辑变为时序逻辑的行为.,逻辑电路的测试测试集合的复杂性,想要知道模块中 a,b,c,d,f 端中是否有电平不能变化的,需要测试信号w1,w2,w3的各种变化组合。最全的情况有8种,最少有四

27、种: 测试集合=001,010,011,100,逻辑电路的测试测试路径的激活(Sensitizing),把w1端的变化直接传到f端,必须把w2置1,w3置0,w4置1。这叫做从w1到f的路径被激活。,逻辑电路的测试树状结构的电路,最小测试集合的确定比较麻烦,扫描路径的安排,电路内部自测试(Build-in Self-Test),在芯片中必须存储有对测试向量的正确响应,经过比较知道被测试电路是否有故障。,测试向量,被测试电路,测试结果处理,x0,Pm-1,P0,Xn-1,四位内部逻辑块观察器Built-in Logic Block Observer (BILBO),M1 M2 的不同组合产生不同

28、的功能,sin,xor,四位内部逻辑块观察器(BILBO)的M1 M2 的不同组合时不同的功能,M1M2=11,正常系统模式,p0到p3直接传递到q0到q3; M1M2=00,当G/S=1时,为移位寄存器模式,测试矢量一位一位地移动进入,给被测试电路一位一位地加上测试信号。当G/S=0时,电路成为二进制伪随机序列发生器。(xor 的两个为输入端相同时,输出为0,否则为1) M1M2=10,为签字模式,p0到p3与寄存器中存储的数比较后,得到签字输出q0到q3,相同为0,不同出现1。 M1M2=01,复位模式,所有触发器置0。,签字分析,分五个步骤完成签字分析过程:,签字分析的五个步骤,把测试向

29、量一位一位地输入BILBO1,复位 BILBO2。 用BILBO1做伪随机序列信号源,用BILBO2产生签字分析结果。 把BILBO2的内容逐位输出,在外面比较签字分析;然后逐位向BILBO2输入CN2的测试向量,启动测试;把BILBO1 中的寄存器复位。 用BILBO2做伪随机序列信号源,用BILBO1产生签字分析结果。 把BILBO1的内容逐位输出,在外面比较签字分析。,边界扫描,电路的可测试性:可以施加测试向量,并可观察输出结果。 电路的可测试性包括:芯片的可测试、线路板可测试、系统可测试。 用移位寄存器的方法,把测试向量逐位移入寄存器,把测试结果逐位移出寄存器,与EDA仿真工具的结果进

30、行比较,分析真实的物理线路是否运行正常。 这个方法非常普及。已经建立有关边界扫描的国际标准:IEEE Standard 1149.1. 设计线路板、芯片都要符合国际标准。有自动化工具在芯片设计的过程中(功能逻辑设计结束后)插入有关 DFT(Design For Test)设计。,有关测试的总结,小规模的电路可以进行全覆盖测试来验证它的功能。 组合逻辑可以根据真值表来测试。 时序逻辑可以根据状态转移表来测试。 如果电路是根据上面介绍的可测试性来设计的,则小规模的电路进行完整的测试是比较容易的。 大规模电路无法进行全覆盖的穷举测试,因为测试向量数量太大,必须动脑筋想办法找到可管理的有效测试集合,以

31、节省测试时间。 EDA工具对于得到设计电路的测试集是有帮助的,但是并不能确定电路的功能确实完全符合设计初衷。,语法要点详细讲解,有关测试模块编写的语法 ; 语法的高级部分: 函数、任务、文件、存贮器建立模型、 双向总线、UDP、综合指令。,语法详细讲解 Verilog测试模块的编写,目的: 复习如何编写较复杂的测试文件,对所做的设计 进行完整的测试和验证。 掌握组织模块测试的常用方法;学会编写常用的 测试代码。,语法详细讲解 用Verilog设计的步骤,注:虚线表示编译器能检查输入文件的可读性和是否存在以及是否允许生成输出文件,include 文件,设计文件,厂家元件 库文件,输入文件:激励和

32、期望的输出信号,输出文件:激励和实际输出的信号,编译器,仿真器,仿真器,语法详细讲解 测试平台的组成,激励 信号,需要验证的 设计,激励信号 和用于验 证的结果 数据,需要验证的 设计,简单的测试平台,复杂的测试平台,语法详细讲解 并行块,在测试块中常用到forkjoin块。用并行块能表示以同一个时间起点算起的多个事 件的运行,并行地执行复杂的过程结构,如循环或任务。举例说明如下: module inline_tb; reg 7:0 data_bus; initial fork data_bus= 8b00; #10 data_bus = 8h45; /这两个repeat开始执行时间不同,但能

33、同时运行 #20 repeat (10) #10 data_bus = data_bus +1; #25 repeat (5) # 20 data_bus = data_bus 1; #140 data_bua = 8h0f; join endmodule,语法详细讲解并行块,时间 data_bus 0 8b0000_0000 10 8b0100_0101 30 8b0100_0110 40 8b0100_0111 45 8b1000_1110 50 8b1000_1111 60 8b1001_0000 65 8b0010_0000 70 8b0010_0001,时间 data_bus 80

34、8b0010_0010 85 8b0100_0100 90 8b0100_0101 100 8b0010_0001 105 8b0100_0110 110 8b1000_1100 120 8b1000_1110 125 8b0001_1100 140 8b0000_1111,上面模块的仿真输出如下:,语法详细讲解强制激励,在一个过程块中,可以用两种不同的方式对信号变量或表达式进行连续赋值。 过程连续赋值往往是不可以综合的,通常用在测试模块中。 两种方式都有各自配套的命令来停止赋值过程。 两种不同方式均不允许赋值语句间的时间控制。 assign和deassign 适用于对寄存器类型的信号 (例如

35、:RTL级上的节点或测试模块中在多个地方被赋值的信号)进行赋值。 initial begin #10 assign top.dut.fsml.state_reg = init_state;,#20 deassign top.dut.fsml.state_reg; end force 和 release 用于寄存器类型和网络连接类型(例如:门级扫描寄存器的输出)的强制赋值,强制改写其它地方的赋值。 initial begin # 10 force top.dut.counter.scan_reg.q=0; # 20 release top.dut.counter.scan_reg.q; end

36、在以上两个例子中,在10到20 这个时间段内,网络或寄存器类型的信号被强制赋值,而别处对该变量的赋值均无效。 force的赋值优先级高于assign。 如果先使用assign,再使用force对同一信号赋值,则信号的值为force所赋 的值,,语法详细讲解强制激励,语法详细讲解强制激励,当执行release后,则信号的值为assign所赋 的值。 如果用force对同一个信号赋了几次值,再执行release,则所有赋的值均不再存在。 可以对信号的某(确定)位、某些(确定)位或拼接的信号,使用force和release赋值;但不能对信号的可变位使用force和release 来赋值。 不能对寄存

37、器类型的信号某位或某些位使用 assign 和deassign 来赋值。,虽然有时在设计中会包含时钟,但时钟通常用在测试模块中。下面 三个例子分别说明如何在门级和行为级建立不同波形的时钟模型。 例1 简单的对称方波时钟:,reg clk; always begin #period/2 clk=0; #period/2 clk=1; end,reg go; wire clk; nand #(period/2) ul (clk,clk,go); initial begin go=0; #(period/2) go=1; end,注:在有些仿真器中,如果设计所用的时钟是由与其相同抽象级别的时钟模型产

38、生的,则仿真器的性能就能得到提高。,语法详细讲解建立时钟,例2简单的带延迟的对称方波时钟:,语法详细讲解建立时钟,reg clk; initial begin clk=0; #(period) forever #(period/2) clk=!clk end,reg go; wire clk; nand #(period/2) ul (clk,clk,go); initial begin go=0; #(period) go=1; end,注:这两个时钟模型有些不同,行为描述的模型延迟期间一直是低电平,而门级描述的模型开始延迟有半个周期是不确定的。,例3. 带延迟、头一个脉冲不规则的、占空比不

39、为1的时钟:,reg clk; initial begin #(period+1) clk=1; #(period/2-1) forever begin #(period/4) clk=0; #(3*period/4) clk=1; end end,reg go; wire clk; nand #(3*period/4,period/4) ul (clk,clk,go); initial begin #(period/4+1) go=0; #(5*period/4-1) go=1; end,注:这两个时钟模型也有些不同,行为描述的模型一开始就有确定的电平,而门级描述的模型有延迟, 开始时电平是

40、不确定的。,语法详细讲解建立时钟,例2简单的带延迟的对称方波时钟:,语法详细讲解建立时钟,reg clk; initial begin clk=0; #(period) forever #(period/2) clk=!clk end,reg go; wire clk; nand #(period/2) ul (clk,clk,go); initial begin go=0; #(period) go=1; end,注:这两个时钟模型有些不同,行为描述的模型延迟期间一直是低电平,而门级描述的模型开始延迟有半个周期是不确定的。,语法详细讲解怎样使用任务,举例说明如何使用任务: module bu

41、s_ctrl_tb; reg 7:0 data; reg data_valid, data_rd; cpu ul(data_valid,data,data_rd); initial begin cpu_driver (8b0000_0000); cpu_driver (8b1010_1010); cpu_driver (8b0101_0101); end,语法详细讲解怎样使用任务,task cpu_driver; input 7:0 data_in; begin #30 data_valid =1; wait (data_rd = =1); #20 data = data_in; wait (

42、data_rd= =0); #20 data = 8hzz; #30 data_valid = 0; end endtask endmodule,语法详细讲解怎样使用任务,在测试模块中使用任务可以提高程序代码的效率,可以用任务把多次重复的操作包装起来。,语法详细讲解存储建模,目标 学会如何用Verilog对存储器建模。 学会如何用Verilog中对双向(即输入/输出)端口, (inout)建模。,存储器建模必须注意以下两个方面的问题: 声明存储器容量的大小。 明确对存储器访问操作的权限。 例如:指出可以对存储器做以下哪几种操作: 1)只读 2)读写 3)同步读写 4)多次读,同时进行一次写 5

43、)多次同步读写,同时提供一些方法保证一致性,语法详细讲解存储器建模,timescale 1ns/10ps module myrom(read_data,addr,read_en_); input read_en_; input 3:0 addr; output 3:0 read_data; reg 3:0 read_data; reg 3:0 mem 0:15; initial $readmemb(“my_rom_data”,mem); always (addr or read_en_) if(!read_en_) read_data=memaddr; endmodule,语法详细讲解简单 R

44、OM 建模,my_rom_data 0000 0101 1100 0011 1101 0010 0011 1111 1000 1001 1000 0001 1101 1010 0001 1101,ROM的数据存储在另外的一个独立的文件中,语法详细讲解简单ROM建模,上页所示的ROM模型说明: 如何在Verilog中用二维的寄存器组来定义存储器。 ROM中的数据保存在一个独立的文件中,如上页的右边的虚线方框所示。 这是一种保存ROM数据的通用的方法,它可以使数据和ROM模型分开。,语法详细讲解简单RAM建模,timescale 1ns/1ns module mymem(data,addr,rea

45、d,write); inout 3:0 data; inout 3:0 addr; input read, write; reg 3:0 memory 0:15; /4 bits, 16 个单元 /从存储器读出到总线上 assign data=read? memoryaddr:4bz; /从总线写入存储器 always (posedge write) memoryaddr=data; endmodule,语法详细讲解简单RAM建模,RAM模型比ROM模型稍微复杂: 它必须具有读写能力; 进行读写时通常使用相同的数据总线; 需要新技术来处理双向总线; 当读信号无效时,RAM模型与总线脱离,如果此

46、时写 信号也无效,总线无驱动源,则总线进入高阻状态, 这就避免了RAM中的读写竞争。 上页的 RAM 模块是可综合的,但综合出来是一大堆寄存器,占比较大的面积,经济上不太合算。,例: module scalable_ROM (mem_word, address); parameter addr_bits=8; /size of address bus parameter wordsize=8; /width of a word parameter words=(1addr_bits); /size of mem output wordsize:1 mem_word; /word of memo

47、ry input addr_bits:1 address; /address bus reg wordsize:1 mem 0 : words-1; /mem declaration /output one word of memory wire wordsize:1 mem_word=memaddress; endmodule,语法详细讲解存储量可变的只读存储器建模,语法详细讲解存储量可变的只读存储器建模,上述的例子演示了怎样通过设置字长和地址位数来编 写 只读存储器的行为模块。 注意 ! 在上例中,存储字的范围从0开始的,而不是从1开始,这是因为存储单元是直接通过地址线寻址定位的。 同样地

48、,也可以用下面的方法来定义存储器和寻址: reg wordsize:1 mem 1:words; /存储器地址 从1 开始 /地址一个一个地增加直到包含了每个地址对应的存储器 wire wordsize:1 mem_word = memaddress+1;,可以在初始化块中用一个循环或系统任务把初始数据存入存储器的每个单元。 使用循环把值赋给存储器数组。 for(i=0;imemsize;i=i+i) / initialize memory memai=wordsize1b1; 调用$readmem系统任务。 /从文件 mem_ 中, 把初始数据存入存储器(mem)的每个单元 $readmem

49、b(“mem_”,mem); 注意:上面两项必须写 在initial 块中,加载这些初始化数据不需要时间。,语法详细讲解存储器的加载,语法详细讲解怎样使用双向口,使用inout关键字声明端口为双向口。 inout 7:0 databus; 使用双向口必需遵循下面的规则: inout口只能声明为网络连接类型, 不允许把它声明为寄存器类型。(所以仿真器能确定多个驱动源的最终值。) 在设计中,每次只能从一个方向来驱动inout口。 例如:当使用总线读RAM中的数据时,如果同时又向RAM模型的双向数据总线写数据,就会产生逻辑竞争,导致总线数据无法确定。所以必须为inout口设计控制逻辑,只有这样才能保

50、证正确的操作。,语法详细讲解怎样使用双向口,注意: 声明一个inout口,可以用来输入或输出数据。inout口默认为网络连接类型。不允许在过程块(initial 或always块)中对网络连接类型的数据进行过程赋值;但可以在过程块外把一个寄存器数据类型通过连续赋值语句赋给它(inout口),或者把它与用户定义的源语(UDP)相连。 必须为inout口设计控制逻辑,用来保证正确的操作。当把inout口作为输入口时,必须通过控制逻辑禁止输出到inout口。,使用Verilog中的基本元件(bufif1)为双向口建模:,语法详细讲解双向口建模,语法详细讲解双向口建模,注意: 在上页的例子中,使用en

51、_a_b和en_b_a 来控制元器件bufifl,如果控制信号同时有效,则结果无法确定。 所以必须把控制信号 en_a_b 和 en_b_a 在时间上分开。,module bus_xcvr(bus_a,bus_b,en_a_b,en_b_a); inout bus_a,bus_b; input en_a_b,en_b_a; bufifl b1(bus_b,bus_a,en_a_b); bufifl b2(bus_a,bus_b,en_b_a); /结构模块逻辑 endmodule,当en_a_b=1时,元器件b1激活,bus_a的值传到bus_b上,当en_b_a=1时,元器件b1激活,bus

52、_b的值传到bus_a上,使用连续赋值为双向口建模:,语法详细讲解双向口建模,注意:在assign语句中,通过en_a_b和en_b_a控制bus_a与bus_b之间的数据交换。如果控制信号同时有效,则结果不能确定。所以必须把控制信号 en_a_b 和 en_b_a 在时间上分开。,语法详细讲解双向口建模,存储器的端口建模:,语法详细讲解双向口建模,注意: 上页中存储单元在wr的下降沿到达时存入数据。上页模块在 wr处于高电平时,通过数据总线写入数据,但必须保证wr的高电平维持时间长于数据的写入时间。 在rd处于高电平时,上述存储单元通过数据总线读出数据。由于此模型为单口存储模型,因此wr变低

53、电平时,rd不能同时为高电平,否则就无法确定存储器的读出/写入的结果。,语法详细讲解双向口建模,目标: 学会怎样定义或调用任务和函数。 学会怎样使用命名块。 学会怎样禁止命名块和任务。 理解有限状态机的作用,学会如何显式地为有限状态机建模。,语法详细讲解Verilog中的高级结构,通过把代码分成小的模块或者使用任务和函数,可把一项任务分成许多较小的、易于管理的部分,从而提高代码的可读性、可维护性和可重用性。 任务: 一般用于编写测试模块或者行为描述的模块。其中可以包含时间控制(如:# delays, , wait);也可以包含input, output 、inout 端口定义和参数;也可以调用

54、其他的任务或函数,语法详细讲解Verilog中的高级结构,函数: 一般用于计算,或者用来代替组合逻辑。 不能包含任何延迟;函数在零时间执行。 函数只有input变量,虽然没有output变量, 但可以通过函数名返回一个值。 可以调用其他的函数,但不可以调用任务,语法详细讲解Verilog中的高级结构,注意: 只能调用本模块内的任务和函数。 在任务和函数中不能声明网络连接类型的变量。 所有的输入和输出变量实际上都是本地寄存器 。 只有当任务或函数调用并执行完后,才能有返回值。 举例说明: 若任务或函数中包含一个forever循环时,永远无法执行完,就不可能有返回值。,语法详细讲解Verilog中

55、的高级结构,语法详细讲解Verilog 任务,下面模块中的任务含有定时控制和一个输入,并且引用了一个本模块的变量,但是没有输出,也没有双向总线和内部变量,不显示任何内容。 用于定时控制的信号,例如 clk,绝对不能作为任务的输入,这是因为输入值只向任务内部传递一次。 module top; reg clk, a, b; DUT u1(out, a, b, clk); always #5 clk=!clk;,语法详细讲解Verilog 任务,task neg_clocks; input 31:0 number_of_edges; repeat(number_of_edges) (negedge

56、clk); endtask initial begin clk=0; a=1; b=1; neg_clocks(3); /任务调用 a=0; neg_clocks(5); b=0; end endmodule,要点: 任务调用是通过在Verilog模块中写入任务名来实现的。 任务中可以包含input, output和inout端口变量的声明。 传递给任务的变量与任务I/O端口变量的声明次序相同。虽然传递给任务的变量名可以和任务内声明的I/O端口变量名相同,但是为了使任务成为一个独立的可共用的任务块,建议不要使用与任务内声明的I/O端口变量名相同的变量名,最好给传递到任务的变量起新的不同的名字。 在任务中可以使用时间控制。 任务使Verilog有更广阔的适用范围。 关键字disable可以用来禁止任务的执行。,语法详细讲解 Verilog 任务,注意: 不要在程序的不同部分同时调

温馨提示

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

评论

0/150

提交评论