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

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}

Verilog逻辑移位运算符与数字移位运算符:

列举:
        << 逻辑左移运算符;<<< 数字左移运算符;
        >> 逻辑右移运算符;>>> 数字右移运算符;

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

如:

        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运算符(逻辑运算符、按位运算符、缩位运算符、迭代连接运算符、移位运算符)_第2张图片

可以验证与文中移位、迭代连接操作的描述统一;

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

出现了问题:

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

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

交流群里请教了大家后发现,原因在于interger默认为32位宽,拼接后被截取导致只有低位,因此不正确;(但是定义时我限定了位宽呀,为何还是32位??)参考博客后发现,integer好像就是位宽不能精确定义,这也是在位宽敏感时避免使用的原因;

仿真如下:

 

本文参考了:

逻辑左移、算术左移、逻辑右移、算术右移区别

Verilog编码规则:不使用integer类型,使用精确定义位宽的wire\reg类型

你可能感兴趣的:(FPGA/Verilog基础,fpga,verilog)