Verilog语法误区总结

组合逻辑锁存器的生成

在Verilog语言组合逻辑的书写中,我们经常会写下面语句:

assign      din_x       =       rvalid == 1'b1 ? {{24{din[9]}},din}: din_x;

或者,

always @(*)
    if(ext_valid == 1'b1)
        dout            <=      comb_in3;
    else
        dout            <=      dout;

直接读写的语法,我们以为编译器会生成锁存器,但是上面的语法分别核下面的等效,

assign      din_x       =       {{24{din[9]}},din};
always @(*)
    dout             =      comb_in3;

是不是很神奇,上面的两条语句就相当于两个信号直接相连。因为编译器自动给你避免了锁存器的生成,但是这样一来,我们的实验结果或许就出现了错误,所以这里需要大家重点关注。

Verilog语句中signed的作用

这里关键字signed的作用不体现在数字的加减上,因为我们不管声不声明这个变量是有符号数,FPGA内部都是按照二进制数的加法来计算的,减法将减数转换成补码进行运算。
test模块:

`timescale 1ns / 1ps
module test(
    //System Interfaces
    input                   sclk            ,
    input                   rst_n           ,
    //Communication Interfaces
    input           [ 7:0]  a               ,
    input           [ 7:0]  b               ,
    output  reg     [ 7:0]  add             ,
    output  reg     [ 7:0]  subtract        
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/


//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        add             <=          8'd0;  
    else 
        add             <=          a + b;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        subtract        <=          8'd0;
    else
        subtract        <=          a - b;

endmodule

tb模块:

`timescale 1ns / 1ps
module tb();
//System Interfaces
reg                         sclk            ;
reg                         rst_n           ;
reg                 [ 7:0]  a               ;
reg                 [ 7:0]  b               ;
wire                [ 7:0]  add             ;
wire                [ 7:0]  subtract        ;

initial begin
    sclk            =           1'b0;
    rst_n           <=          1'b0;
    a               <=          0;
    b               <=          0;
    #(1000)
    rst_n           <=          1'b1;
    #(1000)
    a               <=          5;
    b               <=          7;
    #(1000)
    a               <=          5;
    b               <=          -7;
    #(1000)
    a               <=          -5;
    b               <=          7;
    #(1000)
    a               <=          -5;
    b               <=          -7;
    #(1000);
    $stop;
end

always  #(10)       sclk        =           ~sclk;

test test_inst(
    //System Interfaces
    .sclk                   (sclk                   ),
    .rst_n                  (rst_n                  ),
    //Communication Interfaces
    .a                      (a                      ),
    .b                      (b                      ),
    .add                    (add                    ),
    .subtract               (subtract               )
);

endmodule

运行的结果如下:
在这里插入图片描述
我们将使用关键字signed进行如下实验:
test模块:

`timescale 1ns / 1ps
module test(
    //System Interfaces
    input                       sclk            ,
    input                       rst_n           ,
    //Communication Interfaces
    input       signed  [ 7:0]  a               ,
    input       signed  [ 7:0]  b               ,
    output  reg signed  [ 7:0]  add             ,
    output  reg signed  [ 7:0]  subtract        
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/


//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        add             <=          8'd0;  
    else 
        add             <=          a + b;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        subtract        <=          8'd0;
    else
        subtract        <=          a - b;

endmodule

tb模块:

`timescale 1ns / 1ps
module tb();
//System Interfaces
reg                         sclk            ;
reg                         rst_n           ;
reg     signed      [ 7:0]  a               ;
reg     signed      [ 7:0]  b               ;
wire    signed      [ 7:0]  add             ;
wire    signed      [ 7:0]  subtract        ;

initial begin
    sclk            =           1'b0;
    rst_n           <=          1'b0;
    a               <=          0;
    b               <=          0;
    #(1000)
    rst_n           <=          1'b1;
    #(1000)
    a               <=          5;
    b               <=          7;
    #(1000)
    a               <=          5;
    b               <=          -7;
    #(1000)
    a               <=          -5;
    b               <=          7;
    #(1000)
    a               <=          -5;
    b               <=          -7;
    #(1000);
    $stop;
end

always  #(10)       sclk        =           ~sclk;

test test_inst(
    //System Interfaces
    .sclk                   (sclk                   ),
    .rst_n                  (rst_n                  ),
    //Communication Interfaces
    .a                      (a                      ),
    .b                      (b                      ),
    .add                    (add                    ),
    .subtract               (subtract               )
);

endmodule

运行结果如下:
在这里插入图片描述
对比以上两组实验,我们可以发现定义signed关键字在加减实验中没有体现应有的作用。

但是关键字在移位操作的时候就得到了体现
test模块:

`timescale 1ns / 1ps
module test(
    //System Interfaces
    input                       sclk            ,
    input                       rst_n           ,
    //Communication Interfaces
    input               [ 7:0]  a               ,
    input               [ 7:0]  b               ,
    output  reg         [ 7:0]  add             ,
    output  reg         [ 7:0]  subtract        
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/


//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        add             <=          8'd0;  
    else 
        add             <=          a <<< 1;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        subtract        <=          8'd0;
    else
        subtract        <=          b >>> 1;

endmodule

tb模块:

`timescale 1ns / 1ps
module tb();
//System Interfaces
reg                         sclk            ;
reg                         rst_n           ;
reg                 [ 7:0]  a               ;
reg                 [ 7:0]  b               ;
wire                [ 7:0]  add             ;
wire                [ 7:0]  subtract        ;

initial begin
    sclk            =           1'b0;
    rst_n           <=          1'b0;
    a               <=          0;
    b               <=          0;
    #(1000)
    rst_n           <=          1'b1;
    #(1000)
    a               <=          8;
    b               <=          10;
    #(1000)
    a               <=          8;
    b               <=          -10;
    #(1000)
    a               <=          -8;
    b               <=          10;
    #(1000)
    a               <=          -8;
    b               <=          -10;
    #(1000);
    $stop;
end

always  #(10)       sclk        =           ~sclk;

test test_inst(
    //System Interfaces
    .sclk                   (sclk                   ),
    .rst_n                  (rst_n                  ),
    //Communication Interfaces
    .a                      (a                      ),
    .b                      (b                      ),
    .add                    (add                    ),
    .subtract               (subtract               )
);

endmodule

运行结果:
在这里插入图片描述

下面是加了signed操作的移位,我们可以看出来结果的不一样。
test模块:

`timescale 1ns / 1ps
module test(
    //System Interfaces
    input                       sclk            ,
    input                       rst_n           ,
    //Communication Interfaces
    input       signed  [ 7:0]  a               ,
    input       signed  [ 7:0]  b               ,
    output  reg signed  [ 7:0]  add             ,
    output  reg signed  [ 7:0]  subtract        
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/


//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        add             <=          8'd0;  
    else 
        add             <=          a <<< 1;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        subtract        <=          8'd0;
    else
        subtract        <=          b >>> 1;

endmodule

tb模块:

`timescale 1ns / 1ps
module tb();
//System Interfaces
reg                         sclk            ;
reg                         rst_n           ;
reg     signed      [ 7:0]  a               ;
reg     signed      [ 7:0]  b               ;
wire    signed      [ 7:0]  add             ;
wire    signed      [ 7:0]  subtract        ;

initial begin
    sclk            =           1'b0;
    rst_n           <=          1'b0;
    a               <=          0;
    b               <=          0;
    #(1000)
    rst_n           <=          1'b1;
    #(1000)
    a               <=          8;
    b               <=          10;
    #(1000)
    a               <=          8;
    b               <=          -10;
    #(1000)
    a               <=          -8;
    b               <=          10;
    #(1000)
    a               <=          -8;
    b               <=          -10;
    #(1000);
    $stop;
end

always  #(10)       sclk        =           ~sclk;

test test_inst(
    //System Interfaces
    .sclk                   (sclk                   ),
    .rst_n                  (rst_n                  ),
    //Communication Interfaces
    .a                      (a                      ),
    .b                      (b                      ),
    .add                    (add                    ),
    .subtract               (subtract               )
);

endmodule

运行结果:
在这里插入图片描述
所以,在写程序的时候对有符号数操作,关键走signed还是应该添加。

总结

该篇文章我们会一直补充完善,共同发掘一些语法中的大坑。

在查找一些资料的时候,发现一些博主只给出部分代码,其实这样别人根本看不懂,只有给出整个工程代码才易于知识的传播。创作不易,认为文章有帮助的同学们可以关注、点赞、转发支持。为行业贡献及其微小的一部分。或者对文章有什么看法或者需要更近一步交流的同学,可以加入下面的群:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/zhangningning1996/article/details/105785443