SystemVerilog(零):Verilog数据类型、语法、例程

声明:本篇文章部分参考

https://www.cnblogs.com/protogenoi/p/8926993.html  Verilog笔记.1.基本语法   作者:Protogenoi 

一、Verilog语言整体印象

1、模块是基本描述单位。端口默认是线网数据类型。端口长度声明,默认1位。output [0:3] Z;4位

实例化:指调用软件自带的模块(如内置门级元件)和自己编写的模块。

2、描述设计:有四种方式

1. 数据流描述方式:assign:连续赋值语句,语句并发。编译器指令:` timescale 1ns /100ps 时间单位、时间精度

2. 行为描述方式:过程语句initial、always。只有reg(寄存器)类型能在两种语句中赋值。顺序执行。

always=事 件控制(判断条件)+顺序过程。always语句块可以理解为while语句吗?

3. 结构化描述方式:原语,硬件级, xor、and和or的实例语句

4. 混合设计描述方式:门实例语句,模块实例语句、连续赋值语句,过程语句。

过程赋值vs连续赋值:

1.过程赋值改变寄存器的状态,是时序逻辑,用在initial和always里面;

2.连续赋值是组合逻辑,驱动线型变量(wire)

3、设计模拟:激励、控制、存储响应、设计验证

1. 激励和控制可以由初始化语句产生 

4、抽象模型分级

系统级:用高级语言结构实现设计模块的外部性能的模型。

算法级:用高级语言结构实现设计算法的模型。

RTL级:描述数据在存储器之间流动和如何处理这些数据的模型。

门级:描述逻辑门与逻辑门之间的连接的模型。

开关级:描述器件中三极管和存储节点以及它们连接的模型。

二、Verilog语言要素

1、Verilog内置的12个门级元件,模块可以实例引用门级模型, 对结构进行实例化描述。

                                                        

2、运算符 

(1) 算术运算符 +,-,*,/,%  

(2) 赋值运算符 =,<=

赋值语句:组合逻辑,顺序执行,阻塞赋值,使用=赋值。时序逻辑,并行执行,非阻塞赋值,使用<=赋值。                      

(3) 关系运算符> ,<,>=,<=

(4) 逻辑运算符 &&, ||, ! (与或非)

(5) 条件运算符 ?:

(6) 位运算符 ~, | , ^ ,& ,^~ (取反、或、异或、与、同或)

(7) 移位运算符 << ,>>

(8) 拼接运算符 {}

3、特殊标识符

$开始的标识符表示系统任务/函数 。

ps: 函数vs任务。任务可以返回0或多个值,函数返回一个值。函数在0时刻执行,不允许延迟,任务可以带有延迟。

'开始的标识符是编译器指令。编译器指令在整个编译过程中有效(类似于宏定义) 

4、操作数

四种基本值:0,1,x,z:假,真,未知,高阻态。

三类常量:整形、实数型、字符串型。

整形表示法:

(1)十进制表示:<数字>   默认采用十进制

(2)基数表示法:<位宽>'<进制><数字>    位宽表示占用二进制位数 (bodh:二八十十六)

5、数据类型

(1)线网和寄存器

Verilog两大类数据类型:线网和寄存器,线网有11钟类型,寄存器有5钟类型。

线网类型:表示结构化元件间的物理连线,值由驱动元件决定。

寄存器类型:在always和initial语句赋值过程中的存储单元。五种寄存器类型:reg,integer,time,real,realtime。

区别:wire只能由assign连续赋值语句中赋值,reg只能在initial/always过程赋值语句中赋值。

更多参考:https://www.cnblogs.com/wzd5230/p/3847481.html  verilog中wire与reg类型的区别

reg [msb:lsb] reg1   msb:lsb表示位数范围,大小方向都可以。

reg [0:3] MyMem [0:64]   存储器(寄存器数组)MyMem为64个4位寄存器的数组。线网类型没有对应点的存储器类型。

(2)参数

定义一个标志符代表一个常量(三种类型,如上),常用于定义延迟时间和变量宽度。

parameter <标志符> =  <常量>

三、语句、子程序

1、赋值语句:Verilog中信号有两种赋值方式

(1)连续赋值语句:assign  用于对线网进行赋值,等价于门级描述。

  1. 左值必须为一个线网类型的变量或向量,不能是寄存器类型。
  2. 输出值随输入值变化而随时变化。
  3. 操作数可以是线网或寄存器或函数调用。
  4. 必须用“=”阻塞赋值进行赋值。

(2)过程赋值语句:=,<=

  •  非阻塞赋值方式( 如 b <= a; )
  1. 块结束后才完成赋值操作。
  2. b的值并不是立刻就改变的。
  3. 这是一种比较常用的赋值方法。(特别在编写可综合模块时)
  • 阻塞赋值方式( 如 b = a; )
  1. 赋值语句执行完后,块才结束。
  2. b的值在赋值语句执行完后立刻就改变的。
  3. 可能会产生意想不到的结果。

2、块语句:将多条语句结合在一起。块语句有两种,一种是begin_end语句,通常用来标识顺序执行的语句,用它来标识的块称为顺序块。一种是fork_join语句,通常用来标识并行执行的语句,用它来标识的块称为并行块

3、条件语句:if_else语句、case语句。略。

4、过程语句:initial、always。

        initial语句常用于仿真中的初始化,initial过程块中的语句仅执行一次;always语句则是不断重复执行的。

  每一条initial语句和always语句都是独立的执行过程,彼此并行执行,执行顺序于在模块内的书写顺序无关,并且,每条initial和always语句过程语句都是在仿真时间0时刻同时开始的。

5、编译预处理 `与系统指令#

1)宏定义 `define

2)“文件包含”处理`include

3)时间尺度 `timescale

4)条件编译命令`ifdef、`else、`endif

6、循环语句:forever,repeat,while,for

参考文献:https://www.cnblogs.com/SYoong/p/5857367.html  Verilog学习笔记基本语法篇(六)········ 循环语句

7、子程序:task、function

参考文献:https://blog.csdn.net/HengZo/article/details/49688677  Verilog之function使用说明

参考文献:https://www.cnblogs.com/SYoong/p/5865546.html  Verilog学习笔记基本语法篇(九)任务和函数

8、实例语句

模块实例语句:<模块名> <标志符>(<对应端口1>,<对应端口2>...)

内置门实例语句:<关键字> <标志符>(<输出端口>,<输入端口1>...) 这里的关键字也叫内置门原语xor等,标志符也叫实例名称,括号里是信号列表。信号列表有位置管理和名称关联两种。

四、demo

1、全加器:逻辑:A加数 B被加数 Cin低位进位 S和 Cout高位进位

2、行为描述方式:

// 行为描述,全加器
module FA(a,b,ci,s,co);
input a,b,ci;
output s,co;
reg s,co,t1,t2,t3;

always @(a or b or ci) begin
	s=(a ^ b)^ci;
	t1=a & b;
	t2=a & ci;
	t3=b & ci;
	co=(t1|t2)|t3;
end
endmodule
`timescale 1 ns/ 1 ns
module FA_test();
reg Pa,Pb,Pci;
wire Ps,Pco;
FA F1(Pa,Pb,Pci,Ps,Pco); //模块实例语句:待测模块名 引用名(信号端口一一对应,位置关联)

initial begin: ONLY_ONCE
reg [3:0] i;
	for (i=0;i<8;i=i+1)
	begin
		#20 {Pa,Pb,Pci}=i;
	end
end
endmodule

3、流水灯

module waterled(
	input	clk,
	input	rst,
	output reg [3:0] led
	);
 
reg [7:0] times;	
 
always @ (posedge clk or negedge rst) // 时钟信号计数
begin
	if(!rst)       
		times<=1'b0; // 电路未复位,计数器锁定为0
	else
		if(times<8'd10) // 电路复位开始计数,计数到10重置
			times<=times+1'b1;
		else
			times<=8'd0;
end
 
always @ (posedge clk or negedge rst) // 计数满10,四位数组中的1进位一次
begin
	if(!rst)
		led<=4'b0001; // 电路未复位 led[0]=1
	else
		if(times==8'd10) // 计数满10,led高位到低位,1向前进位
			led<={led[2:0],led[3]};
		else
			led<=led;
end
endmodule
`timescale 1 ns/ 1 ns
module waterled_test;

wire [3:0] led;
reg rst,clk10;
                         
waterled i1 (clk10,rst,led);  //例化语句

always #10 clk10=~clk10;  // 产生时钟信号                                          

initial begin                                                                         
	clk10=1'b0;
	rst=1'b0;
	#100 rst=1'b1; // 100ns时,电路复位 
	#1000 $stop; // 1000ns时,仿真暂停                      
end                                                    

endmodule

4、function demo

module comb15; 

function ADD; 
	input A, B;
	ADD = A ^ B;
endfunction 


initial begin
$display("Hello  %b",ADD(1'b1,1'b0));
end

endmodule

输出1

module comb15; 

function signed [1:0] ADD; 
	input A, B;
	reg S;  
	S = A ^ B;
endfunction 

reg [31:0] N,M;
reg H;
initial begin
N = 100;
M = 100;
H = 32'd100;
$display("Hello",100);
$display("Hello",32'd100);
$display("Hello%b",32'd100);
$display("Hello%b",8'd100);
$display("Hello\n",100);
$display("Hello",N);
$display("Hello",M);
$display("Hello",H);
end

endmodule

display需要begin..and, 超过1句也需要begin..and。

其他参考资料:

https://wenku.baidu.com/view/0d8a1bd4195f312b3169a59c.html  verilog中reg和wire类型的区别

https://zhidao.baidu.com/question/135703718.html  请Verilog高手帮助!wire赋值问题

http://bbs.eetop.cn/thread-313513-1-1.html signed的用法

https://vlab.ustc.edu.cn/guide/doc_verilog.html  Verilog语法

https://zhidao.baidu.com/question/437300882386090484.html  综合和仿真

Verilog这门语言真的是。。。语法臃肿代码效率低。。。这把设计和验证分开是为啥子。。。不能断点调试看变量的值。。。没有ide。。。 不重视缩进。。。函数名与返回值是一个。。。线网和寄存器类型奇奇怪怪。。。魔!鬼!啊!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章