verilog--语法进阶

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
0000 0101 1100 0011 1101 0010 0011 1111 1000 1001 1000 0001 1101 1010 0001 1101
语法详细讲解
简单ROM建模
上页所示的ROM模型说明:
如何在Verilog中用二维的寄存器组来定义存储器。 ROM中的数据保存在一个独立的文件中,如上页的右 边的虚线方框所示。 这是一种保存ROM数据的通用的方法,它可以使数据 和ROM模型分开。
nand #(period/2) ul (clk,clk,go);
initial begin go=0;
end
#(period/2) go=1;
end
注:在有些仿真器中,如果设计所用的时钟是由与其相同抽象级别的时钟 模型产生的,则仿真器的性能就能得到提高。
语法详细讲解
建立时钟
[例2]简单的带延迟的对称方波时钟:
end
end
注:这两个时钟模型有些不同,行为描述的模型延迟期间一直是低电平, 而门级描述的模型开始延迟有半个周期是不确定的。
语法详细讲解
建立时钟
[例3]. 带延迟、头一个脉冲不规则的、占空比不为1的时钟:
reg clk; initial begin reg go; wire clk; nand #(3*period/4,period/4) ul(clk,clk,go);
endmodule
语法详细讲解
并行块
上面模块的仿真输出如下:
时间
0 10 30 40 45 50 60 65 70
data_bus
8‟b0000_0000 8‟b0100_0101 8‟b0100_0110 8‟b0100_0111 8‟b1000_1110 8‟b1000_1111 8‟b1001_0000 8‟b0010_0000 8‟b0010_0001
end
语法详细讲解
建立时钟
[例2]简的带延迟的对称方波时钟:
reg clk; initial begin reg go; wire clk; nand #(period/2) ul (clk,clk,go);
clk=0;
#(period) forever
initial begin
go=0; #(period) go=1;
语法详细讲解
怎样使用任务
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=8’hzz; #30 data_valid=0; end endtask
语法详细讲解
存储建模
目标 学会如何用Verilog对存储器建模。
学会如何用Verilog中对双向(即输入/输出)端口, (inout)建模。
语法详细讲解
存储器建模
存储器建模必须注意以下两个方面的问题: 声明存储器容量的大小。 明确对存储器访问操作的权限。
例如:指出可以对存储器做以下哪几种操作: 1)只读 2)读写 3)同步读写 4)多次读,同时进行一次写 5)多次同步读写,同时提供一些方法保证一致性
语法进阶
语法详细讲解
第一部分 Verilog测试模块的编写
目的:
复习如何编写较复杂的测试文件,对所做的设计 进行完整的测试和验证。 掌握组织模块测试的常用方法;学会编写常用的 测试代码。
语法详细讲解
用Verilog设计的步骤
include 文件
仿真器
厂家元件
库文件
设计文件
编译器
输入文件: 激励和期望 的输出信号
语法详细讲解
简单RAM建模
`timescale 1ns/1ns module 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 words //从存储器读出到总线上 assign data=read? memory[addr]:4‟bz; //从总线写入存储器 always @ (posedge write) memory[addr]=data; endmodule
语法详细讲解
建立时钟
虽然有时在设计中会包含时钟,但时钟通常用在测试模块中。下面 三个例子分别说明如何在门级和行为级建立不同波形的时钟模型。 [例1] 简单的对称方波时钟: reg clk; reg go; wire clk;
always begin
#period/2 clk=0; #period/2 clk=1;
时间
80 85
data_bus
8‟b0010_0010 8‟b0100_0100
90
100 105 110 120 125 140
8‟b0100_0101
8‟b0010_0001 8‟b0100_0110 8‟b1000_1100 8‟b1000_1110 8‟b0001_1100 8‟b0000_1111
#(period+1) clk=1;
#(period/2-1) forever begin
initial begin
#(period/4+1) go=0; #(5*period/4-1) go=1;
#(period/4) clk=0;
#(3*period/4) clk=1; end
end
注:这两个时钟模型也有些不同,行为描述的模 型一开始就有确定的电平,而门级描述的模型有 延迟, 开始时电平是不确定的。
语法详细讲解
简单 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: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=mem[addr]; endmodule ROM的数据存储 在另外的一个独 立的文件中 my_rom_data
reg [wordsize:1] mem [0 : words-1]; //mem declaration
//output one word of memory wire [wordsize:1] mem_word=mem[address]; endmodule
语法详细讲解
存储量可变的只读存储器建模
endmodule
语法详细讲解
怎样使用任务
在测试模块中使用任务可以提高程序代码的效率,可以用 任务把多次重复的操作包装起来。
cpu_data clk data_valid data_rd read_cpu_state
wait wait data1 data2 wait data3 data4 wait
语法详细讲解
强制激励
#20 deassign top.dut.fsml.state_reg; end force 和 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所赋 的值,
语法详细讲解
强制激励
在一个过程块中,可以用两种不同的方式对信号变量或表达式 进行连续赋值。
过程连续赋值往往是不可以综合的,通常用在测试模块中。 两种方式都有各自配套的命令来停止赋值过程。 两种不同方式均不允许赋值语句间的时间控制。 assign和deassign 适用于对寄存器类型的信号(例如:RTL级上 的节点或测试模块中在多个地方被赋值的信号)进行赋值。 initial begin #10 assign top.dut.fsml.state_reg = `init_state;
语法详细讲解
简单RAM建模
RAM模型比ROM模型稍微复杂:
它必须具有读写能力; 进行读写时通常使用相同的数据总线;
需要新技术来处理双向总线;
当读信号无效时,RAM模型与总线脱离,如果此时写 信号也无效,总线无驱动源,则总线进入高阻状态,
这就避免了RAM中的读写竞争。
上页的 RAM 模块是可综合的,但综合出来是一大堆寄存器,占 比较大的面积,经济上不太合算。
仿真器
输出文件:激 励和实际输出 的信号
注:虚线表示编译器能检查输入文件的可读性和是否存在以及是否允许生成输出文件
语法详细讲解
测试平台的组成
激励 信号
需要验证的 设计
简单的测试平台
激励信号
和用于验
证的结果 数据
需要验证的 设计 复杂的测试平台
语法详细讲解
并行块
在测试块中常用到fork…join块。用并行块能表示以同一个时间起点算起的多个事
reg clk; initial begin reg go; wire clk; nand #(period/2) ul (clk,clk,go);
clk=0;
#(period) forever
initial begin
go=0; #(period) go=1;
#(period/2) clk=!clk
件的运行,并行地执行复杂的过程结构,如循环或任务。举例说明如下:
module inline_tb; reg [7:0] data_bus; initial fork data_bus= 8’b00; #10 data_bus = 8’h45;
//这两个repeat开始执行时间不同,但能同时运行。
#20 repeat (10) #10 data_bus = data_bus +1; #25 repeat (5) # 20 data_bus = data_bus <<1; #140 data_bua = 8’h0f; join
语法详细讲解
强制激励
当执行release后,则信号的值为assign所赋 的值。 如果用force对同一个信号赋了几次值,再执行release,则所有 赋的值均不再存在。 可以对信号的某(确定)位、某些(确定)位或拼接的信号, 使用force和release赋值;但不能对信号的可变位使用force和 release 来赋值。 不能对寄存器类型的信号某位或某些位使用 assign 和deassign 来赋值。
#(period/2) clk=!clk
end
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 (8’b0000_0000); cpu_driver (8’b1010_1010); cpu_driver (8’b0101_0101); end
语法详细讲解
存储量可变的只读存储器建模
例:
module scalable_ROM (mem_word, address); parameter addr_bits=8; //size of address bus parameter wordsize=8; //width of a word parameter words=(1<<addr_bits); //size of mem output [wordsize:1] mem_word; input [addr_bits:1] address; //word of memory //address bus
相关文档
最新文档