第14章对验证的支持.ppt

上传人:本田雅阁 文档编号:3125777 上传时间:2019-07-13 格式:PPT 页数:50 大小:237.52KB
返回 下载 相关 举报
第14章对验证的支持.ppt_第1页
第1页 / 共50页
第14章对验证的支持.ppt_第2页
第2页 / 共50页
第14章对验证的支持.ppt_第3页
第3页 / 共50页
第14章对验证的支持.ppt_第4页
第4页 / 共50页
第14章对验证的支持.ppt_第5页
第5页 / 共50页
点击查看更多>>
资源描述

《第14章对验证的支持.ppt》由会员分享,可在线阅读,更多相关《第14章对验证的支持.ppt(50页珍藏版)》请在三一文库上搜索。

1、第14章 对验证的支持,学习内容 理解Verilog文本输出 理解不同的读取仿真时间的系统函数 理解 Verilog文件I/O功能,验证系统中的任务(task)及函数(function),Verilog读取当前仿真时间的系统函数 $time $stime $realtime Verilog支持文本输出的系统任务: $display $strobe $write $monitor,仿真时间,访问仿真时间 $time,$realtime,和$stime函数返回当前仿真时间。 这些函数的返回值使用调用模块中timescale定义的时间单位 $time返回一个64位整数时间值。 $stime返回一个3

2、2位整数时间值。 $realtime返回一个实数时间值。 $stime函数返回一个32位整数时间值。对大于232的时间,返回模232的值。使用它可以节省显示及打印空间。,输出格式化时间信息,timescale 10ns / 100ps module top; reg in1; not m1( o1, in1); initial begin $timeformat(-9, 2, “ns“, 10); in1 = 0; #8 in1 = 1; #10 $display(“%t %b %b“, $realtime, in1, o1); #10 $finish; end endmodule,unit:

3、0(s)到-15(fs)之间的整数,表示时间度量 precision:要显示的十进制小数位数。 suffix:在时间值后显示的字符串 min_width:显示前三项的最小宽度,若使用多个timescale,以最小的时间精度显示时间值。 可用系统任务$timeformat结合格式符%t全局控制时间显示方式。 $timeformat系统任务的语法为: $timeformat(,);,输出格式化时间信息,timescale 1 ns / 10 ps module top; reg in1; not #9.53 n1 (o1, in1); initial begin $display(“time re

4、altime stime t in1 t o1 “); $timeformat(-9, 2, “ns“, 10); $monitor(“%d %t %d t %b t %b“, $time, $realtime, $stime, in1, o1); in1 = 0; #10 in1 = 1; #10 $finish; end endmodule,time realtime stime in1 o1 0 0.00ns 0 0 x 10 9.53ns 10 0 1 10 10.00ns 10 1 1 20 19.53ns 20 1 0,输出格式化时间信息,对#延迟,Verilog将延迟值舍入最近(

5、四舍五入)时间精度值。 例如,上面的例子修改为:,timescale 1ns/ 100ps not #9.42 n1 (o1, in1); 结果为: time realtime stime in1 o1 0 0.00ns 0 0 x 9 9.40ns 9 0 1 10 10.00ns 10 1 1 19 19.40ns 19 1 0,timescale 1ns/ 100ps not #9.49 n1 (o1, in1); 结果为: time realtime stime in1 o1 0 0.00ns 0 0 x 9 9.50ns 9 0 1 10 10.00ns 10 1 1 19 19.5

6、0ns 19 1 0,显示信号值 $display,$display输出参数列表中信号的当前值。 语法:$display(“ format_specifiers”, ) $display输出时自动换行。 $display ($ time, “%b t %h t %d t %o”, sig1, sig2, sig3, sig4); $display ($ time, “%b t”, sig1, “%h t”, sig2, “% d t”, sig3, “%o”, sig4); $display支持二进制、八进制、十进制和十六进制。缺省基数为十进制。 $display (sig1, sig2, s

7、ig3, sig4); $displayb (sig1, sig2, sig3, sig4); $displayo (sig1, sig2, sig3, sig4); $displayh (sig1, sig2, sig3, sig4);,格式符,转义符,显示信号值$write和$strobe,$write与$display相同,不同的是不会自动换行。 $write($time, “%b t %h t %d t %o t”, sig1, sig2, sig3, sig4); $strobe与$display相同,不同的是在仿真时间前进之前的信号值。而$display和$write立即显示信号值

8、。也就是说$strobe显示稳定状态信号值,而$display和$write可以显示信号的中间状态值。 $strobe($time, “%b t %h t %d t %o t”, sig1, sig2, sig3, sig4); $write和$strobe都支持多种数基,缺省为十进制。 $writeb $strobeb $writeo $strobeo $writeh $strobeh,显示信号值$write和$strobe,下面是模块textio仿真的输出: $writeb输出: 0 xxxxxxxx x 注意data是32位数据,由8位十六进制数表示。时间以没有前导零的十进制形式输出。

9、缺省情况下,值以十进制显示,忽略前导零,与%0d格式符相同。可以在一个格式化符前插入一个0使Verilog忽略开头的零。 $displayh: 00000000000000f 00000010 1 注意当前时间,一个64位量,需要16个十六进制的数。 $display: 10 20 $strobe: 10 30,module textio; reg flag; reg 31: 0 data; initial begin $writeb(“%d“, $time, ,“%h t“, data, , flag, “n“); #15 flag = 1; data = 16; $displayh($ti

10、me, ,data, , flag); end initial begin #10 data = 20; $strobe($time, , data); $display($time, , data); data = 30; end endmodule,监视信号值$monitor,$monitor持续监视参数列表中的变量。 在一个时间片中,参数表中任何信号发生变化,$monitor将在仿真时间前进前显示参数表的信号值。 后面的$monitor将覆盖前面的$monitor。 可以用系统任务$monitoron和$monitoroff控制持续监视。 $monitor支持多种基数。缺省为十进制。 $

11、monitor ($ time, “%b t %h t %d t %o”, sig1, sig2, sig3, sig4);,监示信号值$monitor,$monitor是唯一的不断输出信号值的系统任务。其它系统任务在返回值之后就结束。 $monitor和$strobe一样,显示参数列表中信号的稳定状态值,也就是在仿真时间前进之前显示信号。在一个时间步中,参数列表中信号值的任何变化将触发$monitor 。但$time,$stime,$realtime不能触发。 任何后续的$monitor覆盖前面调用的$monitor。只有新的$monitor的参数列表中的信号被监视,而前面的$monitor

12、的参数则不被监视。 可以用$monitoron和$monitoroff系统任务控制持续监视,使用户可以在仿真时只监视特定时间段的信号。 $monitor参数列表的形式与$display相同。 $monitor支持多种基数。缺省为十进制。 $monitorb $monitoro $monitorh,文件输出,$fopen打开一个文件并返回一个多通道描述符(MCD)。 MCD是与文件唯一对应的32位无符号整数。 如果文件不能打开并进行写操作,MCD将等于0。 如果文件成功打开,MCD中的一位将被置位。 以$f开始的显示系统任务将输出写入与MCD相对应的文件中。,. . . integer MCD1

13、; MCD1 = $fopen(“); $fdisplay( MCD1, P1, P2, , Pn); $fwrite( MCD1, P1, P2, , Pn); $fstrobe( MCD1, P1, P2, , Pn); $fmonitor( MCD1, P1, P2, , Pn); $fclose( MCD1); . . .,文件输出,$fopen打开参数中指定的文件并返回一个32位无符号 整数MCD,MCD是与文件一一对应的多通道描述符。如果文件不能打开并进行写操作,它返回0。 $fclose关闭MCD指定的通道。 输出信息到log文件和标准输出的四个格式化显示任务($display,

14、 $write, $monitor, $strobe)都有相对应的任务用于向指定文件输出。 这些对应的任务($fdisplay,$fwrite,$fmonitor,$fstrobe)的参数形式与对应的任务相同,只有一个例外:第一个参数必须是一个指定向何哪个文件输出的MCD。MCD可以是一个表达式,但其值必须是一个32位的无符号整数。这个值决定了该任务向哪个打开的文件写入。 MCD可以看作由32个标志构成的组,每个标志代表一个单一的输出通道。,文件输出,. . . integer messages, broadcast, cpu_chann, alu_chann; initial begin c

15、pu_chann = $fopen(“ cpu.dat“); if(! cpu_chann) $finish; alu_chann = $fopen(“ alu.dat“); if(! alu_chann) $finish; / channel to both cpu. dat and alu. dat messages = cpu_chann | alu_chann; / channel to both files, standard out, and verilog. log broadcast = 1 | messages; end always ( posedge clock) / p

16、rint the following to alu. dat $fdisplay( alu_chann, “acc= %h f=%h a=%h b=%h“, acc, f, a, b); /* at every reset print a message to alu. dat, cpu. dat, standard output and the verilog. log file */ always ( negedge reset) $fdisplay( broadcast, “system reset at time %d“, $time); . . .,必须声明为integer,通道0(

17、编号为1)为标准输出及verilog.log,文件输入,Verilog中有两个系统任务可以将数据文件读入寄存器组。一个读取二进制数据,另一个读取十六进制数据: $readmemb $readmemb (“file_name“, ); $readmemb (“file_name“, , ); $readmemb (“file_name“, , , ); $readmemh $readmemh (“ file_name“, ); $readmemh (“ file_name“, , ); $readmemh (“ file_name“, , , );,文件输入,系统任务$readmemb和$rea

18、dmemh从一个文本文件读取数据并写入存储器。 如果数据为二进制,使用$readmemb;如果数据为十六进制,使用$readmemh。 filename指定要调入的文件。 mem_name指定存储器名。 start和finish决定存储器将被装载的地址。Start为开始地址,finish为结束地址。如果不指定开始和结束地址,$readmem按从低端开始读入数据,与说明顺序无关。,文件输入,$readmemb和$readmemh的文件格式 : $readmemb(“mem_file. txt“, mema);,0000_0000 0110_0001 0011_0010 / 地址3255没有定义

19、100 / hex 1111_1100 /地址2571022没有定义 3FF 1110_0010,文本文件:mem_file.txt,声明的存储器组 reg 0:7 mema0:1023,module readmem; reg 0:7 mema 0:1023 initial $readmemb(“mem_file.txt”, mema); endmodule,文件输入,$readmemb和$readmemh的文件格式 : $readmemb(“mem_file. txt“, mema);,可以指定二进制(b)或十六进制(h)数 用下划线(_)提高可读性。 可以包含单行或多行注释。 可以用空格和

20、换行区分存储器字。 可以给后面的值设定一个特定的地址,格式为: (hex_address) 十六进制地址的大小写不敏感。 在和数字之间不允许有空格。,复习,问题: 哪个系统任务显示参数列表中信号的稳定状态值? 每次能打开多少个输出文件?,解答: 系统任务$monitor和$strobe显示参数列表中信号的稳定状态值。这些任务在时间前进之前输出信号值。 每次只能打开一个输出文件,包括已由仿真器打开的任何log文件。,第十五章 Verilog Test Bench使用简介,学习内容: 用一个复杂的test bench复习设计的组织与仿真 建立test bench通常使用的编码风格及方法,设计组织,

21、虚线表示编译时检测输入文件是否存在及可读并允许生成输出文件。,test bench组织,简单的test bench向要验证的设计提供向量,人工验证输出。 复杂的test bench是自检测的,其结果自动验证。,简单的test bench,复杂的test bench,并行块,forkjoin块在测试文件中很常用。他们的并行特性使用户可以说明绝对时间,并且可以并行的执行复杂的过程结构,如循环或任务。,module inline_ tb; reg 7: 0 data_ bus; / instance of DUT initial fork data_bus = 8b00; #10 data_bus

22、= 8h45; #20 repeat (10) #10 data_bus = data_bus + 1; #25 repeat (5) #20 data_bus = data_bus 1; #140 data_bus = 8h0f; join endmodule,上面的两个repeat循环从不同时间开始,并行执行。象这样的特殊的激励集在单个的beginend块中将很难实现。,Time | data_ bus 0 | 8b0000_0000 10 | 8b0100_0101 30 | 8b0100_0110 40 | 8b0100_0111 45 | 8b1000_1110 50 | 8b100

23、0_1111 60 | 8b1001_0000 65 | 8b0010_0000 70 | 8b0010_0001 80 | 8b0010_0010 85 | 8b0100_0100 90 | 8b0100_0101 100 | 8b0100_0110 105 | 8b1000_1100 110 | 8b1000_1101 120 | 8b1000_1110 125 | 8b0001_1100 140 | 8b0000_1111,包含文件,包含文件用于读入代码的重复部分或公共数据。,module clk_gen (clk); output clk; reg clk; include “comm

24、on.txt“ initial begin while ($ time sim_end) begin clk = initial_clock; #(period/2) clk = !initial_clock; #(period/2); end $finish; end endmodule,在上面的例子中,公共参数在一个独立的文件中定义。此文件在不同的仿真中可被不同的测试文件调用。,/ common. txt / clock and simulator constants parameter initial_clock = 1; parameter period = 15; parameter

25、 max_cyc = 100; parameter sim_end = period * max_cyc,施加激励,产生激励并加到设计有很多 种方法。一些常用的方法有: 从一个initial块中施加线激励 从一个循环或always块施加激励 从一个向量或整数数组施加激励 记录一个仿真过程,然后在另一个仿真中回放施加激励,线性激励,线性激励有以下特性: 只有变量的值改变时才列出 易于定义复杂的时序关系 对一个复杂的测试,测试基准(test bench)可能非常大,module inline_ tb; reg 7: 0 data_ bus, addr; wire 7: 0 results; DUT

26、 u1 (results, data_ bus, addr); initial fork data_bus = 8h00; addr = 8h3f; #10 data_ bus = 8h45; #15 addr = 8hf0; #40 data_ bus = 8h0f; #60 $finish; join endmodule,循环激励,从循环产生激励有以下特性: 在每一次循环,修改同一组激励变量 时序关系规则 代码紧凑,module loop_tb; reg clk; reg 7:0 stimulus; wire 7:0 results; integer i; DUT u1 (results,

27、 stimulus); always begin / clock generation clk = 1; #5 clk = 0; #5 end initial begin for (i = 0; i 256; i = i + 1) ( negedge clk) stimulus = i; #20 $finish; end endmodule,数组激励,从数组产生激励有以下特性: 在每次反复中,修改同一组激励变量 激励数组可以直接从文件中读取,module array_ tb; reg 7: 0 data_ bus, stim_ array 0: 15; / 数组 integer i; DUT

28、u1 (results, stimulus); initial begin / 从数组读入数据 #20 stimulus = stim_array0; #30 stimulus = stim_array15; / 线激励 #20 stimulus = stim_array1; for (i = 14; i 1; i = i - 1) / 循环 #50 stimulus = stim_arrayi ; #30 $finish; end endmodule,矢量采样,在仿真过程中可以对激励和响应矢量进行采样,作为其它仿真的激励和期望结果。,module capture_tb; parameter

29、period = 20 reg 7:0 in_vec, out_vec; integer RESULTS, STIMULUS; DUT u1 (out_ vec, in_ vec); initial begin STIMULUS = $fopen(“stimulus. txt“) ; RESULTS = $fopen(“results. txt“) ; fork if (STIMULUS != 0 ) forever #( period/2) $fstrobeb (STIMULUS, “%b“, in_vec); if (RESULTS != 0 ) #( period/2) forever

30、#( period/2) $fstrobeb (RESULTS, “%b“, out_vec); join end endmodule,矢量回放,保存在文件中的矢量反过来可以作为激励,module read_file_tb; parameter num_vecs = 256; reg 7:0 data_bus; reg 7:0 stim num_vecs-1:0; integer i; DUT u1 (results, data_bus) initial begin / Vectors are loaded $readmemb (“vec. txt“, stim); for (i =0; i

31、num_vecs ; i = i + 1) #50 data_bus = stimi; end endmodule,/ 激励文件vec.txt 00111000 00111001 00111010 00111100 00110000 00101000 00011000 01111000 10111000 . .,使用矢量文件输入/输出的优点: 激励修改简单 设计反复验证时直接使用工具比较矢量文件。,错误及警告报告,使用文本或文件输出类的系统任务报告错误及警告,always ( posedge par_err) $display (“ error-bus parity errors detect

32、ed“); always ( posedge cor_err) $display(“warning-correctable error detected“);,一个更为复杂的test bench可以: 不但能报告错误,而能进行一些动作,如取消一个激励块并跳转到下一个激励。 在内部保持错误跟踪,并在每次测试结束时产生一个错误报告。,强制激励,在过程块中,可以用两种持续赋值语句驱动一个值或表达式到一个信号。 过程持续赋值通常不可综合,所以它们通常用于测试基准描述。 对每一种持续赋值,都有对应的命令停止信号赋值。 不允许在赋值语句内部出现时序控制。 对一个寄存器使用assign和deassign,将

33、覆盖所有其他在该信号上的赋值。这个寄存器可以是RTL设计中的一个节点或测试基准中在多个地方赋值的信号等。 initial begin #10 assign top.dut.fsm1.state_reg = init_state ; #20 deassign top.dut.fsm1.state_reg ; end 在register和net上(例如一个门级扫描寄存器的输出)使用force和release,将覆盖该信号上的所有其他驱动。 initial begin #10 force top. dut. counter. scan_ reg. q = 0 ; #20 release top. d

34、ut. counter. scan_ reg. q ; end,强制激励,可以强制(force)并释放一个信号的指定位、部分位或连接,但位的指定不能是一个变量(例如out_veci) 不能对register的一位或部分位使用assign和deassign 对同一个信号,force覆盖assign。 后面的assign或force语句覆盖以前相同类型的语句。 如果对一个信号先assign然后force,它将保持force值。在对其进行release后,信号为assign值。 如果在一个信号上force多个值,然后release该信号,则不出现任何force值。,在上面两个例子中,在 net或re

35、gister上所赋的常数值,覆盖所有在时刻10和时刻20之间可能发生在该信号上的其他任何赋值或驱动。如果所赋值是一个表达式,则该表达式将被持续计算。,建立时钟,例1:虽然有时候在设计中给出时钟,但通常时钟是测试基准中建立。 下面介绍如何产生不同的时钟波形。同时给出用门级和行为级描述方法 下面是一个简单对称时钟的例子:,reg ck; always begin #( period/2) ck = 0; #( period/2) ck = 1; end,reg go; wire ck; nand #( period/2) u1 (ck, ck, go); initial begin go = 0;

36、 #( period/2) go = 1; end,注意:在一些仿真器中,时钟与设计使用相同的抽象级描述时,仿真性能会好一些。,产生的波形(假定period为20),建立时钟,例2:有启动延时的对称时钟的例子:,reg ck; initial begin ck = 0; #( period) forever #( period/2) ck = !ck; end,reg go; wire ck; nand #( period/2) u1 (ck, ck, go); initial begin go = 0; #(period) go = 1; end,注意:在行为描述中,在时间0将CK初始化为0

37、;而在结构描述中,直到period/2才影响CK值。当go信号在时间0初始化时,CK值到period/2才变化。可以使用特殊命令force和release立即影响CK值。,产生的波形(假定period为20),建立时钟,例3:有不规则启动延时的不对称时钟的例子:,注意:在行为描述中,CK值立刻被影响;而在结构描述中,在传播延时后才输出正确波形。,产生的波形(假定period为20),reg ck; initial begin #(period + 1) ck = 1; #(period/2 1) forever begin #(period/4) ck = 0; #(3*period/4) c

38、k = 1; end end,reg go; wire ck; nand #(3*period/4, period/4) u1(ck, ck, go); initial begin #(period/4 + 1) go = 0; #(5*period/4 1) go = 1; end,使用task,在test bench中使用task可以压缩重复操作,提高代码效率。,module bus_ctrl_tb; reg 7: 0 data; reg data_valid, data_rd; cpu u1 (data_valid, data,data_rd); initial begin cpu_dr

39、iver (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 (data_rd = 0); #20 data = 8hzz; #30 data_valid = 0; end endtask endmodule,使用task,产生的波形,复习,问题: 什么操作可以容易的在forkjoin块做到,

40、而不容易在beginend块做到? 通常怎样产生规则激励和不规则激励? 从一个文件中读取激励时使用什么数据类型? 在行为级时钟模型中能做哪些在门级时钟模型中很难或不能作到的事?,解答: forkjoin块中不但能够赋值,还可以并行执行循环、条件语句、任务或函数调用。 循环或always块能有效地产生规则激励,不规则激励适合用在initial块产生。 用寄存器组(存储器)并用$readmem系统任务从一个文件以读取向量。 行为级代码可以很容易地产生一个启动时间不规则的时钟波形,并且可以在时刻零初始化时钟。,第16章 存储器建模,学习内容: 如何描述存储器 如何描述双向端口,存储器件建模,描述存储

41、器必须做两件事: 说明一个适当容量的存储器。 提供内容访问的级别,例如: 只读 读和写 写同时读 多个读操作,同时进行单个写操作 同时有多个读和多个写操作,有保证一致性的方法,简单ROM描述,下面的ROM描述中使用二维寄存器组定义了一个存储器mem。ROM的数据单独保存在文件my_rom_data中,如右边所示。通常用这种方法使ROM数据独立于ROM描述。,timescale 1ns/10ps module myrom (read_data, addr, read_en_); input read_en_; input 3:0 addr; output 3:0 read_data; reg 3

42、: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,简单的RAM描述,RAM描述比ROM略微复杂,因为必须既有读功能又有写功能,而读写通常使用同一数据总线。这要求使用新的处理双向数据线的建模技术。在下面的例子中,若读端口未使能,则模型不驱动数据总线;此时若数据总线没有写数据驱动,则总线为高阻态Z。这避免了RAM写入时的冲突。,timescale 1ns /1

43、ns module mymem (data, addr, read, write); inout 3:0 data; input 3:0 addr; input read, write; reg 3:0 memory 0:15; / 16*4 / 读 assign data = read ? memoryaddr : 4bz; / 写 always ( posedge write) memoryaddr = data; endmodule,这个描述可综合,但许多工具仅仅产生一个寄存器堆,因此与一个真正的存储器相比耗费更多的面积。,参数化存储器描述,在下面的例子中,给出如何定义一个字长和地址均参

44、数化的只读存储器件。,module scalable_ROM (mem_word, address); parameter addr_bits = 8; / 地址总线宽度 parameter wordsize = 8; / 字宽 parameter words = (1 addr_bits); / mem容量 output wordsize:1 mem_word; / 存储器字 input addr_bits:1 address; / 地址总线 reg wordsize:1 mem 0 : words-1; / mem声明 / 输出存储器的一个字 wire wordsize:1 mem_wor

45、d = memaddress; endmodule,例中存储器字范围从0而不是1开始,因为存储器直接用地址线确定地址。也可以用下面的方式声明存储器并寻址。 reg wordsize:1 mem 1:words; / 从地址1开始的存储器 / 存储器寻址时地址必须加1 wire wordsize:1 mem_word = mem address + 1;,存储器数据装入,可以使用循环或系统任务给存储器装入初始化数据 用循环给存储器的每个字赋值 for (i= 0; i memsize; i = i+ 1) / initialize memory mema i = wordsize 1b1; 调用

46、系统任务$readmem $readmemb(“mem_file. txt“, mema);,可以用 系统任务$readmem给一个ROM或RAM加载数据。对于ROM,开始时写入的数据就是其实际内容。对于RAM,可以通过初始化,而不是用不同的写周期给每个字装入数据以减少仿真时间。,使用双向端口,用关键词inout声明一个双向端口 inout 7:0 databus; 双向端口声明遵循下列规则: inout端口不能声明为寄存器类型,只能是net类型。 这样仿真器若有多个驱动时可以确定结果值。 对inout端口可以从任意一个方向驱动数据。端口数据类型缺省为net类型。不能对net进行过程赋值,只能

47、在过程块外部持续赋值,或将它连接到基本单元。 在同一时间应只从一个方向驱动inout端口。 例如:在RAM模型中,如果使用双向数据总线读取RAM数据,同时在数据总线上驱动写数据,则会产生逻辑冲突,使数据总线变为未知。 必须设计与inout端口相关的逻辑以确保正确操作。当把该端口作为输入使用时,必须禁止输出逻辑。,双向端口建模 使用基本单元建模,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; bufif1 b1 (bus_b, bus_a, en_a_b); buf

48、if1 b2 (bus_a, bus_b, en_b_a); / Structural module logic endmodule,若en_a_b=1,基本单元b1使能,bus_a数据传送到bus_b,若en_b_a=1,基本单元b2使能,bus_b数据传送到bus_a,信号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; assign bus_b = en_a_b ? bus_a : bz; assign bus_a = en_b_a ? bus_b : bz; / Structural module logic endmodule,若en_a_b=1,赋值语句驱动bus_a数据到bus_b,若en_b_a=1,赋值语句驱动bus_b值到bus_a,信号en_a_b和en_b_a控制使能,双向端口建模 存储器端口建模,modu

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1