verilog testbench 写法

verilog testbench 写法
verilog testbench 写法

Verilog测试平台(testbench)技术(一) 收藏

对设计进行功能仿真和时序仿真时,需要给待测模块提供激励输入。对于由Verilog语言描述的设计模块,最好的方法自然同样是用Verilog语言对待测模块施加激励和检测模块的输出响应。实际应用中,Verilog测试平台(testben ch)就是用来提供上述功能的。Verilog测试平台是一个例化的待测(MUT)Verilog 模块,给它施加激励并观测其输出。由于测试平台是用Verilog语言描述的,因此可以应用到不同的仿真环境中。待测模块和与之对应的测试平台组成一个仿真模型,应用这个模型可以在不同的测试环境中用相同的激励对待测模块进行调试。下面就对不同电路类型分别介绍verilog测试平台的语言结构。

一、测试平台

1.组合电路测试

设计组合电路的测试平台时,待测模块及其功能决定了激烈的选择与测试次数。

对于一个已有的待测模块,测试平台中需要声明与待测模块输入输出端口对应的变量。与输入端口相连接的变量定义为reg,与输出端口相连接的变量定义为wire,例化时将测试平台中声明的变量与待测模块的输入输出端口相关联。使用initial语句控制程序运行,initial语句是一种过程结构,在initial块中可使用延迟控制语句来控制initial块中的程序流动。

这里对一个简单的算术逻辑单元(ALU)为例进行测试,下面是该单元Verilog 描述。

/***************************************************************** ********/

//多动能ALU的Verilog代码

'timescale 1ns/100ps

module alu_4bit(a,b,f,oe,y,p,ov,a_gt_b,a_eg_b,a_lt_b);

input [3:0] a,b;

input [1:0] f;

input oe;

input [3:0] y;

output p,ov,a_gt_b,a_eg_b,a_lt_b; reg [4:0] im_y;

always @(a or b or f)

begin

ov=1'b0;

im_y=0;

case(f)

2'b00:

begin

im_y=a+b;

if(im_y>5'b01111)

ov=1'b1;

end

2'b01:

begin

im_y=a-b;

if(im_y>5'b01111)

ov=1'b1;

end

2'b10:

im_y[3:0]=a&b;

2'b11:

im_y[3:0]=a^b;

default:

im_y[3:0]=4'b0000;

endcase

end

always @(a or b)

begin

if(a>b)

{a_gt_b,a_ge_b,a_lt_b}=3'b100;

else if(a

{a_gt_b,a_ge_b,a_lt_b}=3'b001;

else

{a_gt_b,a_ge_b,a_lt_b}=3'b010;

end

assign p=^im_y[3:0];

assign y=oe?im_y[3:0]:4'bz;

endmodule

/***************************************************************** ********/

模块alu_4bit是四功能的算术逻辑单元,输入包括数据信号a、b和功能信号f,输出包括数据信号y和ALU生成的奇偶校验信号p、溢出信号ov及比较信号。

下面代码描述了alu_4bit模块的测试平台。

/***************************************************************** ********/

module test_alu_4bit;

reg [3:0] a=4'b1011,b=4'b0110;

reg [1:0] f=2'b00;

reg oe=1;

wire [3:0] y;

wire p,ov,a_gt_b,a_eg_b,a_lt_b;

alu_4bit cut(a,b,f,oe,y,p,ov,a_gt_b,a_eg_b,a_lt_b);

initial

begin

#20 b=4'b1011;

#20 b=4'b1110;

#20 b=4'b1110;

#80 oe=1'b0;

#20 $finish;

end

always #23 f=f+1;

endmodule

/***************************************************************** ********/

与alu_4bit模块相连的变量在声明时被赋初值。用一个initial语句对ALU 的输入数据b和输出使能oe赋值,在前60ns,每隔20n给b赋一个新值然后等待80ns,给oe赋0值来禁止ALU的输出,再等待20ns后结束仿真。最终等待20ns后,显示的仿真结果里包含最后一个输入数据产生的输出。

用always语句对alu_4bit的输入数据f赋值,f的初值为0,以后每隔23ns 它的值加1.initial块的$finish语句在160ns时被执行,此时所有正在运行的过程语句都停止,仿真结束。

下图所示是仿真后的波形曲线。

Verilog测试平台(testbench)技术(二) 收藏

2.时序电路测试

时序电路测试包括测试电路时钟与输入数据的同步。这里以一个名为misr的模块为例说明时序电路的测试方法。

misr模块描述的电路有一个输入时钟、一个复位信号、输入数据与输出数据。该电路有一个poly参数,用于计算让的输出值和数据压缩。每个时钟上升沿到来时,通过已有的misr寄存器数据和输入数据计算新的输出值。其Verilog描述如下。

/***************************************************************** ********/

`timescale 1ns/100ps

module misr #(parameter [3:0] poly=0) (input clk, rst, input [3:0] d_in, out put reg [3:0] d_out );

always @( posedge clk )

if( rst )

d_out =4'b0000;

else

d_out = d_in ^ ({4{d_out[0]}} & poly) ^ {1'b0,d_out[3:1]};

endmodule

/***************************************************************** ********/

下面是misr模块的测试平台。

/***************************************************************** ********/

module test_misr;

reg clk=0,rst=0;

reg [3:0] d_in;

wire [3:0] d_out;

misr #(4'b1100) MUT(clk,rst,d_in,d_out);

initial

begin

#13 rst=1'b1;

#19 d_in=4'b1000;

#31 rst=1'b0;

#330 $stop;

end

always #37 d_in=d_in+3;

always #11 clk=~clk;

endmodule

/***************************************************************** ********/

测试平台中的initial语句产生rst信号的一个上升脉冲,从13ns到63ns。这样做的目的是让这个脉冲至少覆盖一个时钟上升沿,这样,同步的rst信号可以初始化misr模块的寄存器。输入数据d_in初始值为不定态,当rst为1时,被赋予初值4'b1000。

除了这个initial语句块之外,test_misr模块还包括两个always语句,用于生成clk和d_in。时钟是周期信号,每隔11ns翻转一次,另外每隔37ns就给输入d_in一个新值。为了降低多个输入同时翻转的概率,对时序电路的输入一般采用素数作为时间间隔。

仿真波形如下所示。

Verilog测试平台(testbench)技术(三) 收藏

二、测试平台技术

下面讨论许多有关测试激励生成与输出结果观测的代码编写技术。在这里待测模块我们使用一个如下描述的 Moore 状态机,它是一个 101Moore 序列检测器。当检测到输入序列为 101 时,当前状态值变为 d ,输出 z 的值为 1 。这是一个同步复位电路。

/**************************************************************** *********/

`timescale 1ns/100ps

module Moore_detector (input x, rst, clk, output z);

parameter [1:0] a=0,b=1,c=2,d=3;

reg [1:0] current;

always @( posedge clk )

begin

if( rst )

current = a;

else

case ( current )

a: current=x?b:a;

b: current=x?b:c;

c: current=x?d:a;

d: current=x?b:c;

default: current=a;

endcase

end

assign z = (current==d)?1'b1:1'b0;

endmodule

/**************************************************************** *********/

1. 测试数据

如下代码是 moore_detector 模块的测试平台,与前面类似,测试平台是一个没有输入输出端口的模块。这个模块有 4 个过程块用于生成待测状态机的测试数据。与例化模块 MUT 的输入端相连的变量在过程块里位于赋值语句的左侧,它们的定义为 reg 类型。

/**************************************************************** *********/

module test_moore_detector;

reg x,reset,clock;

wire z;

Moore_detector MUT(x,reset,clock,z);

initial

begin

clock=1'b0;

x=1'b0;

reset=1'b1;

end

initial

#24 reset=1'b0;

always #5 clock=~clock;

always #7 x=~x;

endmodule

/**************************************************************** *********/

通常不是在声明 reg 类型变量时对其进行初始化,而是采用 initial 块对其进行初始化。初始化变量很重要,特别是对 clock 这种需要利用它前一时刻的值来计算当前时刻的值的变量,若不对其进行初始化,它的初始值为不确定状态,并将一直保持为该状态。

2. 对仿真的控制

下面代码描述了 moore_detector 模块的另一种测试平台。上一节介绍的测试平台,如果不中断它或停止它,它会一直运行,而下面描述的测试平台解决了这个问题,它加入另一个 initial 块,使仿真在 189ms 时停止。

/**************************************************************** *********/

// 有 $stop 仿真控制任务的测试平台

module test_moore_detector;

reg x=0,reset=1,clock=0;

wire z;

Moore_detector MUT(x,reset,clock,z);

initial

#24 reset=1'b0;

always #5 clock=~clock;

always #7 x=~x;

initial

#189 $stop;

endmodule

/**************************************************************** *********/

$stop 和 $finish 是仿真控制任务。当过程块运行到此类任务时,仿真暂停或结束。暂停的仿真可以继续运行,而结束的仿真则不能。仿真波形如下图。

下面是 moore_detector 模块的第三种测试平台,它把 reset 信号无效和仿真控制任务放在同一个 initial 块里,在这种时序下,仿真在 189ns 时刻停止。

/**************************************************************** *********/

// 有 $finish 仿真控制任务的测试平台

module test_moore_detector;

reg x=0,reset=1,clock=0;

wire z;

Moore_detector MUT(x,reset,clock,z);

initial

begin

#24 reset=1'b0;

#165 $finish;

end

always #5 clock=~clock;

always #7 x=~x;

endmodule

/**************************************************************** *********/

Verilog测试平台(testbench)技术(四) 收藏

3. 设置数据限制

测试平台也可以不通过设置仿真时间限制来控制仿真时间,而是通过对 MU T 输入数据的数量进行设置来达到控制仿真时间的目的。同样,也可以停止仿真,避免其无限制地运行。

下面 Verilog 代码描述了 moore_detector 模块的第四中测试平台。这里采用 $random 对输入 x 生成随机数据。 initial 块里的 repeat 语句让时钟共执行 13 次变化,每 5ns 变化一次;而 x 共得到 10 个新数据,每隔 7ns 变化一次。这里采用随机信号代替固定的测试数据。这种策略生成数据比较简单,但是分析输出时比较困难,因为它的输入是不可预测的。对于大规模电路来说,随机数据比可控的数据更有用。

/**************************************************************** *********/

// 用 repeat 语句限制输入数据的测试平台

module test_moore_detector;

reg x=0,reset=1,clock=0;

wire z;

Moore_detector MUT(x,reset,clock,z);

initial #24 reset=1'b0;

initial repeat(13) #5 clock=~clock;

initial repeat(10) #7 x=$random;

endmodule

/**************************************************************** *********/

4. 采用同步数据

前面介绍的几个测试平台的例子中,时钟和数据均采用独立时序。当同时施加几组数据时,数据与系统时钟的同步将出现困难。

改变时钟频率会造成待测模块所有输入数据时序的改变。

下面描述的 moore_detector 模块的测试平台解决了这一问题。它采用事件控制语句来同步由测试平台生成的 x 与时钟。在一个 initial 语句里用 repe ate 语句生成 clock 信号。另一个 initial 语句用于生成随机的数据 x 。其中,用一个 forever 循环来重复执行这项操作。这个循环语句等到 clock 上升沿到来 3ns 后执行,为 x 生成新的随机数。这个时钟上升沿后稳定的数据在下一时钟上升沿时施加到 moore_detector 模块。这种激励技术保证数据和时钟不会同时变化。

/**************************************************************** *********/

// 与时钟同步的数据

module test_moore_detector;

reg x=0,reset=1,clock=0;

wire z;

Moore_detector MUT(x,reset,clock,z);

initial #24 reset=1'b0;

initial repeat(13) #5 clock=~clock;

initial forever @(posedge clock) #3 x=$random;

endmodule

/**************************************************************** *********/

这里采用 3ns 的延迟,使该测试平台既可以用于行为仿真,又可以用于综合后仿真。在综合后仿真时,采用带有真实时延的元件模型,测试平台的延迟使该测试数据比其余测试数据先结束。

5. 输出结果的同步显示

在前面所述测试平台的基础上,下面介绍一种可以用于同步观测待测模块的输出或内部信号的方法。当采用层次化命名时,这种测试平台能够显示待测模块的内部变量和内部信号。在这里我们用到了任务函数 $display 和 $monitor 。

以下面描述的 moore_detector 模块测试平台为例来介绍这一方法。该平台用于观测 moore_detector 状态值 current 和输出值 z ,其中用到任务函数$monitor 来显示寄存器 current 的值,另外在一个 always 块中,用任务函数 $diaplay 来显示输出结果 z 。每当 current 状态值和输出值 z 变化时,就会显示变化后的值。

/**************************************************************** *********/

module test_moore_detector;

reg x=0,reset=1,clock=0;

wire z;

Moore_detector MUT(x,reset,clock,z);

initial #24 reset=1'b0;

initial repeat(19) #5 clock=~clock;

initial forever @(posedge clock) #3 x=$random;

initial $monitor("New state is %d and occurs at %t",MUT. current,$time);

always @(z) $display("Output changes at %t to %b",$time, z);

endmodule

/**************************************************************** *********/

该测试平台的最后一个过程赋值语句是对 z 值敏感的 always 语句。该语句里嵌套了一个 $display 任务,用于在 z 值变化时显示变化后的值及其变化时间。下面所示是运行测试平台生成的结果。

# New state is x and occurs at 0

# Output changes at 5 to 0

# New state is 0 and occurs at 5

# New state is 1 and occurs at 25

# New state is 2 and occurs at 85

# Output changes at 95 to 1

# New state is 3 and occurs at 95

Verilog测试平台(testbench)技术(五) 收藏

6. 交互式测试平台

在下面的几个测试平台里,我们采用了新的待测状态机,如下面代码所示。它是一个有开始 (start) 和复位 (rst) 控制的 1101Moore 序列检测器。它共有 5 个状态,在序列检测器的检测过程中,如果 start 的值变为 0 ,那么状态机复位到初始状态。当前状态到达 e 状态时,输出为 1 。

/**************************************************************** *********/

// 带开始 (start) 和复位 (rst) 控制的 1101More 序列检测器

`timescale 1ns/100ps

module Moore_detector (input x, start,rst, clk, output z);

parameter a=0,b=1,c=2,d=3,e=4;

reg [2:0] current;

always @( posedge clk )

begin

if( rst )

current <= a;

else if(~start)

current <= a;

else

case ( current )

a: current <= x?b:a; b: current <= x?c:a; c: current <= x?c:d; d: current <= x?e:a; e: current <= x?c:a; default: current <= a; endcase

end

assign z = (current==e);

endmodule

/**************************************************************** *********/

对于这个状态机,我们使用一个交互式测试平台,如下代码所示。

/**************************************************************** *********/

module test_moore_detector;

reg x=0,start,reset=1,clock=0;

wire z;

Moore_detector MUT(x,start,reset,clock,z);

initial

begin

#24 reset = 1'b0;

start = 1'b1;

wait(z==1'b1);

#11 start=1'b0;

#13 start=1'b1;

repeat(3)

begin

#11 start=1'b0;

#13 start=1'b1;

wait(z==1'b1);

end

#50 $stop;

end

always #5 clock=~clock;

always #7 x=$random;

endmodule

/**************************************************************** *********/

在一个 initial 块中,测试平台与待测模块通信。输入 x 和 clock 由两个 always 块生成。 clock 是连续周期信号, x 是周期产生的随机信号。

首先对 reset 和 start 的值分别赋值为 0 和 1 ,于是状态机开始工作,然后是一个 wait 语句,用于等待待测模块的结果 z 在输入 x 和 clock 的作用下变为 1 。当 z 变为 1 后, 11ns 后 start 变为 0 ,再过 13ns 后 sta rt 变为 1 ,这是重启状态机的过程。 repeat 语句将重复 3 次这样的等待和重启过程。 repeat 语句执行完毕后 50ns ,运行系统 $stop ,仿真结束。

下图所示为测试平台的部分仿真波形。

帧格式头数据检测_VerilogHDL有限状态机

题目1:串行通讯中,经常要检测数据包的开始标志,例如:USB 数据包的起 始数据是8‘b00101010设计一个电路,能够检测串行数据流中的特殊数据串,并在数据串有效时,给出相应的指示信号; (1)RTL Code /*信号定义与说明 Clk:同步时钟 rstb: 异步复位信号,低电平复位 up_down: 加/减计数方向控制信号,1为加计数 Din:串行数据输入 pat_det: 检测结果输出 */ `timescale 1ns/1ns module serialdata(din,clk,rstb,pat_det); input clk,rstb; input din; output pat_det; parameter S0='d0,S1='d1,S2='d2,S3='d3,S4='d4,S5='d5,S6='d6,IDLE='d7; reg[2:0] state; assign pat_det=(state= =S6&&din= =0)?1:0; always@(posedge clk or negedge rstb) begin if(!rstb) state<=IDLE; else begin case(state) IDLE: begin if(din==0) state<=S0; else state<=IDLE; end S0: begin if(din==0) state<=S1; else state<=IDLE; end S1: begin if(din==1) state<=S2; else state<=S1; end S2:

begin if(din==0) state<=S3; else state<=IDLE; end S3: begin if(din==1) state<=S4; else state<=S1; end S4: begin if(din==0) state<=S5; else state<=IDLE; end S5: begin if(din==1) state<=S6; else state<=S1; end S6: state<=IDLE; default: state<=IDLE; endcase end end endmodule (2)Test File `timescale 1ns/1ns `include "serialdata.v" module tb_serialdata; reg clk,rstb; wire din; wire pat_det; reg[31:0] data; assign din=data[31]; serialdata t1(din,clk,rstb,pat_det); initial begin clk=1'b0; rstb=1'b0; data=32'b1001_0010_1010_1100_1010_1000_1010_1010; #10 rstb=1'b1; #640 $stop; end

编写高效率的testbench

Writing Efficient Testbenches 编写高效的测试设计(testbenches) 原文作者:Mujtaba Hamid 注: 一个设计的测试验证是非常重要的。有效的测试可以助我们快速的完成或改善设计。Testbenches建议编写有效的测试代码来通过软件实现可靠的验证。无意中发现,顺手译为中文,以备将来方便。也贴给没有找到更好中文版本的同道人。 Testbenches本意应该是测试平台更合理,但是在中文中阅读起来很不舒服。所以本文中有时译为“测试设计”,“测试代码”,有时干脆是“测试”。 摘要: 应用笔记为HDL验证设计的新手,或者是没有丰富的测试设计经验的逻辑设计者而编写。 测试设计是验证HDL设计的主要手段。本应用笔记为创建或准备和构建有效的测试设计提供准则。它也提供一个为任何设计开发自较验测的测试设计的一个代数方法。 涉及的所有设计文件可以从以下的站点获得: PC: ftp://https://www.360docs.net/doc/e118725942.html,/pub/applications/xapp/xapp199.zip UNIX: ftp://https://www.360docs.net/doc/e118725942.html,/pub/applications/xapp/xapp199.tar.gz 简介: 由于设计的规模越来越大也越来越复杂,数字设计的验证已经成为一个日益困难和繁琐的任务。验证工程师们依靠一些验证工具和方法来应付这个挑战。对于几百万门的大型设计,工程师们一般使用一套形式验证(formal verification)工具。然而对于一些小型的设计,设计工程师常常发现用带有testbench的HDL仿真器就可以很好地进行验证。 Testbench已经成为一个验证高级语言(HLL --High-Level Language) 设计的标准方法。通常testbench完成如下的任务: 1.实例化需要测试的设计(DUT); 2.通过对DUT模型加载测试向量来仿真设计; 3.将输出结果到终端或波形窗口中加以视觉检视; 4.另外,将实际结果和预期结果进行比较。 通常testbench用工业标准的VHDL或Verilog硬件描述语言来编写。Testbench调用功能设计,然后进行仿真。复杂的testbench完成一些附加的功能—例如它们包含一些逻辑来选择产生合适的设计激励或比较实际结果和预期结果。 后续的章节描述了一个仔细构建的testbench的结构,并且提供了一个自动比较实际结果与预期结果的进行自我检查的testbench例子。 图1给出了一个如上所描述步骤的标准HDL验证流程。由于testbench使用VHDL或Verilog来描述,testbench的验证过程可以根据不同的平台或不同的软件工具实现。由于VHDL 或Verilog是公开的通用标准,使用VHDL或Verilog编写的testbench以后也可以毫无困难地重用(reuse)。

verilog可综合有限状态机的4种写法(夏文宇书注)

verilog可综合有限状态机的4种写法(夏文宇书注) 第一种:自然编码 module fsm1( input i_clk, input rst_n, input A, output reg K1, output reg K2, output reg [1:0] state ); parameter Idle=2'b00, Start=2'b01, Stop=2'b10, Clear=2'b11; [email=always@(posedge]always@(posedge[/email] i_clk) if(!rst_n) begin state<=Idle; K2<=0; K1<=0; end else case(state) Idle:if(A) begin state<=Start; K1<=0; end else begin state<=Idle; K2<=0; K1<=0; end Start:if(!A) state<=Stop; else state<=Start; Stop:if(A) begin state<=Clear; K2<=1;

else begin state<=Stop; K2<=0; K1<=0; end Clear:if(!A) begin state<=Idle; K1<=1; K2<=0; end else begin state<=Clear; K2<=0; K1<=1; end default: state<=Idle; endcase endmodule 这种大家应该都熟悉的 第二种:采用独热编码,据说其可靠性和速度都不错module fsm2( input i_clk, input rst_n, input A, output reg K1, output reg K2, output reg [3:0] state ); parameter Idle=4'b1000; parameter Start=4'b0100; parameter Stop=4'b0010; parameter Clear=4'b0001; always@(posedge i_clk) begin if(!rst_n)

怎样写testbench(内有一个实例分析)

怎样写testbench 本文的实际编程环境:ISE 6.2i.03 ModelSim 5.8 SE Synplify Pro 7.6 编程语言 VHDL 在ISE中调用ModelSim进行仿真 一、基本概念和基础知识 Testbench不仅要产生激励也就是输入,还要验证响应也就是输出。当然也可以只产生激励,然后通过波形窗口通过人工的方法去验证波形,这种方法只能适用于小规模的设计。 在ISE环境中,当前资源操作窗显示了资源管理窗口中选中的资源文件能进行的相关操作。在资源管理窗口选中了testbench文件后,在当前资源操作窗显示的ModelSim Simulator中显示了4种能进行的模拟操作,分别是:Simulator Behavioral Model(功能仿真)、Simulator Post-translate VHDL Model(翻译后仿真)、Simulator Post-Map VHDL Model(映射后仿真)、Simulator Post-Place & Route VHDL Model(布局布线后仿真)。如图1所示: 图1 l Simulator Behavioral Model 也就是所说的功能仿真、行为仿真、前仿真。验证功能是否正确,这是设计的第一步。功能仿真正确的程序不一定能被正确综合,也 就是硬件实现。有的在综合时报错误,有的虽然能综合但结果并不正确。当然,功 能仿真如果都不能通过,以后的步骤也就无法进行。这是必做的仿真。 l Simulator Post-translate VHDL Model 也就是翻译后仿真。对源程序进行编译后首先排除了语法错误,对一些像类属命令(Generic)、生成语句(Generate)等进 行了展开。不是必做的仿真。 l Simulator Post-Map VHDL Model也就是映射后仿真。不同的器件内部结构也不尽相同,映射的作用就是将综合后产生的网表文件对应到实际的器件上去。由于映射 不包含布线,也就是要用什么类型的逻辑单元虽然已经确定但要用哪个位置的还没 有确定,因此,映射后仿真不包含布线延时。不是必做的仿真。 l Simulator Post-Place & Route VHDL Model也就是所说的布局布线后仿真、时序仿真、后仿真。这是最完整的仿真,既包含逻辑延时又包含布线延时。在做布局布 线后仿真时要用到一个叫SDF的文件。SDF文件包含设计中每个单元(Cell)的延

VERILOG语言编写规范

VERILOG语言编写规范 1 目的 本规范的目的是提高书写代码的可读性可修改性可重用性,优化代码综合和仿真结果,指导设计工程师使用VerilogHDL规范代码和优化电路,规范化公司的ASIC设计输入从而做到 1. 逻辑功能正确 2.可快速仿真 3. 综合结果最优如果是hardware model) 4. 可读性较好。 2 范围 本规范涉及Verilog HDL编码风格,编码中应注意的问题, Testbench的编码等。 本规范适用于Verilog model的任何一级( RTL behavioral, gate_level),也适用于出于仿真,综合或二者结合的目的而设计的模块。 3 定义 Verilog HDL : Verilog 硬件描述语言 FSM :有限状态机 伪路径:静态时序分析( STA)认为是时序失败,而设计者认为是正确的路径 4 引用标准和参考资料 下列标准包含的条文通过在本标准中引用而构成本标准的条文在标准出版时所示版本 均为有效所有标准都会被修订使用本标准的各方应探讨使用下列标准最新版本的可能性 Actel HDLCoding Style Guider Sun Microsystems Revision 1.0 VerilogStyle and Coding Guidelines 5 规范内容 5.1 Verilog 编码风格

本章节中提到的Verilog编码规则和建议适应于 Verilog model的任何一级( RTL behavioral,gate_level) 也适用于出于仿真,综合或二者结合的目的而设计的模块。 5.1.1 命名规范 选择有意义的信号和变量名,对设计是十分重要的。命名包含信号或变量诸如出处,有效状态等基本含义下面给出一些命名的规则。 1. 用有意义而有效的名字 有效的命名有时并不是要求将功能描述出来如 For ( I = 0; I < 1024; I = I + 1 ) Mem[I]<= #1 32’b0; For 语句中的循环指针I 就没必要用loop_index作为指针名。 2. 用连贯的缩写 长的名字对书写和记忆会带来不便,甚至带来错误采用缩写时应注意同一信号在模块中的一致性。缩写的例子如下: Addr address Pntr pointer Clk clock Rst reset 3. 用名字前加小写n表示低电平有效高电平有效的信号不得以下划线表示短暂 的引擎信号建议采用高有效 如 nRst, nTrdy, nIrdy nIdsel. 4. 大小写原则 名字一般首字符大写,其余小写(但parameter, integer 定义的数值名可全部用大写),两个词之间要用下划线连接(或第二个单词首字母大写) 如 :Packet_addr, Data_in, Mem_wr , Mem_ce_ Or: PacketAddr, DataIn, MemWr , MemCe 5.全局信号名字中应包含信号来源的一些信息 如: D_addr[7:2] 这里的 D 指明了地址是解码模块(Decoder module)中的地址.

Verilog三段式状态机的建模方法和注意事项

Verilog三段式状态机(FSM) 网上收集整理…… 时序电路的状态是一个状态变量集合,这些状态变量在任意时刻的值都包含了为确定电路的未来行为而必需考虑的所有历史信息。 状态机采用VerilogHDL语言编码,建议分为三个always段完成。这是为什么呢? 设计FSM的方法和技巧多种多样,但是总结起来有两大类:第一种,将状态转移和状态的操作和判断等写到一个模块(process、block)中。另一种是将状态转移单独写成一个模块,将状态的操作和判断等写到另一个模块中(在Verilog代码中,相当于使用两个“always”block)。其中较好的方式是后者。其原因如下。 首先FSM和其他设计一样,最好使用同步时序方式设计,好处不再累述。而状态机实现后,状态转移是用寄存器实现的,是同步时序部分。状态的转移条件的判断是通过组合逻辑判断实现的,之所以第二种比第一种编码方式合理,就在于第二种编码将同步时序和组合逻辑分别放到不同的程序块(process,block)中实现。这样做的好处不仅仅是便于阅读、理解、维护,更重要的是利于综合器优化代码,利于用户添加合适的时序约束条件,利于布局布线器实现设计。 三段式建模描述FSM的状态机输出时,只需指定case敏感表为次态寄存器,然后直接在每个次态的case分支中描述该状态的输出即可,不用考虑状态转移条件。 三段式描述方法虽然代码结构复杂了一些,但是换来的优势是使FSM做到了同步寄存器输出,消除了组合逻辑输出的不稳定与毛刺的隐患,而且更利于时序路径分组,一般来说在FPGA/CPLD等可编程逻辑器件上的综合与布局布线效果更佳。 示例如下: //第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器 always @ (posedge clk or negedge rst_n) //异步复位 if(!rst_n) current_state <= IDLE; else current_state <= next_state;//注意,使用的是非阻塞赋值 //第二个进程,组合逻辑always模块,描述状态转移条件判断 always @ (current_state) //电平触发 begin next_state = x; //要初始化,使得系统复位后能进入正确的状态 case(current_state) S1: if(...) next_state = S2; //阻塞赋值 ... endcase end

testbench时钟信号的编写(verilog)

testbench时钟信号的编写 2011-01-13 11:07:38| 分类:FPGA的分享| 标签:clock parameter reg 占空比 time_period |举报|字号大中小订阅 /******************************************************* 时钟信号的编写 *******************************************************/ 'timescale 1ns/1ps //定义时间单位/时间精度 /******************占空比50%(采用initial)**************/ parameter TIME_PERIOD = 10; reg clock; initial begin clock = 0;//初始化clock为0 forever # (TIME_PERIOD/2) clock = ~clock; end /******************占空比50%(采用always)***************/ parameter TIME_PERIOD = 10; reg clock; initial clock = 0;//初始化clock为0 always # (TIME_PERIOD/2) clock = ~clock; /******************非50%占空比(采用always)*************/ parameter HI_TIME = 5, LO_TIME = 10; reg clock; always begin # HI_TIME clock = 0; # LO_TIME clock = 1; end /***********固定数目时钟占空比50%(采用initial)*********/ parameter PULSE_COUNT = 4, TIME_PERIOD = 10; reg clock; initial begin clock = 0;//初始化clock为0 repeat (2*PULSE_COUNT)

VERYLOG编码规范

Verilog编码规范! 一. 强调Verilog代码编写风格的必要性。 强调Verilog代码编写规范,经常是一个不太受欢迎的话题,但却是非常有必要的。 每个代码编写者都有自己的编写习惯,而且都喜欢按照自己的习惯去编写代码。与自己编写风格相近的代码,阅读起来容易接受和理解。相反和自己编写风格差别较大的代码,阅读和接受起来就困难一些。 曾有编程大师总结说,一个优秀的程序员,能维护的代码长度大约在1万行数量级。代码的整洁程度,很大程度上影响着代码的维护难度。 遵循代码编写规范书写的代码,很容易阅读、理解、维护、修改、跟踪调试、整理文档。相反代码编写风格随意的代码,通常晦涩、凌乱,会给开发者本人的调试、修改工作带来困难,也会给合作者带来很大麻烦。 (实际上英文Coding Style有另一层涵义,更偏重的是,某一个电路,用那一种形式的语言描述,才能将电路描述得更准确,综合以后产生的电路更合理。本文更偏重的是,编写Verilog代码时的书写习惯。) 二. 强调编写规范的宗旨。 缩小篇幅 提高整洁度 便于跟踪、分析、调试 增强可读性,帮助阅读者理解 便于整理文档 便于交流合作 三. 变量及信号命名规范。 1. 系统级信号的命名。 系统级信号指复位信号,置位信号,时钟信号等需要输送到各个模块的全局信号;系统信号以字符串Sys开头。 2. 低电平有效的信号后一律加下划线和字母n。如:SysRst_n;FifoFull_n; 3. 经过锁存器锁存后的信号,后加下划线和字母r,与锁存前的信号区别。如CpuRamRd信号,经锁存后应命名为CpuRamRd_r。 低电平有效的信号经过锁存器锁存后,其命名应在_n后加r。如CpuRamRd_n信号,经锁存后应命名为CpuRamRd_nr 多级锁存的信号,可多加r以标明。如CpuRamRd信号,经两级触发器锁存后,应命名为CpuRamRd_rr。 4. 模块的命名。 在系统设计阶段应该为每个模块进行命名。命名的方法是,将模块英文名称的各个单词首字母组合起来,形成3到5个字符的缩写。若模块的英文名只有一个单词,可取该单词的前3个字母。各模块的命名以3个字母为宜。例如: Arithmatic Logical Unit模块,命名为ALU。 Data Memory Interface模块,命名为DMI。

verilog有限状态机实验报告(附源代码)

有限状态机实验报告 一、实验目的 ●进一步学习时序逻辑电路 ●了解有限状态机的工作原理 ●学会使用“三段式”有限状态机设计电路 ●掌握按键去抖动、信号取边沿等处理技巧 二、实验内容 用三段式有限状态机实现序列检测功能电路 a)按从高位到低位逐位串行输入一个序列,输入用拨动开关实现。 b)每当检测到序列“1101”(不重叠)时,LED指示灯亮,否则灭,例如 i.输入:1 1 0 1 1 0 1 1 0 1 ii.输出:0 0 0 1 0 0 0 0 0 1 c)用八段数码管显示最后输入的四个数,每输入一个数,数码管变化一次 d)按键按下的瞬间将拨动开关状态锁存 i.注意防抖动(按键按下瞬间可能会有多次的电平跳变) 三、实验结果 1.Rst_n为0时数码管显示0000,led灯不亮,rst_n拨为1,可以开始输入,将输 入的开关拨到1,按下按钮,数码管示数变为0001,之后一次类推分别输入1, 0,1,按下按钮后,数码管为1101,LED灯亮,再输入1,LED灯灭,之后再输 入0,1(即共输入1101101使1101重叠,第二次LED灯不亮),之后单独输入

1101,LED灯亮 2.仿真图像 刚启动时使用rst_n 一段时间后 其中Y代表输出,即控制led灯的信号,sel表示数码管的选择信号,seg表示数码管信号 四、实验分析 1、实验基本结构

其中状态机部分使用三段式结构: 2、整体结构为:

建立一下模块: Anti_dither.v 输入按键信号和时钟信号,输出去除抖动的按键信号生成的脉冲信号op 这一模块实现思路是利用按钮按下时会持续10ms以上而上下抖动时接触时间不超过10ms来给向下接触的时间计时,达到上限时间才产生输出。 Num.v 输入op和序列输入信号A,时钟信号clk和复位信号,复位信号将num置零,否则若收到脉冲信号则将num左移一位并将输入存进最后一位。输出的num即为即将在数码管上显示的值 Scan.v 输入时钟信号,对其降频以产生1ms一次的扫描信号。 Trigger.v 这一模块即为状态机模块,按三段式书写。 整个模块的输入为时钟信号,脉冲信号,序列输入变量,复位信号,输出LED灯控制信号Y。 第一段是状态转换模块,为时序逻辑电路,功能是描述次态寄存器迁移到现态寄存器。即如果收到复位信号将现态置零,否则将上次得到的next_state赋给current_state。

VHDL——如何写简单的testbench

use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; --use ieee.std_logic_unsigned.all; entity cnt6 is port (clr,en,clk :in std_logic; q :out std_logic_vector(2 downto 0) ); end entity; architecture rtl of cnt6 is signal tmp :std_logic_vector(2 downto 0); begin process(clk) -- variable q6:integer; begin if(clk'event and clk='1') then if(clr='0')then tmp<="000"; elsif(en='1') then if(tmp="101")then tmp<="000"; else

tmp<=unsigned(tmp)+'1'; end if; end if; end if; q<=tmp; -- qa<=q(0); -- qb<=q(1); -- qc<=q(2); end process; end rtl; 二、六进制计数器testbench的代码

signal en :std_logic:='0'; signal clk :std_logic:='0'; signal q :std_logic_vector(2 downto 0); constant clk_period :time :=20 ns; begin instant:cnt6 port map ( clk=>clk,en=>en,clr=>clr,q=>q ); clk_gen:process begin wait for clk_period/2; clk<='1'; wait for clk_period/2; clk<='0'; end process; clr_gen:process begin clr<='0'; wait for 30 ns; clr<='1'; wait; end process; en_gen:process begin en<='0'; wait for 50ns; en<='1'; wait; end process; end rtl;

1 ModelSim的使用与Testbench的编写

ModelSim的使用与Testbench的编写 重温了基本的Quartus操作和语法后,需要对手头的工作进行仿真验证,Quartus 9.x自带的Vector Waveform已经淘汰掉了,必须用 ModelSim进行仿真。现在就开始一步步入手ModelSim,并通过与Quartus无缝衔接实现仿真。本文使用了ModelSim10.0c + QuartusII 10.0,其他版本基本雷同,请自行研究。 源程序如下: module add( mclk, rst_n, a_in, b_in, c_out ); input mclk, rst_n; input[7:0] a_in, b_in; output[8:0] c_out; reg[8:0] c_out; always@(posedge mclk, negedge rst_n) begin if(!rst_n) c_out <= 9'h0; else c_out <= a_in + b_in; end endmodule 请建立工程,将源程序编译通过. 1.设置第三方EDA工具 在Tools -> Options中设置ModelSim的安装路径,注意要设置到win32文件夹(64位软件对应的就是win64)。

仿真工具为ModelSim。这样Quartus就能无缝调用ModelSim了。

当然也可以在建立工程的时候就设置仿真工具。

2.编写Testbench 说到Testbench,你可以叫它Testbench,或者Testbenches,但不是Test Bench。说起来,就连Quartus也没注意这个问题,至于原因嘛参见Common Mistakes In Technical Texts一文。文章中还列举了些别的错误用语,包括Flip-flop不能写成Flipflop,等等。文章链接: https://www.360docs.net/doc/e118725942.html,/papers/Technical_Text_Mistakes.pdf 我们可以通过Quartus自动生成一个Testbench的模板,选择Processing -> Start -> Start Test Bench Template Writer,等待完成后,在导航栏中打开刚才生成的Testbench,默认是保存在simulation\modelsim文件夹下的.vt格 式文件。

第5章-Verilog HDL语法规范(第10讲)-5.10

Verilog HDL语言规范

Verilog HDL 行为描述语句 本部分介绍行为描述语句。通过行为级建模把一个复杂的系统分解成可操作的若干个模块,每个模块之间的逻辑关系通过行为模块的仿真加以验证。同时行为级建模还可以用来生成仿真激励信号,对已设计模块进行仿真验证。

Verilog HDL 行为描述语句 --过程语句 过程分配用于更新reg,integer,time,real, realtime和存储器数据类型。对于过程分配和连续分配来说,有下面的不同之处: ?连续分配 连续分配驱动网络。只要一个输入操作数的值发生变化,则更新和求取所驱动网络的值。 ?过程分配 在过程流结构的控制下,过程分配更新流结构内变量的值。

Verilog HDL 行为描述语句 --过程语句 过程分配的右边可以是求取值的任何表达式。左边应该是一个变量,它接收右边表达式分配的值。 过程分配的左边可以是下面的一种格式: ?reg 、integer 、real 、realtime 或者time 数据类型分配给这些数据类型所引用的名字。 ?reg 、integer 、real 、realtime 或者time 数据类型的位选择分配到单个的比特位

Verilog HDL 行为描述语句 --过程语句 ?reg 、integer 、real 、realtime 或者time 数据类型的部分选择一个或者多个连续的比特位的部分选择。 ?存储器字 存储器的单个字 ?任何上面的并置(连接)或者嵌套的并置(连接) 上面四种形式的并置或者嵌套的并置。这些语句对右边的表达式进行有效的分割,将分割的部分按顺序分配到并置或者嵌套并置的不同部分中。

用verilog语言编写交通灯程序

交通灯 一、实验目的 写一个交通灯,要求: ①有东西南北四个方向,两组交通灯轮流交替变换,其中,红灯时间为30 个时间单位,绿灯时间为25个时间单位,黄灯时间为5个时间单位。最后用modelsim软件进行仿真。 ②要求设计是一个可综合设计。 二、实验原理 根据实验要求的逻辑功能描述,可以分析得出原理图如下: 根据实验要求画出控制器的状态转移图如下:

三、代码 1、源代码 (1)控制器模块 module traffic_lights(clk,rst,count,ew,sn); input clk,rst; input[5:0] count; output[2:0] ew,sn; reg[2:0] ew,sn; reg[3:0] state; parameter Idle=3'b000,s1=3'b001,s2=3'b010,s3=3'b011,s4=3'b100; always @(posedge clk) if(!rst) begin state<=Idle; end else casex(state) Idle: if(rst) begin state<=s1; end s1: if(count=='d25) begin state<=s2; end s2: if(count=='d30) begin state<=s3;

end s3: if(count=='d55) begin state<=s4; end s4: if(count=='d60) begin state<=s1; end endcase always @(posedge clk) begin if(!rst) begin ew<=3'b100; sn<=3'b100; end else casex(state) Idle: if(rst) begin ew<=3'b100; sn<=3'b001; end s1: if(count=='d25) begin ew<=3'b100; sn<=3'b010; end

Verilog状态机的写法

Verilog状态机的写法-转 1 引言 Verilog HDL作为当今国际主流的HDL语言,在芯片的前端设计中有着广泛的应用。它的语法丰富,成功地应用于设计的各个阶段:建模、仿真、验证和综合等。可综合是指综合工具能将Verilog HDL代码转换成标准的门级结构网表,因此代码的描述必须符合一定的规则。大部分数字系统都可以分为控制单元和数据单元两个部分,控制单元的主体是一个状态机,它接收外部信号以及数据单元产生的状态信息,产生控制信号,因而状态机性能的好坏对系统性能有很大的影响。 有许多可综合状态机的Verilog代码描述风格,不同代码描述风格经综合后得到电路的物理实现在速度和面积上有很大差别。优秀的代码描述应当易于修改、易于编写和理解,有助于仿真和调试,并能生成高效的综合结果。 2 有限状态机 有限状态机(Finite State Machine,FSM)在数字系统设计中应用十分广泛。根据状态机的输出是否与输入有关,可将状态机分为两大类:摩尔(Moore)型状态机和米莉 (Mealy)型状态机。Moore型状态机的输出仅与现态有关;Mealy型状态机的输出不仅与现态有关,而且和输入也有关。图1是有限状态机的一般结构图,它主要包括三个部分,其中组合逻辑部分包括状态译码器和输出译码器,状态译码器确定状态机的下一个状态,输出译码器确定状态机的输出,状态寄存器属于时序逻辑部分,用来存储状态机的内部状态。 图1 状态机的结构框图 2.1 好的状态机标准 好的状态机的标准很多,最重要的几个方面如下: 第一,状态机要安全,是指FSM不会进入死循环,特别是不会进入非预知的状态,而且由于某些扰动进入非设计状态,也能很快的恢复到正常的状态循环中来。这里面有两层含义。其一要求该FSM的综合实现结果无毛刺等异常扰动,其

如何写testbench

如何编写testbench 今天,我来带领大家写一个简单的testbench,顺便讲解如何写好一个testbench以及写testbench时应该注意的地方。 在讲解testbench之前,我们先看一下前面的那个AND_2程序的仿真图,如下: 如上图中所标,在1处,B已经为低电平了,但是输出C仍然为高电平,这样求与运算就会出错。在2处,A和B都是低电平了,C仍然为高电平,直到下次出现时钟的上升沿为止,为什么会这样呢?编译的时候并没有报错,呵呵,出了怪事了啊!其实编译器只能检查处语法错误,无法检测到逻辑错误,这个图给出的结果和我们程序所表达的结果一样,但是这并不是我们所要的求与运算,我们想要的是A和B同时为高电平时,C才输出高电平。我们把程序的敏感列表改为: always@(posedge clk or negedge rst or A or B) 就可以了,把A的电平改变和B的电平改变都加进敏感列表,激励不变,所得到的仿真图: 这才是我们所要的求与运算! 好了,现在开始讲如何写testbench。Testbench不像RTL级代码,可以用高级行为语句,不用考虑其可综合性,这样就能写出高效的检测代码。在语法上,testbench和可综合代码一样,都是类C结构。好了,我们开始吧! 1,建立工程等,与之前的一样,但是在创建文件的时候,我们一次创建两个。取名分别为ParallelSerial_Mult和ParallelSerial_Mult_test。创建完成后,如下图:

这两个代码分别如下: module ParallelSerial_Mult(Clk,Rst,MultiplicandIn,MultiplierIn,Load,Product,Out_en); parameter N=8; parameter CYCLES=3; input Clk,Rst,Load; input[N-1:0]MultiplicandIn,MultiplierIn; output[2*N-1:0]Product; output Out_en; reg[2*N-1:0]Product; wire Out_en; reg[N-1:0]Multiplicand; reg[2*N-1:0]NextProduct; reg[CYCLES:0]Count; reg Busy; wire[N-1:0]Sum; wire Carry; assign{Carry,Sum}=Multiplicand+Product[2*N-1:N]; assign Out_en=Count[CYCLES]; always@(posedge Clk or negedge Rst) if(!Rst) begin Multiplicand<=0; Count<=0; Product<=0; Busy<=0; end else begin Product<=NextProduct; if(Load) begin Multiplicand<=MultiplicandIn; Count<=0; Busy<=1'b1; end else begin if(Busy) Count<=Count+1'b1; if(Count[CYCLES]) begin

verilog语言代码设计规范

verilog语言代码设计规范2011年12月

目录 一、规范适用范围 ------------------------------------------------------------------------ 4 1.1项目适用范围------------------------------------------------------------------------------------- 4 1.2人员适用范围------------------------------------------------------------------------------------- 4 1.3编码设计的成果形式 --------------------------------------------------------------------------- 4 二、代码书写规范 ------------------------------------------------------------------------ 5 2.1模块说明书写规范------------------------------------------------------------------------------- 5 2.1模块注释书写规范------------------------------------------------------------------------------- 5 2.3变量名称书写规范------------------------------------------------------------------------------- 6 2.4代码结构书写规范------------------------------------------------------------------------------- 7 三、使用verilog语言的语法范围----------------------------------------------------- 8 3.1设计RTL代码的语法范围 -------------------------------------------------------------------- 8 3.2设计仿真代码的语法范围 -------------------------------------------------------------------- 10 四、使用verilog语言的结构范围---------------------------------------------------- 11 4.1系统设计文件的形式与使用方法----------------------------------------------------------- 11 4.2模块结构划分的标准 -------------------------------------------------------------------------- 12 4.3组合逻辑的代码风格 ------------------------------------------------------------------------ 13 4.4时序逻辑的代码风格 -------------------------------------------------------------------------- 21 4.5仿真代码的代码风格 -------------------------------------------------------------------------- 27 五、使用受限范围内的语法或结构要进行的申请过程-------------------------- 32 5.1受限的语法与结构------------------------------------------------------------------------------ 32 5.2批准使用的程序--------------------------------------------------------------------------------- 32

Verilog仿真文件testbench编写样例

Verilog 仿真文件testbench编写样例 `timescale 1ns/100ps module testbench; localparam DATA_WIDTH = 32; localparam CLK_100_PERIOD = 5; localparam CLK_200_PERIOD = 2.5; localparam SIM_TIME = 150000; localparam ; localparam ; reg clk_100, clk_200; wire clk; assign clk = clk_100; always begin clk_100 = 0; forever #CLK_100_PERIOD clk_100 = ~clk_100; end always begin clk_200 = 0; forever #CLK_200_PERIOD clk_200 = ~clk_200;

end reg rstn; integer fp_testin; integer fp_matlab_out; integer fp_sim_out; integer fp_outdiff; reg signed [DATA_WIDTH/2-1:0] matlab_in_re, matlab_in_im; reg signed [DATA_WIDTH/2-1:0] matlab_out_re, matlab_out_im; reg signed [DATA_WIDTH/2-1:0] matlab_diff_re, matlab_diff_im; reg signed [DATA_WIDTH/2-1:0] matlab_diff_re2, matlab_diff_im2; reg signed [DATA_WIDTH/2-1:0] max_diff_re, max_diff_im; initial begin max_diff_re = 0; max_diff_im = 0; rstn = 0; #500 rstn = 1;

相关文档
最新文档