VerlogHDL语言

模组

  • 针对阶层化的设计观念,在 Verilog 中提供一种模组 ( module ) 的架构。
  • 模组中可以取用其他模组的别名,本身也可以被其他的模组所取用,所以可以先写基本元件线路的模组,在经由取用得到较大的模组,此符合由下到上的方法。
  • 模组在取用时,所看到的只是其输出与输入的值,与内部的描述层次无关,可以先以行为层次来描述基本元件,并先取用,此符合上到下的设计方法。
  • 在 Verilog 中模组的宣告是用关键字 module endmodule。module 後需加一个用以识别的模组名称 ( module_name ),然後是宣告一个模组的输入与输出的埠列 ( module_terminal_list ),在模组的最後要加上 endmodule 。其架构如下所示:
  • module  <module_name>  (<module_terminal_list>);    

    ...    
    <module internals>
    ...    
    ...    
    endmodule

学习目标:

* 了解空白(Whitespace) ,

注解(Comments),

运算子(Operators),

数字(Number),

字串(Strings),

定义名称(Idntifers),

语法协定(Lexical Conventions)。


* 定义数值组(Value Set),

接线(Nets),

暂存器(Registers),

向量(Vectors),

时间,

阵列(Arrays),

记忆体 (Memories)

参数(Parameters),

字串(Strings)的资料型态(Data Types)。


* 说明有用的系统任务(system tasks):

资讯显示(Displaying information),

资讯监视(Monitoring information),

中止 (Stopping) 

完成(finishing)模拟。
* 说明简单的组译指令(Compiler Directives)。

 

3.1 语法协定(Lexical Conventions)

Verilog 的语法协定与 C 语言是非常类似的

3.1.1 空白(Whitespace)

空白包含有: 空格 (blank spaces, \b),栏位 (tabs, \t),和换行(newlines, \n) ,除了分隔标记的空白和字串中的空白外,皆忽略。

3.1.2 注解(Comments)

注解是为了使程式易读 (readability)或文件化 (documentation)。
 

a=b && c; //这是一单行注解 
/* 这是一 
    多行注解 */ 

/* 这是一 /*非法 */ 注解 */

 

3.1.3 运算子(Operators)

运算元有叁种形式:一元 (unary),二元(binary),和叁元 (ternary)。
 

a=~b; // ~ 是一元运算子. b是运算元 
a=b && c; //  && 是二元运算子. b和c是运算元 
a=b ? c : d; // ?: 是叁元运算子. b,c和d是运算元 

 

3.1.4 数字规格(Number Specification)

Verilog 有规定长度 (sized),不定长度 (unsized)二种数字规格.

规定长度之数字(Sized numbers)

规定长度之数字以 <size>'<base format><number>来表示.
<size>是以十进位来表示数字的位数(bits),<base format>是用以定义此数为十进位('d或'D),十六进位('h或'H),二进位('b或'B),八进位('o或'O)。
 

8'b11111111 // 这是一 8-bit 二进位数 
16'habcd // 这是一  16-bit 十六进位数 
16'd255 // 这是一 16-bit 十进位数

不规定长度之数字(Unsized numbers)

* 不规定长度之数字不使用<size>去规定数字之位元数大小,而是使用模拟器或硬体内定规格(必须大於32位元)。
* 若无<base format> 则定义为十进制。
 

2345 // 定义为 32 bits 十进位数 
'hc3e  // 32 bits  十六进位数 
'o2  // 32 bits 八进位数

x或z值

x 是代表不确定的值,z 是代表高阻抗。
 

12'h1xx // 这是一  12-bit  十六进位数 ;最小8位元为不确定之值 
6'hx    // 这是一  6-bit  十六进位数 
32'bz   // 这是一  32-bit 高阻抗

负数(Negative numbers)

将负号放在<size>之前即代表该数之负数。
 

-8'd3 //用 8-bit二补数表示负叁 
4'd-2 // 不正确的表示法

底线(Underscore characters)和问号(Question marks)

* 底线 "_"的功用在於增加可读性,并无特别的功用与功能。
* 但是需要注意的是,第一个字元不能使用底线。
* 问号 "?"是与 "z"是同义的,其目的是增加可读性。
 

12'b1111_0000_1010 // 与12'b111100001010同 
4'b10??  // 与4'b10zz同

 

3.1.5 字串(Strings)

字串之所有字元必须在同一行上。
 

"Hello Verilog World" //是一个字串 
"a/b" //是一个字串

 

3.1.6 定义名称(Identifers)与关键字(Keywords)

* 关键字是一组特殊的定义名称,其功用是为了定义程式语言架构。
* 定义名称是在程式语言中所给予物件的名称。
* 定义名称可由字母,数字,底线和钱号($)所组成。
* 定义名称的大小写是有分别的,且不能以钱号做开头。
 

wire value; // wire 是关键字   value是定义名称 
output out; // output 是关键字   out是定义名称

 

3.2 数据型态(Data Types)

3.2.1 数值组(Value Set)

Verilog提供四种数值和八种强度(Strengths)。四种数值位准(value level)如下:
 

数值位准
实际电路状态
0
逻辑0,假(false)
1
逻辑1,真(true)
x
不确定值(Unknown value)
z
 高阻抗(High impedance),悬接(floating state)

数值位准为0、1有八种强度如下:
 

强度位准
型态
程度
supply
Driving
最强
storng
Driving
 
pull
Driving
 
large
Storage
 
weak
Driving
 
medium
Storage
 
small
Storage
 
highz
High Impedance
最弱

* 其目的是为了解决在实际逻辑电路中,二个不同强度的驱动信号(driver)冲突(conflicts) 的问题。
* 如果strong1 和 weak0接在同一条线上,结果会是 strong1。

 

3.2.2 接点(Nets)

 接点是连接硬体元件之点。在Fig3.1 接点 a是及闸gate1的输出,其值为接点b AND 接点c 的结果。
 
 fig3.1

 接点之最主要的关键字为wire。
 

wire a; //宣告上面电路中一个接线a 
wire b,c; //宣告上面电路中接线b,c 
wire d = 1'b0; //在宣告时设定接线d为一固定值0

 

3.2.3 暂存器(Registers)

在Verilog 中暂存器的功用与变数非常相近,可以直接给一个数值,不用像节点一样需要驱动才能改变数值。暂存器的关键字是 reg,内定值是 x。
 

reg reset; //宣告一个变数来持留(hold)数值 
initial // 这一个架构将於後面章节讨论 
begin 
  reset = 1'b1; //设定reset之初始值为1来重设电路 
  #100 reset = 1'b0; // 在 100个模拟时间後,设定reset为0 
end

3.2.4 向量(Vectors)

节点和暂存器皆可定义为向量,若无定义位元长度,则以一个位元(纯量)计。
 

wire a; //定义为纯量接线变数 
wire [7:0] bus; // 8-bit 汇流排 
wire [31:0] busA,busB,busC; //3 个 32-bit 宽度的汇流排 
reg clock; //定义为纯量暂存器变数 
reg [0:40] virtual_addr; //向量暂存器变数, 41 bits宽度虚位址

向量可定义为[high#:low#] or [low#:high#],但是中括号左边者为最大位元。
 

busA[7] // 汇流排A之第七个位元 
bus[2:0] // 汇流排之最末叁个位元,若使用bus[0:2]为非法的 
virtual_addr[0:1] //虚位址之最高叁个位元

 

3.2.5 整数、实数、和时间暂存资料型态 (Integer、Real、and Time Register Data Types)

整数

整数是以关键字 integer做宣告,虽然我们可以用 reg来做一般变数的宣告,但是一些整数变数以 integer做宣告是较便利的,如计数(counting)。
 

integer counter; //一般用途的变数 
initial 
   counter = -2; //将负2存在 counter中

实数

实数是以关键字real做宣告。
 

real delta; //宣告一实数变数 delta 
inital 
begin 
   delta = 4e10; //delta 被指定一科学表示式 
   delta = 2.13; //delta  被指定一数值 2.13 
end 
integer i; //宣告一整数变数 i 
initial 
   i = delat; //i 的数值为 2 (rounded value of 2.13)

时间

时间是以关键字time做宣告,其功用是储存模拟时间(simulation time),最少要为64bits的资料。
 

time save_sim_time; //定义时间变数 save_sim_time 
initial 
   save_sim_time = $time; //储存目前模拟时间

 

3.2.6 阵列(Arrays)

阵列之内容可以是整数、暂存资料、时间、和向量,但不能为实数。其表示法为<array_name>[<subscript>] ,且不能为多维阵列。
 

integer count[0:7]; //  8个 count 变数的阵列 
reg bool[31:0]; // 32 个一位元布林暂存器变数的阵列 
time chk_point[1:100]; //100  个时间核对点(checkpoint)变数的阵列 
reg [4:0] port_id[0:7];//  8个 port_id的阵列;每一个 port_id 是 5 位元宽度 
integer matrix[4:0][4:0];// 多维阵列为非法宣告 

count[5]// count 变数的第五个元件 
chk_point[100]// 第100个时间核对点变数值 
port_id[3] //  port_id 阵列的第叁个元件. 是一 5 位元值

向量与阵列是不相同的,向量是一个多位元的元件(element),阵列是多个1bit或若干bits的元件。

 

3.2.7 记忆体(Memories)

在Verilog 中,记忆体像是一个暂存器的阵列,在阵列中的每一个物件,就像是个字元(word),每个字元可以是一个 bit或多个bits。
 

reg mem1bit[0:1023]; //记忆体 mem1bit 是 1k 个 一位元的字 
reg [7:0] membyte[0:1023]; //记忆体  membyte 是 1k 个 八位元的字 
membyte[511]// 提取位址为511的一位元组的字

 

3.2.8 参数(Parameters)

在模组中我们可以用关键字 parameter 定义一个固定常数(参数),这一个参数在每一次的编译时可以更改。
 

parameter port_id = 5; //宣告一常数 port_id 
parameter cache_line_width = 256; //定义一常数快取线的宽度(width of cache line)

 

3.2.9 字串(Strings)

字串可以指定给暂存器 (reg)。
 

reg [8*18:1] string_value; //宣告一变数18个位元组的宽度 
initial 
   string_value = "Hello Verilog World"; // 将字串存於变数中

Table 3-3 是一些为了显示用的特殊字元

Table3-3 特殊字元 

特殊字元  显示字元
\n 换行
\t 跳栏
%% %
\\ \
\" "
\ooo 1-3个八位元数

 

3.2.9 字串(Strings)

字串可以指定给暂存器 (reg)。
 

reg [8*18:1] string_value; //宣告一变数18个位元组的宽度 
initial 
   string_value = "Hello Verilog World"; // 将字串存於变数中

Table 3-3 是一些为了显示用的特殊字元

Table3-3 特殊字元 

特殊字元  显示字元
\n 换行
\t 跳栏
%% %
\\ \
\" "
\ooo 1-3个八位元数

3.3 系统任务(System Tasks) 和 组译指令(Compiler Directives)

3.3.1 系统任务

系统任务包含有显示、监视数值、暂停、完成..等,其皆以$<keyword>表示。

资讯显示(Displaying information)

Usage: $display(p1,p2,p3,....,pn);
p1,p2,p3,....,pn可以是字串、变数、或说明。每一个 $display 命令後会自动跳行。由格式定义表(format specifications listed) 表格 3-4,可以做字串的格式。

 表格 3-4  格式定义表

格式 显示
%d or %D 十进制变数
%b or %B 二进制变数
%s or %S 字串
%h or %H 十六进制变数
%c or %C  ASCII 字元 
%m or %M 阶层名(不需引数)
%v or %V 强度
%o or %O 八进制变数
%t or %T 目前时间
%e or %E 实数科学记号
%f or %F 十进制实数变数
%g or %G 选择实数科学记号和十进制实数变数较短者

范例 3-2 显示任务

//显示双引号中之字串 
%display("Hello Verilog World"); 
--Hello Verilog World 

//显示目前时间 
%display($time); 
--230 

//显示虚拟位址为1fe0000001c的值和目前时间 200 
reg [0:40] virtual; 
$display("At time %d virtual adderess is %h", $time, virtual_adder); 
--At time 200 virtual address is 1fe0000001c 

//使用二进制显示port_id其值为五 
reg [4:0] port_id; 
 $display("ID of the port is %b", port_id); 
-- ID of the port is 00101 

//显示 x 特性 
//使用二进制显示四位元汇流排其值为 10xx 
reg [3:0] bus; 
$display("Vus value is %b",bus); 
--Bus value is 10xx 

//显示较高层次模组top的别名p1的阶层名,不需任何引数 
$display("This string is displayed from %m level of hierarchy") 
--This string is displayed from top.p1 level of hierarchy

 
范例 3-3  特殊字元 

//跳行及显示特殊字元% 
$display("This is a \n multiline string with a %% sign") 
--This is a 
--multinline string with a % sign 

//显示其他特殊字元

资讯监视(Monitoring information)

Usage:$monitor(p1,p2,p3,....,pn);
p1,p2,....,pn 是与 $display 相同的,但是 $monitor 不仅仅是显示而已,其在每一次信号变化都能显示出来。

范例3-4  Monitor statement

// 监视信号 clock and reset的值和时间 
//Clock 每 5 时间单位触发一次 和 reset在 10时间单位转为低电位 
initial 
begin 
  $monitor($time, "Value of signals clock = %b reset = %b, click, reset); 
end 

Partial output of the monitor statement: 
-- 0 Value of signals clock = 0 reset = 1 
-- 5 Value of signals clock = 1 reset = 1 
-- 10 Value of signals clock = 0 reset = 0

中止(Stopping) 和 完成(finishing)

Usage: $stop;
可以暂时中止模拟来检验信号的值是否正确。

Usage: $finish;
完成并退出模拟。

范例3-5  中止 和 完成

// 中止模拟在100时间单位并检验结果 
// 在1000时间单位完成 
initial //  模拟时间为0 
begin 
clock = 0; 
reset = 1; 
#50 $stop; //  中止模拟在50时间单位 
#900 $finish; // 完成模拟在950时间单位 
end

 

3.3.2 编译命令(Compiler Directives)

编译命令皆以`<keyword>来表示。

`define
定义文字巨集(text macro)。

范例3-6  `define Directive

//用文字巨集定义字的宽度 
//在程式码中使用  `WORD_SIZE 
`difine WORD_SIZE 32 

//定义一个别名,当 `s 出现时用 $stop取代 
`define s $stop; 

//定义一个经常使用的文字字串 
`define WORD_REG reg [31:0] 
//然後可以用 `WORD_REG reg32; 定义一个 32-bit 暂存器变数

`include
可以包含令一个Verilog file 一起编译。

范例3-7  `include 指令

//包含 header.v档案, 其包含一些在主程式design.v档案中之宣告 
`include header.v 
... 
... 
<Verilog code in file design.v> 
... 
...

 

3.4 总结

* Verilog 语法极类似C语言。
* 说明空白注解,运算子,数字,字串,定义名称语法协定
* 在Verilog中有数种有用的资料型态可以使用。四种逻辑值,八种强度。可以使用资料型态,接线,暂存器,向量,时间,阵列,记忆体,参数,字串,资料型态。
* Verilog提供有用的系统任务 :资讯显示,资讯监视,中止和完成模拟。
* 编译指令 `define是用来定义一个文字巨集,`include 是用来包含其他的Verilog档案。
 

posted on 2012-03-05 21:58  mculove  阅读(680)  评论(0编辑  收藏  举报

导航