? 任务能够包含定时控制,任务可在被调用后再经过一定时延才返回值;
? 任务调用语句是过程性语句,所以任务调用中的输出和输入输出参数必须是寄存器类
型的;
? 任务可以带有时序控制,或等待特定事件的发生。但是,输出参数的值直到任务退出
时才传递给调用参数。
实例应用:利用task和电平敏感的always块设计比较后重组信号的组合逻辑。可以看到,利用task非常方便地实现了数据之间的交换,如果要用函数实现相同的功能是非常复杂的;另外,task也避免了直接用一般语句来描述所引起的不易理解和综合时产生冗余逻辑等问题。
模块源代码:
//----------------- sort4.v ------------------ module sort4(ra,rb,rc,rd,a,b,c,d); output[3:0] ra,rb,rc,rd; input[3:0] a,b,c,d; reg[3:0] ra,rb,rc,rd; reg[3:0] va,vb,vc,vd; always @ (a or b or c or d) begin {va,vb,vc,vd}={a,b,c,d}; sort2(va,vc); //va 与vc互换。 sort2(vb,vd); //vb 与vd互换。 sort2(va,vb); //va 与vb互换。 sort2(vc,vd); //vc 与vd互换。 sort2(vb,vc); //vb 与vc互换。 {ra,rb,rc,rd}={va,vb,vc,vd}; end task sort2; inout[3:0] x,y; reg[3:0] tmp; if(x>y) begin tmp=x; //x与y变量的内容互换,要求顺序执行,所以采用阻塞赋值方式。 x=y; y=tmp; end endtask
endmodule
值得注意的是task中的变量定义与模块中的变量定义不尽相同,它们并不受输入输出类型的限制。如此例,x与y对于task sort2来说虽然是inout型,但实际上它们对应的是always块中变量,都是reg型变量。
测试模块源代码: `timescale 1ns/100ps `include \module task_Top;
reg[3:0] a,b,c,d;
wire[3:0] ra,rb,rc,rd;
2 6
initial begin a=0;b=0;c=0;d=0;
repeat(5) begin
#100 a ={$random}; b ={$random}; c ={$random}; d ={$random};
end #100 $stop;
sort4 sort4 (.a(a),.b(b),.c(c),.d(d), .ra(ra),.rb(rb),.rc(rc),.rd(rd));
endmodule
3,设计
1,设计一个带控制端的逻辑运算电路,分别完成正整数的平方、立方和阶乘的运算。编写测试模块,并给出仿真波形。
2,设计一个模块,通过任务完成3个8位2进制输入数据的冒泡排序。要求:时钟触发任务的执行,每个时钟周期完成一次数据交换的操作。
三、实验报告要求
1、简要描述Verilog HDL中任务和函数的区别和使用要点;
2、实验报告应包括Modelsim环境下仿真得到的波形和QuatusII环境下综合得到RTL级电路图; 3、实验报告应附硬件仿真的波形或显示的照片。
2 7
实验四 有限状态机(FSM)的设计 一 、实验目的
1、了解FSM的应用范围和两种类型的不同特点; 2、掌握FSM的电路结构和设计要点。
二、实验原理、内容及步骤
1、 FSM相关概念和设计要点
FSM适合于设计数字系统的控制模块。用Verilog HDL的case/if-else等语句能很好地描述基于状态机的设计。状态机可以认为是组合逻辑和时序逻辑的特殊组合。时序逻辑部分用于存贮状态,组合电路用于状态译码和产生输出信号。状态机的下一个状态不仅与输入信号有关,还与状态寄存器当前所处的状态有关。
状态机分为Mealy和Moore两种类型,前者的输出只是当前状态的函数,也就是状态的转换与输入信号无关,后者的输出则是当前状态和当前输入的函数,即状态的转换与输入信号有关。
状态机的表示方法:状态图、状态表和流程图。 状态机设计要点
? 一般采用同步时序方式,在时钟信号的触发下完成状态转移;
? 起始状态是指电路复位后所处的状态,选择一个合理的起始状态将使整个系统简洁、高效,
有的综合器会自动为状态机的设计选择一个最佳的起始状态; ? 状态编码的方式主要有二进制编码、格雷编码和一位热码编码等:
? 二进制编码(Binary State Machine):采用普通的二进制数代表每个状态,如4个状
态state0/state1/state2/state3对应编码为00/01/10/11。这种编码的缺点是相邻状态的转换有可能有多个比特发生变化(如01->10),瞬变次数多,容易产生毛刺,引起逻辑错误;
? 格雷编码(Gray Code State Machine): 4个状态state0/state1/state2/state3对应编
码为00/01/11/10即为格雷编码方式。格雷码节省逻辑单元,而且在状态的顺序转换中相邻状态每次只有一个比特发生变化,这样减少了瞬变的次数,也减少了产生毛刺和一些暂态的可能。
? 一位热码编码(One-Hot State Machine Encoding):采用n位来编码具有n个状态的
状态机 。如4个状态state0/state1/state2/state3对应编码为1000/0100/0010/0001。采用一位热码编码,虽然多用了触发器,但可以有效节省和简化组合电路。对于寄存器数量多而门逻辑相对缺乏的FPGA来说,采用一位热码编码可以有效地提高电路地速度和可靠性,也有利于提高器件资源的利用率。因此,对于FPGA器件,建议采用这种编码方式。采用这种编码会出现一些多余的状态,即一些无效的状态,需要增加default分支项,以便这些状态下能自动回到起始状态。
? 状态编码的定义可以用parameter或者`define语句。建议采用前者。尽量采用同步电路设
计;
`define state0 2’b00 //不要加分号 `define state1 2’b01 …. case (state)
`state0: …; //不能少“`”
2 8
….
? 状态转换一般使用case/casex/casez描述。Case语句比if-else语句更清晰明了。此外,
case语句的最后不要忘了default分支语句以避免锁存器的产生。 2、状态机设计实例
功能是检测一个5位二进制序列“10010”。考虑到序列重叠的可能,有限状态机共提供8个状态(包括初始状态IDLE)。
模块源代码: //seqdet.v
module seqdet(x,z,clk,rst,state);
input x,clk,rst; output z;
output[2:0] state; reg[2:0] state; wire z;
parameter IDLE='d0, A='d1, B='d2,C='d3, D='d4,E='d5, F='d6,G='d7;
assign z = ( state==E && x==0 )? 1 : 0; //当x=0时,状态已变为E, //状态为D时,x仍为1。因此
//输出为1的条件为( state==E && x==0 )。
always @(posedge clk)
if(!rst) begin state <= IDLE; end else casex(state) IDLE : if(x==1)
begin
state <= A; end A: if(x==0) begin state <= B; end B: if(x==0) begin state <= C; end else begin state <= F; end C: if(x==1) begin state <= D; end
2 9
else begin state <= G; end D: if(x==0) begin state <= E; end else begin state <= A; end E: if(x==0) begin state <= C; end else begin state <= A; end F: if(x==1) begin state <= A; end else begin state <= B; end G: if(x==1) begin state <= F; end default:state=IDLE; //缺省状态为初始状态。 endcase
endmodule
测试模块源代码:
//------------------ seqdet.v ------------------- `timescale 1ns/1ns `include \module seqdet_Top; reg clk,rst; reg[23:0] data; wire[2:0] state; wire z,x; assign x=data[23];
3 0