语法要点详细讲解.ppt
《语法要点详细讲解.ppt》由会员分享,可在线阅读,更多相关《语法要点详细讲解.ppt(144页珍藏版)》请在三一办公上搜索。
1、语法要点详细讲解,有关测试模块编写的语法;语法的高级部分:函数、任务、文件、存贮器建立模型、双向总线、UDP、综合指令。,语法详细讲解 Verilog测试模块的编写,目的:复习如何编写较复杂的测试文件,对所做的设计 进行完整的测试和验证。掌握组织模块测试的常用方法;学会编写常用的 测试代码。,语法详细讲解 用Verilog设计的步骤,注:虚线表示编译器能检查输入文件的可读性和是否存在以及是否允许生成输出文件,include文件,设计文件,厂家元件库文件,输入文件:激励和期望的输出信号,输出文件:激励和实际输出的信号,编译器,仿真器,仿真器,语法详细讲解 测试平台的组成,激励信号,需要验证的设计
2、,激励信号和用于验证的结果数据,需要验证的设计,简单的测试平台,复杂的测试平台,语法详细讲解 并行块,在测试块中常用到forkjoin块。用并行块能表示以同一个时间起点算起的多个事件的运行,并行地执行复杂的过程结构,如循环或任务。举例说明如下:module inline_tb;reg 7:0 data_bus;initial fork data_bus=8b00;#10 data_bus=8h45;/这两个repeat开始执行时间不同,但能同时运行#20 repeat(10)#10 data_bus=data_bus+1;#25 repeat(5)#20 data_bus=data_bus 1
3、;#140 data_bua=8h0f;joinendmodule,语法详细讲解并行块,时间 data_bus0 8b0000_000010 8b0100_010130 8b0100_011040 8b0100_011145 8b1000_111050 8b1000_111160 8b1001_000065 8b0010_000070 8b0010_0001,时间 data_bus80 8b0010_001085 8b0100_010090 8b0100_0101 100 8b0010_0001105 8b0100_0110110 8b1000_1100120 8b1000_1110125 8
4、b0001_1100140 8b0000_1111,上面模块的仿真输出如下:,语法详细讲解强制激励,在一个过程块中,可以用两种不同的方式对信号变量或表达式进行连续赋值。过程连续赋值往往是不可以综合的,通常用在测试模块中。两种方式都有各自配套的命令来停止赋值过程。两种不同方式均不允许赋值语句间的时间控制。assign和deassign 适用于对寄存器类型的信号(例如:RTL级上的节点或测试模块中在多个地方被赋值的信号)进行赋值。initial begin#10 assign top.dut.fsml.state_reg=init_state;,#20 deassign top.dut.fsml.
5、state_reg;endforce 和 release 用于寄存器类型和网络连接类型(例如:门级扫描寄存器的输出)的强制赋值,强制改写其它地方的赋值。initial begin#10 force top.dut.counter.scan_reg.q=0;#20 release top.dut.counter.scan_reg.q;end 在以上两个例子中,在10到20 这个时间段内,网络或寄存器类型的信号被强制赋值,而别处对该变量的赋值均无效。force的赋值优先级高于assign。如果先使用assign,再使用force对同一信号赋值,则信号的值为force所赋 的值,,语法详细讲解强制激
6、励,语法详细讲解强制激励,当执行release后,则信号的值为assign所赋 的值。如果用force对同一个信号赋了几次值,再执行release,则所有赋的值均不再存在。可以对信号的某(确定)位、某些(确定)位或拼接的信号,使用force和release赋值;但不能对信号的可变位使用force和release 来赋值。不能对寄存器类型的信号某位或某些位使用 assign 和deassign 来赋值。,虽然有时在设计中会包含时钟,但时钟通常用在测试模块中。下面三个例子分别说明如何在门级和行为级建立不同波形的时钟模型。例1 简单的对称方波时钟:,reg clk;always begin#peri
7、od/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,注:在有些仿真器中,如果设计所用的时钟是由与其相同抽象级别的时钟模型产生的,则仿真器的性能就能得到提高。,语法详细讲解建立时钟,例2简单的带延迟的对称方波时钟:,语法详细讲解建立时钟,reg clk;initial begin clk=0;#(period)forever#(period/2)clk=!clk end,reg go;wire clk;nand#(pe
8、riod/2)ul(clk,clk,go);initial begin go=0;#(period)go=1;end,注:这两个时钟模型有些不同,行为描述的模型延迟期间一直是低电平,而门级描述的模型开始延迟有半个周期是不确定的。,例3.带延迟、头一个脉冲不规则的、占空比不为1的时钟:,reg clk;initial begin#(period+1)clk=1;#(period/2-1)forever begin#(period/4)clk=0;#(3*period/4)clk=1;endend,reg go;wire clk;nand#(3*period/4,period/4)ul(clk,c
9、lk,go);initial begin#(period/4+1)go=0;#(5*period/4-1)go=1;end,注:这两个时钟模型也有些不同,行为描述的模型一开始就有确定的电平,而门级描述的模型有延迟,开始时电平是不确定的。,语法详细讲解建立时钟,例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)
10、go=1;end,注:这两个时钟模型有些不同,行为描述的模型延迟期间一直是低电平,而门级描述的模型开始延迟有半个周期是不确定的。,语法详细讲解怎样使用任务,举例说明如何使用任务:module bus_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
11、 7:0 data_in;begin#30 data_valid=1;wait(data_rd=1);#20 data=data_in;wait(data_rd=0);#20 data=8hzz;#30 data_valid=0;end endtaskendmodule,语法详细讲解怎样使用任务,在测试模块中使用任务可以提高程序代码的效率,可以用任务把多次重复的操作包装起来。,语法详细讲解存储建模,目标学会如何用Verilog对存储器建模。学会如何用Verilog中对双向(即输入/输出)端口,(inout)建模。,存储器建模必须注意以下两个方面的问题:声明存储器容量的大小。明确对存储器访问操作
12、的权限。例如:指出可以对存储器做以下哪几种操作:1)只读 2)读写 3)同步读写 4)多次读,同时进行一次写 5)多次同步读写,同时提供一些方法保证一致性,语法详细讲解存储器建模,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(!rea
13、d_en_)read_data=memaddr;endmodule,语法详细讲解简单 ROM 建模,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建模,tim
14、escale 1ns/1nsmodule mymem(data,addr,read,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模型稍微复杂:它必须具有读写能力;进行读写时通常使用相同的数据总线;需要新技术来处理双向总线
15、;当读信号无效时,RAM模型与总线脱离,如果此时写 信号也无效,总线无驱动源,则总线进入高阻状态,这就避免了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;
16、/word of memory 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开始,这是因为存储单元是直接通过地址线寻址定位的。
17、同样地,也可以用下面的方法来定义存储器和寻址: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_file.txt 中,把初始数据存入存储器(mem)的每个单元$readmemb(
18、“mem_file.txt”,mem);注意:上面两项必须写 在initial 块中,加载这些初始化数据不需要时间。,语法详细讲解存储器的加载,语法详细讲解怎样使用双向口,使用inout关键字声明端口为双向口。inout 7:0 databus;使用双向口必需遵循下面的规则:inout口只能声明为网络连接类型,不允许把它声明为寄存器类型。(所以仿真器能确定多个驱动源的最终值。)在设计中,每次只能从一个方向来驱动inout口。例如:当使用总线读RAM中的数据时,如果同时又向RAM模型的双向数据总线写数据,就会产生逻辑竞争,导致总线数据无法确定。所以必须为inout口设计控制逻辑,只有这样才能保证
19、正确的操作。,语法详细讲解怎样使用双向口,注意:声明一个inout口,可以用来输入或输出数据。inout口默认为网络连接类型。不允许在过程块(initial 或always块)中对网络连接类型的数据进行过程赋值;但可以在过程块外把一个寄存器数据类型通过连续赋值语句赋给它(inout口),或者把它与用户定义的源语(UDP)相连。必须为inout口设计控制逻辑,用来保证正确的操作。当把inout口作为输入口时,必须通过控制逻辑禁止输出到inout口。,使用Verilog中的基本元件(bufif1)为双向口建模:,语法详细讲解双向口建模,语法详细讲解双向口建模,注意:在上页的例子中,使用en_a_b
20、和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_b的值传到bus_a
21、上,使用连续赋值为双向口建模:,语法详细讲解双向口建模,注意:在assign语句中,通过en_a_b和en_b_a控制bus_a与bus_b之间的数据交换。如果控制信号同时有效,则结果不能确定。所以必须把控制信号 en_a_b 和 en_b_a 在时间上分开。,语法详细讲解双向口建模,存储器的端口建模:,语法详细讲解双向口建模,注意:上页中存储单元在wr的下降沿到达时存入数据。上页模块在 wr处于高电平时,通过数据总线写入数据,但必须保证wr的高电平维持时间长于数据的写入时间。在rd处于高电平时,上述存储单元通过数据总线读出数据。由于此模型为单口存储模型,因此wr变低电平时,rd不能同时为高电
22、平,否则就无法确定存储器的读出/写入的结果。,语法详细讲解双向口建模,目标:学会怎样定义或调用任务和函数。学会怎样使用命名块。学会怎样禁止命名块和任务。理解有限状态机的作用,学会如何显式地为有限状态机建模。,语法详细讲解Verilog中的高级结构,通过把代码分成小的模块或者使用任务和函数,可把一项任务分成许多较小的、易于管理的部分,从而提高代码的可读性、可维护性和可重用性。任务:一般用于编写测试模块或者行为描述的模块。其中可以包含时间控制(如:#delays,wait);也可以包含input,output、inout 端口定义和参数;也可以调用其他的任务或函数,语法详细讲解Verilog中的高
23、级结构,函数:一般用于计算,或者用来代替组合逻辑。不能包含任何延迟;函数在零时间执行。函数只有input变量,虽然没有output变量,但可以通过函数名返回一个值。可以调用其他的函数,但不可以调用任务,语法详细讲解Verilog中的高级结构,注意:只能调用本模块内的任务和函数。在任务和函数中不能声明网络连接类型的变量。所有的输入和输出变量实际上都是本地寄存器。只有当任务或函数调用并执行完后,才能有返回值。举例说明:若任务或函数中包含一个forever循环时,永远无法执行完,就不可能有返回值。,语法详细讲解Verilog中的高级结构,语法详细讲解Verilog 任务,下面模块中的任务含有定时控制
24、和一个输入,并且引用了一个本模块的变量,但是没有输出,也没有双向总线和内部变量,不显示任何内容。用于定时控制的信号,例如 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 clk);endtask initial begin clk=0;a=1;b=1;neg_clocks
25、(3);/任务调用 a=0;neg_clocks(5);b=0;end endmodule,要点:任务调用是通过在Verilog模块中写入任务名来实现的。任务中可以包含input,output和inout端口变量的声明。传递给任务的变量与任务I/O端口变量的声明次序相同。虽然传递给任务的变量名可以和任务内声明的I/O端口变量名相同,但是为了使任务成为一个独立的可共用的任务块,建议不要使用与任务内声明的I/O端口变量名相同的变量名,最好给传递到任务的变量起新的不同的名字。在任务中可以使用时间控制。任务使Verilog有更广阔的适用范围。关键字disable可以用来禁止任务的执行。,语法详细讲解
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语法 要点 详细 讲解
链接地址:https://www.31ppt.com/p-5386020.html