verilog基础语法及规范

一、Verilog 语法—设计使用

a) reg:寄存器型信号;//在always语句中变量必须定义为reg,在initial语句中用reg。

b) wire: 线网型信号;//信号若无声明,默认为wire型,assign语句中,例化的输出信号。

c) parameter:参数声明;
d) assign:连续赋值;

e) {}:拼接/复制运算符;//led = 0001 {led[0],led[3:1]} led = 1000;

f) if - else、if - else if – else、case :条件选择;

a) 赋值运算符:非阻塞赋值(<=)、阻塞赋值(=);

阻塞赋值“=”(组合逻辑电路),非阻塞赋值“<=”(时序逻辑电路);
阻塞赋值具有先后顺序
非阻塞不具有先后顺序
如:a = 1; b = 2; c = 3;

	a =  b + c;		
	c =  a;

结果是a = 5 , c = 5

	a <=  b + c;		
	c <=  a;	

结果是a = 5 , c = 1

b) 算术运算符:+,-,*,/;
c) 关系运算符:<、<=、>、>=、 ==、 !=;
d) 逻辑运算符:&&、||、!;
e) 位运算符: ~、|、^、&;
f) 逻辑移位运算符:<<、>>;

g) 算术移位运算符:<<<、>>>;//有符号数的移位操作,只能使用算数移位。逻辑右移要补符号位

Verilog 语法—仿真使用
a) initial:激励信号初始化;
b) for/while/repeat/forever:循环;//forever只能在initial中用
c) integer:整型变量声明;
d) #:延时;
e) $random:产生随机数;// 加上{}后表示在正数范围随机

{$random}%10000//表示10000内的正数随机数

f) task/founction:任务、函数;

module task_function(
           in1,
           in2,
           in3,
           in4,
           out1,
           out2
       );
 
input [7:0] in1,in2,in3,in4;
output reg [8:0] out1,out2;
 
//任务
task add1;										//注意无端口列表
    input [7:0] a,b;							//输入端口和数据类型声明
    output reg [8:0] out1;					//输出端口和数据类型声明
    out1 = a + b;								//a,b,out1名称的作用范围仅为task任务内部
endtask
 
//调用任务
always@(in1 or in2) begin
    add1(in1,in2,out1);						//调用任务,注意端口列表的顺序要和任务中定义的一致
end
 
//函数
function [8:0] add2;							//函数定义  函数会自动生成一个和函数名同名的内部变量,作为函数返回值所用的寄存器。
    input [7:0] c,d;							//输入端口声明  函数只有输入端口,输出端口为函数名本身。
    add2 = c + d;								//返回输出值  输出寄存器为和函数同名的内部寄存器
endfunction
//调用函数
always @(in3 or in4) begin
    out2 = add2(in3,in4);					//调用函数,注意端口列表的顺序要和函数中定义的一致
end
 
endmodule

分别在任务和函数中实现两个数相加的操作,在调用任务时,需要向任务中传递输入输出端口。在调用函数的时候,只需要传递输入信号,函数的返回值作为输出信号。

g) force/wait/fork:仿真很少用;
Verilog 代码设计—时序逻辑、组合逻辑

二、Verilog 代码设计规范

  1. 一个 always 只产生一个信号,一个信号只能在一个 always 赋值;
  2. always 是描述一个信号的方法,在某种情况下,这个信号的值为多少;在其他情况下,值又为多少,要全部考虑清楚;
  3. 条件判断只使用 if-else / if-else if – else 和 case;
  4. 敏感列表含有 posedge 或 negedge 的一定是时序逻辑;
  5. 设计时,如果想立即有结果,就用组合逻辑;如果想要延时一拍再输出,就用时序
    逻辑;
  6. always 中的信号一定用 reg 定义,非 always 中的信号一定用 wire 定义;
  7. 时序逻辑使用非阻塞(<=)赋值,组合逻辑使用阻塞(=)赋值。

补充:
1、算术左移-逻辑左移
算术左移和逻辑左移一样都是右边补 0: 比如 00101011
算术左移一位:01010110
逻辑左移一位:01010110
对于二进制的数值来说左移 n 位等于原来的数值乘以 2 的 n 次方
比如 00011010 十进制是 26,左移两位后是 01101000 转成十进制是 104 恰好是 26 的 4
倍。
ps:这种倍数关系只适用于左移后被舍弃的高位不含 1 的情况,否则会溢出。
2、算术右移,逻辑右移
逻辑右移很简单,只要将二进制数整体右移,左边补 0 即可
如 10101101 逻辑右移一位为 01010110
算术右移符号位要一起移动,并且在左边补上符号位,也就是如果符号位是 1 就补 1 符号
位是 0 就补 0
比如:11100 算术右移一位为 11110(符号位 1 跟着一起移动并且左边补了 1)
对于二进制的数值来说右移 n 位等于原来的数值除以 2 的 n 次方
比如 10110100 十进制是 76(需要先将这个补码转换成原码之后再转换成十进制),右移两
位后是 11101101 转成十进制是 19 恰好是 76 的 4 倍。
算术左移和算术右移主要用来进行有符号数的倍增、减半;
逻辑左移和逻辑右移主要用来进行无符号数的倍增、减半。

**原码:**原码的表示与机器数真值表示的一样,即用第一位表示符号,其余位表示数值,例如的十进制的的正负1,用8位二进 制的原码表示如下: 【+1】= 原:[ 0000 0001 ]
【-1】= 原:[ 1000 0001 ]
**反码:**反码的表示方法为:
正数的反码是其原码本身。
负数的反码是在其原码的基础上,符号位不变,其余各位取反。
【+1】= 原: [ 0000 0001 ] = 反:[ 0000 0001 ]
【-1】 = 原:[ 1000 0001 ] = 反:[ 1111 1110 ]
**补码:**补码的表示方法为: 正数的补码是其原码本身。 负数的补码是在其原码的基础上,符号位不变,其余各位取反后加1(即在反码的基础上加1)。
【+1】= 原: [ 0000 0001 ] = 反:[ 0000 0001 ] = 补:[ 0000 0001 ]
【-1】 = 原:[ 1000 0001 ] = 反:[ 1111 1110 ] = 补:[ 1111 1111 ]

参考

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值