verilog常用运算符(逻辑运算符、按位运算符、缩位运算符、迭代连接运算符、移位运算符)

一、逻辑运算符与按位运算符

区别:按位运算符进行逐位的逻辑运算(如:与或非),输出与输入位数一致;逻辑运算符进行逻辑运算,不关注输入的某一位而是将输入作为整体进行逻辑操作,输出位数为 1;

列举:

  • 与:& 按位与;&& 逻辑与;
  • 或:| 按位或;|| 逻辑或;
  • 非:~ 按位非;! 逻辑非;

二、缩位运算符

灵活使用缩位运算符,可以简化代码,避免重复工作;

如:

&a 可实现 a 各位间的与运算,即:&a 等价于 a(0)&a(1)&…&a(n)

| a 可实现 a 各位间的或运算,即:| a 等价于 a(0)|a(1)|…|a(n)

三、迭代连接运算符

连接功能:将若干个寄存器类型/线网类型的变量首尾连接,形成一个更大位宽的变量;

如:

a = 2’b10;

b = 3’b010;

有{a,b} = 5’b10010;

迭代功能:把一个变量复制多次,首尾连接组成一个更大位宽的变量;(实际仍为连接功能的一个特例:连接元素相同)

如:

a = 2’b10;

有{4{a}},即{a,a,a,a}

注意:要保证迭代的完整性:例如 { {4{a}},b},其中 {4{a}} 为迭代功能,括号不能少;即不能写为{ 4{a},b}。

另外,迭代连接运算符还可用于常量操作:{ {4{1’b1}},2’b10}

四、逻辑移位运算符与数字移位运算符

列举:

<< 逻辑左移运算符;<<< 数字左移运算符;

>> 逻辑右移运算符;>>> 数字右移运算符;

区别:逻辑移位运算符不关心符号位;逻辑左移右端补零,逻辑右移左端补零;数字左移位运算符不关心符号位,与逻辑左移一样;数字右移运算符关心符号位,左端补符号位;

如:

1010101010,其中[]是添加的位

逻辑左移一位:010101010[0]

算数左移一位:010101010[0]

逻辑右移一位:[0]101010101

算数右移一位:[1]101010101

五、仿真验证

进行部分仿真(感觉很简单,着手去编写的时候却碰见了不少问题,万不可眼高手低!!!),代码如下:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: guoliang CLL
// 
// Create Date: 2020/02/19 10:15:53
// Design Name: 
// Module Name: operation
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 常见操作符测试
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//
 
 
module operation(
input [1:0]a,
input [2:0]b,
input signed[5:0]c, 
//input signed[5:0]d, 
output [5:0]e,// {3{a}}
output [4:0]f, // {a,b}
output [5:0]g,// {{2{2'b10}},b}
output [5:0]sl, // 逻辑左移
output [5:0]sr,// 逻辑右移
output [5:0]sl1, // 数字左移
output [5:0]sr1 // 数字右移
    );
 
integer N = 2'b11;
assign e = {3{a}};
assign f = {a,b};
assign g = { {2{2'b11}} ,a};
assign sl = c << 1;
assign sr = c >> 1;
assign sl1 = c <<< 1;
assign sr1 = c >>> 1;
endmodule

添加测试文件:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2020/02/19 10:59:51
// Design Name: 
// Module Name: operation_tsb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//
 
 
module operation_tsb(
 
    );
reg  [1:0]a;
reg  [2:0]b;
reg signed[5:0]c;
//input signed[5:0]d, 
wire [5:0]e;// {3{a}}
wire [4:0]f; // {a,b}
wire [5:0]g;// {{2{2'b11}},b}
wire [5:0]sl; // 逻辑左移
wire [5:0]sr;// 逻辑右移
wire [5:0]sl1; // 数字左移
wire [5:0]sr1; // 数字右移
 
initial
begin
    a = 2'b10;
    b = 3'b101;
    c = 6'b110010;
    # 20
    c = 6'b010011;
end
 operation ins(
   .a(a),
   .b(b),
   .c(c),
   .e(e),
   .f(f),
   .g(g),
   .sl(sl),
   .sr(sr),
   .sl1(sl1),
   .sr1(sr1)
       );
endmodule

RTL 电路以及仿真结果:

verilog常用运算符(逻辑运算符、按位运算符、缩位运算符、迭代连接运算符、移位运算符)
图 1 verilog 运算符的 RTL 电路
verilog常用运算符(逻辑运算符、按位运算符、缩位运算符、迭代连接运算符、移位运算符)
图 2 verilog 运算符的仿真结果

从上述仿真结果,可以看出移位、迭代连接操作与上文描述一致;

g 的输出,证明迭代连接运算符确实可以用于常量操作,并且可以常量与变量混用,即仿真中的{ 2{2‘b11},a}

需要注意的地方:

验证迭代连接运算符确实可以用于常量操作时,如果将常量声明为 integer 类型,g 的输出就不正确,即仿真中的 integer N=2‘b11;

g = { {2{N}},a}时输出不对;改为 parameter 类型时,输出正确;

原因在于 interger 默认为 32 位宽,拼接后被截取导致只有低位,因此不正确;即使定义时限定了 interger 的位宽,还是会按照默认 32 位宽;integer 好像就是位宽不能精确定义,这也是在位宽敏感时避免使用的原因。

扫码关注尚为网微信公众号

尚为网微信公众号
每天学习电路设计嵌入式系统的专业知识,关注一波,没准就用上了。

原创文章,作者:sunev,如若转载,请注明出处:https://www.sunev.cn/embedded/1236.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022年6月22日 21:16
下一篇 2022年6月30日 20:37

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注