




已阅读5页,还剩49页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第9章 Verilog HDL语言 Verilog HDL是使用广泛的硬件描述语言,该语言的特点是 语言能力强,代码简单,有大量支持仿真的语句与可综合语句。 本章介绍该语言中的可综合语句描述数字电路与系统,重点介绍 该语言的基本语法、组合电路与时序电路的描述与实际描述举例 。 9.1 Verilog HDL语言基础 Verilog HDL语言以模块(module)的形式来描述数字电路,模块接口部分用来描 述与其他模块之间的连接,一般一个文件就是一个模块。模块的定义从关键词 module开始,到关键词endmodule结束,每条Verilog HDL语句以分号“;”作为 结束(块语句、endmodule等少数语句除外)。注释语句单行以“/”开头,多行以 “/*”开始、以“*/”结束。该语言很多规定与C语言相似。 【例9-1】 Verilog HDL描述与非门。 module NAND(in1,in2,out);/以module开头,随后是模块名和括号内的端口名列表,最后以 分 /号结束 input in1,in2; /定义端口类型,只有输入(input)、输出(output)和双向(inout)三种 output out; /凡是在端口列表的端口,都必须经过定义 /wire in1,in2,out; /由于in1、in2和out是1位宽连线类型,所以可以采用默认定义 ,此 /语句可省略 assign out=(in1 /连续赋值语句assign描述组合电路 /在Verilog中,还有initial叙述、always叙述、模块调用、门调用等 endmodule /关键字endmodule用于结束行,注意其后没有分号 9.1.1 Verilog HDL中的基本约定 1可用在描述语句中的逻辑状态 0表示逻辑0、逻辑非、低电平、假;1表示逻辑1、逻辑真、高电平、真。 x或X表示不确定的逻辑状态;z或Z表示高阻态。 2整数及其表示 整数可以按照简单十进制数格式或基数格式书写。 (1)简单十进制数格式 简单十进制数的整数表示与普通十进制数表示相同,例如,35、-46。 (2)基数格式 表示格式:+/- 其中:+/-是符号位;位宽就是数的等效二进制数的位数(bit),位宽用十进制数表 示;二进制的基数符号位b或B;八进制的基数符号是o或O;十进制的基数符号是d 或D,可默认不写基数符号;十六进制的基数符号是h或H。 一些规定: 数值中,左边是数值最高位(MSB),右边是最低有效位(LSB); 在二进制中,x、z只代表相应位的逻辑状态,x表示不定,z表示高阻; 当位宽默认时,位宽为32位。 例如:3b000是位宽为3的二进制数; res = 8b11111110是8位二进制数; 9o671是位宽为9的八进制数; 8h3f是位宽为8的十六进制数。 3标志符取名 标志符取名的规定:标志符必须是字母或下画线开头,长度小于1024;后续部分可以 是字母、数字或下画线;Verilog HDL中的标志符区分大小写。 例如,_bus,topp,BUS。 4系统命令 以$开头的标志符代表Verilog HDL中的命令(系统任务与系统函数),普通的标志符 不能以$开头。 5保留字 Verilog HDL语言内部已经使用的保留字,在Verilog HDL语言编辑器中,保留字以 醒目的颜色表示。 9.1.2 数据类型 Verilog HDL中的4种最基本数据类型是:整型(integer)、参数(parameter )型、寄存器(reg)类型和连线(wire)类型。 1连线类型 常用的连线类型关键字为wire。 连线类型的逻辑状态为0、1、x(任意)、z(高阻),连线类型主要用在模块的结 构描述中,对应硬件的物理信号连线,当用数字表示其逻辑值时,不存在符号位。 在用连线类型的信号时,必须用连线类型定义语句对信号进行类型说明,当说明被 省略时,表示位宽为1bit的wire型连线信号。wire是基本的、不附带其他功能的连 线,也是最常用的连线类型。 对于input,output和inout端口,若未指明数据类型,默认为连线类型。 连线类型定义格式: 矢量范围 , 连线名; 矢量范围以MSB:LSB格式描述。 例如:wire 0: 31 w1, w2; / w1和w2是32位连线类型,高位MSB为bit0 wir5e 7:0 tmp; /tmp为8位连线,高位MSB为bit7,低位LSB是位0 2寄存器类型 常用的寄存器类型的关键字为reg。 寄存器类型的信号,必须通过过程赋值语句进行赋值,只能出现在always后 面的过程语句中。 寄存器变量的定义格式: 矢量范围 ,寄存器名; 矢量范围以MSB:LSB格式描述。 例如:reg a; /a为寄存器类型 reg 3: 0 v; / v为4位寄存器类型 reg 7: 0 m, n; /m和n为8位寄存器类型 在Verilog HDL中,线宽为一位的连线和只有一位的寄存器变量称为标量;线宽 大于一位的连线和位宽大于一位的寄存器变量为矢量。 按位或部分位赋值的矢量称为标量类矢量,相当于多个一位标量的集合,标量类 矢量进行类型说明时,需要关键字scalared(可以默认)。 例如,reg scalared 7:0 reg_a;/reg_a被定义成标量类矢量 该说明可以默认关键字scalared,因此可以写成:reg 7:0 reg_a; 3端口信号与内部信号 信号可以分为端口信号和内部信号。出现在端口列表中的信号是端口信号,其 他的信号为内部信号。对于端口信号,输入端口只能是连线类型。输出端口可以是 连线(wire)类型,也可以是寄存器(register)类型。若输出端口在过程块中赋 值则为register类型;若在过程块外赋值,则为wire类型。 内部信号类型与输出端口相同,可以是连线(wire)类型或寄存器(register )类型。若在过程块(always叙述)中赋值,则为register类型;若在过程块外赋 值,则为wire类型。 端口类型只有输入(input)、输出(output)和双向(inout)三种,凡是在 端口列表中的端口,都必须定义端口类型。例如,“output6:0ag;”定义端口ag为 输出端口,“input3:0hex;”定义端口hex为输入端口。 4其他定义语句 (1)参数定义语句 参数定义语句经常用于对时延、线宽、寄存器位数等物理量的定义,其方法是用 一个文字参数来代替一个数字量,从而增加描述语句的可修改性。 参数定义的格式: parameter 其中参数定义部分给出具体的各个参数与数字之间的关系,各个关系之间用逗号 隔开。 例如:module module_name( ); parameter msb=7,lsb=0; /定义参数 regmsb:lsb reg_a; /使用参数 endmodule 9.1.3 运算符 1算术运算符 算术运算符包括加法、减法与乘法,例如a+b,a-b,a * b。有些综合工具不支持乘 法。 2位运算符 按位运算的运算符是位运算符,原来的操作数有几位,结果就有几位。若两个操作 数位数不同,则短的操作数左端会自动补0处理。位运算符为:按位取反 、按位与 assign z=pre /将pre assign mux=(s=0)? a: bz; (2)在定义连线类型时赋值 连续赋值可作为连线说明的一部分,成为连线说明赋值。 wire 3:0 sum=4b0; /将4b0赋给sum wire clear=b1; /将b1赋给clear 【例9-5】 描述一个数值比较器。 在Verilog HDL中,描述组合逻辑时常使用assign结构。源代码如下: module compare(equal,a,b); input a,b; output equal; assign equal=(a=b)?1:0; /a等于b时,equal输出为1;a不等于b时,equal 输出为0 endmodule 2Verilog HDL行为描述 (1)过程块 Verilog HDL对模块的行为描述以过程块为基本单位,一个模块的行为描述由 一个或多个并行运行的过程块组成。过程块格式如下: 过程语句 (事件控制敏感表) 块语句开始标志符:块名 块内局部变量说明; 一条或多条过程赋值或其他程序语句; 块语句结束标志符 过程语句就是指关键字always开始的语句,事件控制敏感表中的信号用于激活 过程语句的执行;块语句标志符为begin-end,块名和块内局部变量说明均为可选 项。 (2)过程语句always 如图9-1所示,always从时刻0开始执行,并循环重复执行后面的块语句。 always语句常带有触发(激活或敏感)条件,只有当触发条件满足时,块中的 语句才真正开始执行,若触发条件默认,则触发条件始终成立。 一个模块的行为描述中可以有多个always语句,这些语句之间相互独立,并行 运行。 3块语句 (1)串行块 串行块的标志符是begin-end,位于串行块中的语句按串行方式顺序执行。综合工具 支持串行块描述。 (2)串行块的行为描述可以形象地理解为硬件电路中,数据在时钟与控制信号的作 用下,沿数据通道的各级寄存器之间的传送过程。 例如,begin reg_a=reg_b; reg_c=reg_a; end 4过程赋值语句 Verilog HDL对模块的行为描述由一个或多个并行运行的过程块构成,而位于过程块 中赋值语句称为过程赋值语句。在过程赋值语句中表达式左边的信号必须是寄存器类 型(如reg类型);在过程赋值语句等式右边可以是任何有效的表达式,数据类型也 没有限制。如果一个信号没有声明则默认为wire类型,使用过程赋值语句给wire赋值 会产生错误。 过程赋值的基本格式是:= 例如:如果sum定义为寄存器信号,而carry为连线信号,则在always过程块中有: sum = a b cin ; /正确 carry = a /错误 (1)事件控制 事件控制以“”开头,后面紧跟的是事件敏感表 a)(信号名)。 其中信号名通常是一位标量,也可以是多位矢量,数据类型没有限制,其含义是只 有检测到信号名所确定的信号发生变化时,后面的赋值语句才能执行。 例如,(clock) reg_a=reg_b; /当时钟信号clock发生变化的时候,执行reg_a=reg_b b)(posedge 信号名)。 与前一情况相比,只关心信号上升沿(posedge)跳变的情况。 例如,(posedge clock) reg_a=reg_b; / 当时钟上升沿到来的时候,执行reg_a=reg_b c)(negedge 信号名)。 只关心信号下降沿(negedge)跳变的情况。 例如,(negedge clock) reg_a=reg_b; /当时钟下降沿到来的时候,执行reg_a=reg_b d)(敏感事件1 or 敏感事件2 or 敏感事件3 )。 在这个表达式中,敏感事件可以是上面、三类事件控制中的任一种,只要 所列举的任意一种情况发生,都将激活事件控制,各个敏感事件之间是“或”的关系 。 例如,(posedge reset or negedge clear) reg_out=0; always语句的敏感信号表中,注意敏感信号的动作类型应该一致, 例如: always (posedge clk or negedge rst_n) /正确,都是边沿动作。负沿可以代替低电平, /正沿可以代替高电平,这里rst_n为低电平有效 always (state or go or ws) /正确,都是电平动作 always ( posedge clk or go or ws) /不正确,有边沿和电平两类,动作类型不一致 (2)阻塞型过程赋值与非阻塞型过程赋值 等号赋值符“=”,在Verilog HDL中称为阻塞(blocking)型过程赋值符,该赋值 符的特点是它在串行块的执行过程中,前一条语句没有完成赋值过程之前,后面的 语句不能执行,阻塞的意义就是前一条语句阻塞了后面语句的执行。 非阻塞(non_blocking)赋值符“=”可以改变阻塞的情况,在串行块中,非阻塞 赋值符是并行执行的。 例如: 阻塞赋值:a=1;b=a;c=b;结果是a、b、c都等于1,相当于图9-2所示的组合逻辑电 路。 非阻塞赋值:a=1;b=a;c=b; 则a等于1,b是a的老值,c是b的老值,相当于图9 -3所示的寄存器电路。 图9-2 阻塞型赋值示意图 图9-3 非阻塞型示意图 【例9-6】 如果实现图9-4所示的逻辑图,必须在过程块中使用阻塞型赋值语句 ,程序如下: module blocking(a,b,c,x,y); /a、b和c是输入,x、y是输出 input a,b,c; output x,y; reg x,y; always (a or b or c) begin x=a /阻塞赋值 y=x|c; end endmodule 【例9-7】 对于图9-5所示的电路,必须在过程块中使用非阻塞型赋值语句, 程序如下: module demo1 (reg_a,reg_b,d,clock); /该例相当于两个寄存 器串联 input d,clock; output reg_a,reg_b; reg reg_a,reg_b; always (posedge clock) /时钟上升沿动作 begin reg_a=d; / reg_a的输入为d reg_b=reg_a; / reg_b的输出为 reg_a的老值 end endmodule (3)连续赋值语句与过程赋值语句的区别 Verilog HDL语言中的过程赋值语句与连续赋值语句之间的区别如下。 赋值对象不同:连续赋值语句用于连线类型信号,过程赋值语句用于寄存器 类型信号。 赋值语句的实现过程不同:连线信号一旦被连续赋值语句赋值后,赋值语句 右端表达式中的信号有任何变化,都将反映到左端的连线变量中;过程赋值语 句只有在执行时才有效。 语句的位置不同:连续赋值语句不能出现在过程块中;而过程赋值语句只能 出现在过程块中。 语句结构不同:连续赋值语句以assign开头;而过程赋值不需要先导字。 9.3 Verilog HDL语言中的分支语句 1if-else语句 (1)if(条件表达式) 块语句 当条件表达式成立时,执行后面的块语句,否则不执行。 (2)if(条件表达式) 块语句1 else 块语句2 当条件表达式成立时,执行块语句1,否则执行块语句2。 (3)if(条件表达式) 块语句1 else if (条件表达式) 块语句2 else if (条件表达式) 块语句n else (条件表达式) 块语句n+1 if-else 语句可以嵌套使用,使用方法同C语言,注意else与最近的if搭配。 2case语句 语句格式: case(敏感表达式) 值1:块语句1 值2:块语句2 值n:块语句n default: 块语句n+1 Endcase if语句、case语句必须在always块中使用,assign语句不能在always块中使用。 if语句中,关系表达式之间应该用逻辑运算符( input h, g, f, e, d, c, b, a; /编码器输入信号,可以是按钮信号, 高电平有效 output out2, out1, out0; /编码器输出信号 output none_on; /有编码输出信号 reg 3:0 out; assign none_on, out2, out1, out0 = out; /连接运算 always (a or b or c or d or e or f or g or h) /always过程块,敏感信号中没有边 沿描述关键字 begin if (h) outvec = 4b0111; /使用如果语句,如果h为1,则输出out等于 4b0111 else if (g) out = 4b0110; else if (f) out = 4b0101; else if (e) out = 4b0100; else if (d) out = 4b0011; else if (c) out = 4b0010; else if (b) out = 4b0001; else if (a) out = 4b0000; else out = 4b1000; end endmodule 2连续赋值语句实现组合电路 使用连续赋值语句assign需要注意: 连续赋值的信号型式一定是连线wire型。 使用assign关键字,格式是 assign 被赋值的连线变量=表达式; 只要等式右侧的值发生改变时,就会重新对左侧被赋值变量进行赋值。 所有输出(output)和输入(input)端口都默认为连线类型,不需要特别 的连线类型声明。 【例9-9】 Verilog HDL描述8线-3线编码器例2。 module encoder(none_on, out2, out1, out0, h, g, f, e, d, c, b, a); input h, g, f, e, d, c, b, a; output none_on, out2, out1, out0; wire 3:0 out;/定义out为内部 连线信号 assign out = h ? 4b0111: g ? 4b0110: f ? 4b0101: e ? 4b0100: d ? 4b0011: c ? 4b0010: b ? 4b0001: a ? 4b0000: 4b1000; /条件操作符 assign none_on = out3; /正在编码信号,用于编码器级联 assign out2 = out2; assign out1 = out1; assign out0 = out0; endmodule 9.6 Verilog HDL语言描述时序电路 时序逻辑是具有状态记忆的电路,其输出不仅依赖于当前的输入,而且依赖于以前 的状态。可以使用always块和连续赋值assign语句实现时序电路。 1使用always块实现触发器 只要在always块敏感信号表中定义有效的时钟沿,然后使用非阻塞过程赋值语句 对信号赋值,就可以实现触发器或寄存器了。需要注意的是在always块中的过程 赋值语句只能对reg型的信号进行赋值。 【例9-10】 Verilog HDL描述D触发器。 module dff(q,a,b,clk ); /q是输出,a、b是输入,clk是时钟信号 output q; input a,b,clk; reg q; always (posedge clk) /时钟clk的上升沿是敏感信号 begin q=a | b; /D触发器的驱动方程是a|b,这里使用非阻塞型赋值语 句 end endmodule 2使用连续赋值语句实现电平敏感的触发器 在Verilog HDL中实现电平敏感的触发器最好使用连续赋值语句assign。 【例9-11】 Verilog HDL连续赋值语句描述电平敏感的同步触发器。 module latch(q,a,b,clk ); /q是输出,a、b是输入,clk是时钟信 号 output q; input a,b,clk; assign q=clk ? (a|b) : q; /连续赋值语句 endmodule 3使用always块实现电平敏感的触发器 always块同样能实现电平敏感的触发器。 【例9-12】 Verilog HDL中的always块实现电平敏感的触发器。 module lat2(q,a,b,clk ); /q是输出,a、b是输入,clk是时钟信号 output q; input a,b,clk; reg q; always (clk or a or b) begin if (clk) q= a | b; end endmodule 4置位与清零 异步置位与清零的触发器中,置位与清零信号的作用与时钟信号无关;同步置位与 清零的触发器中,置位与清零信号的作用一定等到时钟的有效边沿出现时起作用。 (1)异步置位与清零 异步置位(set)与清零(reset)的触发器描述,always块中的敏感信号应该为: always (时钟边沿关键字 时钟信号 or 时钟边沿关键字 置位信号 or 时钟边沿关 键字 复位信号) 其中对于高电平有效的置位和清零信号,使用的时钟边沿关键字是posedge;而对 于低电平有效的置位和清零信号,应该使用的时钟边沿关键字是negedge。 对于高电平置位和清零的D触发器,一般有如下格式: always (posedge clk or posedge set or posedge reset) /上升沿时钟,高电 平置位与复位 begin if (reset) begin /*置位输出为0*/ end else if (set) begin /*置位输出为1*/ end else begin /*时钟边沿执行的逻辑*/ end end (2)同步置位与清零 对于同步置位与清零的触发器,其置位和清零信号是在时钟信号的有效沿发挥作 用的,描述这些触发器的always块的敏感信号只有时钟,但是在块内总是首先 检查置位和清零信号。对于高电平置位清零的同步触发器,有如下格式: always ( posedge clk) /敏感信号表中只有时钟沿 begin if (reset) begin /* 触发器清零*/ end else if (set) begin /* 触发器置位*/ end else begin /* 时钟逻辑*/ end end 9.7 Verilog HDL语言描述状态机 Verilog HDL中常用always块和case语句描述状态机。状态机描述一般可分为 次态逻辑、输出逻辑和状态寄存器三部分。 1状态机描述 Verilog中需要定义寄存器变量,并进行状态编码。 定义寄存器变量分现态与次态,例如: reg 1:0 state,next_state;/定义位宽为2的寄存器信号state和 next_state 使用参数语句定义状态编码,例如: parameter s0 = 2b00,s1 = 2b01, s2 = 2b10, s3 = 2b11;/只能用1个参数语 句定义状态编码 使用always语句描述状态寄存器的状态转换,例如: always (posedge clk) /描述状态寄存器的always块,在时钟的 上升沿 begin state =next_state; end /实现从现态到次态的状态转换 使用always语句、case语句描述次态逻辑。 使用always语句或是连续赋值语句assign描述输出。 或者使用always语句、case语句描述输出与次态逻辑,先描述输出,再描 述次态逻辑。 2Verilog HDL描述状态机时应该注意的约定 每一个模块只描述一个状态机。 在组合always块的顶部(case语句前)可给出次态的初始值,还可给输出赋 初值。一旦在case语句前给输出赋初值,则在各状态下,可只对不同于初值的输 出赋值。 若是输出未赋过初值,则应该在各状态对所有输出信号赋值。若只对部分输出信 号赋值,则在仿真时,有些状态下输出信号为任意值。 状态转移描述,要把向其他状态转移的条件与保持在自己状态的条件同时写清 楚。 一般情况下,还应该给状态机设置一个异步或是同步复位引脚,以便在任何情 况下可以把状态机复位到初始状态。在复位或是在某些条件下,所有状态都向初 始状态转移的情况,可以在状态寄存always块中处理。 例如,按钮key在低电平时,从所有状态返回状态s0,则可以写成如下: always (posedge clk or negedge key) begin if(!key) state=s0; /描述key=0时,返回初始状态s0的语句 else state=next_state; /否则,从现态转到次态 end 3状态机描述例题 下面举例说明如何描述状态机的这三个部分。 【例9-13】 试用Verilog HDL描述图9-6所示的4状态摩尔状态机,该状态机有一 个输入信号x和一个输出信号z。 第1种描述:次态逻辑、输出逻辑使用一个always块描述,状态寄存器单独使 用一个always描述的例子。Verilog HDL描述如下: module fsm1(clk,x,z); input x,clk; output z; reg z; reg 1:0 state,next_state; /定义寄存器类型 的状态变量 parameter s0 = 2b00,s1 = 2b01, s2 = 2b10, s3 = 2b11; /用参数语句描述 状态编码 always (posedge clk) /描述状态寄存器的 always块 begin state =next_state; end /实现状态转换 always (state or x) /次态逻辑和输出逻辑 always块 begin case (state) s0: begin z=1; /状态s0,先描述 输出z=1 if (!x) begin next_state =s1; end /再描述次态逻辑 else begin next_state =s0; end end s1: begin z=0; /状态s1 if (x) begin next_state =s2; end else begin next_state =s1; end end s2: begin z=0; /状态s2 if (!x) begin next_state =s3; end else begin next_state =s2; end end s3: begin z=1; /状态s3 if (x) begin next_state =s0; end else begin next_state =s3; end end endcase end Endmodule 该例使用了两个always块,将次态逻辑、输出逻辑与状态寄存器分开描述,采用 Max+Plus II软件,可以得到该例的仿真结果如图9-7所示,可以看出输出的变化与 状态变化同时发生。 第2种描述:分别使用三个always块描述次态逻辑、输出逻辑和状态寄存器的 例子。该描述的Verilog HDL源程序如下。 module fsm2(clk,x,z); /clk是时钟。x是输入,z是输出 input x,clk; output z; reg z; reg 1:0 state,next_state; /定义寄存器类型的状态变量 parameter s0 = 2b00,s1 = 2b01, s2 = 2b10,s3 = 2b11; /用参数语句描述 状态编码 always (posedge clk) /描述状态寄存器always块 begin state =next_state; end /实现状态转移 always (state or x) /描述次态逻辑的always块 begin case (state) s0: begin /状态s0 if (!x) begin next_state =s1;end else begin next_state =s0;end end s1: begin /状态s1 if (x) begin next_state =s2;end else begin next_state =s1;end end s2: begin /状态s2 if (!x) begin next_state =s3;end else begin next_state =s2;end end s3: begin /状态s3 if (x) begin next_state =s0;end else begin next_state =s3; end end endcase end always (state) /描述输出逻辑的always块 begin if (state=s0) | (state=s3) z = 1; else z = 0; end Endmodule 该例的仿真结果也如图9-7所示。 第3种描述:该例采用状态为独一编码的次态逻辑、状态寄存器和输出逻辑,分 三个always块描述。 module fsm3(clk,x,z); input x,clk; output z; reg z; reg 2:0 state,next_state; /初始状态的编码应该与复位、上电后的触发 器状态一致 parameter s0 = 4b000,s1 = 4b001,s2 = 4b010,s3 = 4b100; /参数语句描 述独一编码 always (posedge clk) /状态寄存器的always块描述 begin state =next_state; end always (state or x) /次态逻辑的always块 begin case (state) s0: begin /S0状态 if (!x) begin next_state =s1; end else begin next_state =s0; end end s1: begin /S1状态 if (x) begin next_state =s2; end else begin next_state =s1; end end s2: begin /S2状态 if (!x) begin next_state =s3; end else begin next_state =s2; end end s3: begin /S3状态 if (x) begin next_state =s0; end else begin next_state =s3; end end default: next_state =s0; endcase end always (state) /描述输出逻辑的always块 begin if (state=s0) | (state=s3) z = 1; else z = 0; end Endmodule 该例的仿真结果如图9-8所示。从仿真结果可知除了状态编码发生了变化,输出z的波形 与前例的一样。 【例9-14】 Verilog HDL描述图9-9(a)所示的状态机。该状态机的框图如图9-9(b )所示。该状态机的信号如下: 低电平有效异步复位信号rst_n,时钟信号clk。 两个输入信号:运行信号go和等待信号ws。 两个输出信号:读信号rd、选通信号ds。 当复位信号为0,进入IDLE状态;若go信号为1,则进入读状态READ,这时读信号 rd=1,选通信号ds=0;随后进入延时状态DLY,若是等待信号ws=1,则在READ状 态与DLY状态之间交换,若是ws=0,则进入状态DONE,使ds=1后返回IDLE状态。 该状态机用于控制CPU读存储器的过程,在go=1时,输出rd=1,进入读存储器状态 ,但是由于存储器速度慢,需要等待若干个CPU周期,当等待周期数未到ws=1,则 等待;当等待周期数到后ws=0,使读选通信号ds=1后结束读操作。 如下采用两个always块描述该状态机,其中一个always块采用非阻塞赋值,另一 个always块采用阻塞赋值。 module first ( rd, ds, go, ws, clk, rst_n); output rd, ds; input go, ws, clk, rst_n; reg rd, ds; parameter IDLE = 2b00, READ = 2b01, DLY = 2b11, DONE = 2b10; /状态编 码 reg 1:0 state, next; always (posedge clk or negedge rst_n) /状态寄存器always块,该块采用 非阻塞赋值 if (!rst_n) state = IDLE; else state = next; always (state or go or ws) /次态逻辑与输出always块,该块采用阻塞 赋值 begin next = bx; /设置初始次态为任意 rd = 1b0; /设置输出rd初始状态 ds = 1b0; /设置输出ds初始状态 case (state) IDLE : if (go) next = READ; /空闲状态 else next = IDLE; READ : begin /读状态 rd = 1b1;/由于在case语句前已经有了输出赋值,则这里只对变化 /的输出赋值 next = DLY; end DLY : begin /延时状态 rd = 1b1; if (!ws) next = DONE; else next = READ; end DONE : begin /完成状态 ds = 1b1; next = IDLE; /返回空闲状态 end endcase end Endmodule 该状态机的仿真结果如图9-10所示。 【例9-15】 某控制器在按钮a按下后,控制信号y1输出高电平21s,然后输出低 电平5s,再输出高电平25s。任何时候当按钮b为低电平时,将返回初始状态。 该题的控制器框图如图9-11所示。状态图如图9-12所示。 该例题的状态机Verilog HDL描述如下,状态机的仿真如图9-13所示。 module state ( a,b,t, db1, db2, clk, td,state_out,y1); /state_out输出状 态编码 output t, db1,db2,state_out,y1; input clk, a,b,td; reg3:0 db1,db2; reg t,y1; reg 2:0 state, next,state_out; /parameter s0 =2b00, s1 =2b01, s2 = 2b10, s3 =2b11; parameter s0 =0, s1 =1, s2 = 2, s3 =3,s4=4,s5=5; /采用十进制数字描述 状态编码 always (posedge clk or negedge b ) /状态寄存器描述 if(!b) state=s0; /任何时候,b=0时,返回状态s0 else state = next; always (state or a or td) /输出与次态逻辑 begin case (state ) s0: begin t = 1b0; db1 = 4b0001; db2=4b0010;y1=0; if (!a) next = s1; else next = s0; end s1: begin t = 1b1; db1 = 4b0001; db2=4b0010; y1=1; if (td) next = s2; else next = s1; end s2: begin t = 1b0; db1 = 4b0101; db2=4b0000; y1=0; next = s3; end s3: begin t = 1b1; db1 = 4b0101; db2=4b0000; y1=0; if(td) next = s4; else next = s3; end s4: begin t = 1b0; db1 = 4b0101; db2=4b0010; y1=0; next = s5; end s5: begin t = 1b1; db1 = 4b0101; db2=4b0010; y1=1; if(td) next = s0; else next = s5; end default : next = s0; endcase state_out=state; end endmodule 采用具有可变预置数的99进制计数器作为定时器。输入t=0时置数,输入t=1时计 数,计数值归零时,输出td=1。 module jishu10b(clk,t,td,qq1,qq2,db1,db2); input t,clk,db1,db2; /db1是预置数低位,db2是预置数高位 output td; output 3:0 qq1,qq2; wire 3:0 qq1,qq2,db1,db2; reg tds; /定义信号 reg 3:0 qq11,qq22; /定义信号 always (posedge clk or negedge t) begin if (t=0) begin qq11=db1; qq22=db2;tds=0; end /t=0时,计数器预置数 ,tds赋初值 else if(!tds)
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 智能采矿能源回收利用创新创业项目商业计划书
- 小白菜品牌化包装创新创业项目商业计划书
- 坚果风味糖果创新创业项目商业计划书
- 企业职工健身房设备更新维护计划
- 特发性震颤临床诊疗标准流程
- 交通管理智能化系统方案设计
- 2025-2030骨科手术机器人操作培训体系构建与市场教育策略报告
- 2025-2030风电齿轮箱技术可靠性提升与运维成本控制研究
- 2025-2030风电叶片回收利用技术路径与循环经济模式报告
- 2025-2030非病毒载体基因递送系统技术突破与知识产权布局分析
- 墩柱安全教育培训课件
- 新版中华民族共同体概论课件第十五讲新时代与中华民族共同体建设(2012- )-2025年版
- 卫生监督协管五项制度范文(4篇)
- 2025中国低压电能质量市场白皮书
- 2025年全国《家庭教育指导师》考试模拟试题(附答案)
- 航空安全培训计划课件
- 电瓶搬运车安全培训课件
- 数据保护与安全知识培训课件
- 情报共享平台架构-洞察及研究
- 棉纱库存管理办法
- 2024~2025学年人教版小学四年级数学上册第一单元检测试卷(含答案)
评论
0/150
提交评论