zoukankan      html  css  js  c++  java
  • 【FPGA篇章三】FPGA常用语句:Verilog基本语法要素

    欢迎大家关注我的微信公众账号,支持程序媛写出更多优秀的文章

     

    Verilog中总共有十九种数据类型,我们先介绍四个最基本的数据类型,他们是:

    reg型、wire型、integer型、parameter型

    1 常量

      1.1 数字integer

        整数:b二进制   d十进制   h十六进制   o八进制

          表达方式:<位宽=default><进制=d><数字>

          Eg. 8‘b10100100,2'h0a3,3'o455,4’d2435

          注意,当仅有位宽被忽略时,即'b, 'd, 'o'等形式,数据默认位宽为当前机器的字节宽度,常为32位

        X与Z值:x代表不定值,z代表高阻值

          可以用于定义当前进制数的1位(如h下可表达1位十六进制数)。

        负数:位宽前加减号

        下划线:分割数的表达,提高可读性,无意义

      1.2 参数parameter

        定义一个标识符代表一个常量,即标识符形式的常量。提高可读性。格式如下:

        parameter para1=3'b010, para2=4'd1432,...,paran=2'h6a;
        parameter ave_delay = (r+f)/2;

        常用于定义延迟时间和变量宽度,以及改变在被引用模块或实例中已定义的参数。如:

     1       module Decode(A,F);
     2            parameter Width=1, Polarity=1;
     3            ...
     4       endmodule
     5  6       module Top;
     7            wire[3:0] A4;
     8            wire[4:0] A5;
     9            wire[15:0] F16;
    10            wire[31:0] F32;
    11            Decode #(4,0) D1(A4,F16);//w=4,p=0
    12            Decode #(5) D2(A5,F32);//w=5
    13       endmodule

        在实例时使用 #() 的方式来更改引用模块参数

    2 变量

      2.1 net(default)

      网络数据类型net表示结构实体(如门)之间的物理连接,它不能储存值,而且必须受到驱动器的驱动。如无驱动器连接,则呈现高阻Z态。

        wire(default)

        单门驱动或连续赋值语句驱动的网络型数据。

        常用来表示以assign关键字指定的组合逻辑信号。

        tri

        多驱动器驱动的网络型数据。

        (多驱动源下,若无定义逻辑强度,逻辑值会发生冲突产生不确定值X)

    1     wire [n-1:0] name1, name2, ... , namei;
    2     wire [n:1] name1, name2, ... , namei;
    3     wire name;

      2.2 register

      寄存器是数据储存单元的抽象,通过赋值语句可以改变寄存器储存的值,作用与改变触发器储存的值相当。

      常用来表示always块内的指定信号,代表触发器。

      always块中被赋值的每一个信号都必须定义成reg型

      reg被赋值如同一组触发器存储单元的值被改变。

    1     reg [n-1:0] name1, name2, ... , namei;
    2     reg [n:1] name1, name2, ... , namei;
    3     reg rega;

      默认初始值为x。可以赋正负值,但当该reg是一个表达式中的操作数时,被作为无符号数处理。

      reg型只表示被定义的信号将用在always块内,虽常为寄存器、触发器的输出,但并非总是如此。

      2.3 memory

      Verilog通过建立reg型变量的数组来对存储器进行建模,描述RAM/ROM型存储器和reg文件。

      Verilog中不存在多维数组,memory型数据通过扩展reg型数据的地址范围来生成

     1     reg [n-1:0] mem1[m-1:0];
     2 
     3     reg [n-1:0] mem2[m:1];
     4 
     5     reg [7:0] mem[255:0];   //定义了一个名为mem 的存储器,该存储器拥有 256个 数据位宽为8 存储器,地址范围是从0到255​
     6 
     7     reg [n-1:0] rega;      // rega 是一个n位的寄存器
     8     rega = 0;          // rega 可以由一个赋值语句赋值
     9     reg mema[n-1:0];            // mema 是一个由n个1位寄存器单元构成的存储器
    10     mema[0] = 0;
    11     mema[1] = 0;
    12     ...
    13     mema[n-1] = 0;               // mema 必须一个一个单元地赋值

      如果想对memory中的存储单元进行读写操作,必须指定该单元在存储器中的地址。

    3 基本运算符号
      按操作数个数: 有单目、双目、三目运算符,分别可带一个、两个、三个操作数。

      按功能:

        1) 算术运算符+、-、×、/、%

           加、减、乘、除、求余

           整数除法结果值略去小数部分,取模运算符号位采用模运算式中第一个操作数的符号位。

        2) 赋值运算符=、<=

           同一个always块中,只能全使用阻塞赋值或全使用非阻塞赋值。

          * 非阻塞赋值<=:当前语句的执行不会阻塞下一语句的执行。

          在块语句结束时才完成赋值操作,块内的赋值语句同时赋值

          可以看作两个步骤的过程:

            赋值时刻开始时,计算非阻塞赋值右操作数表达式。

            赋值时刻结束时,更新非阻塞赋值左操作数。

    1     reg a=1, b=2, c=3, d=4;
    2     always @(posedge clk)
    3     {
    4        a <= b;
    5        b <= c;
    6        c <= d;
    7     }

          并行,电路实现往往与触发沿有关,常被综合成时序逻辑电路。

          * 阻塞赋值=:完成当前语句后才能做下一句的操作

          在该语句结束时就完成赋值操作,块内的阻塞赋值语句顺序执行

          顺序执行,一般不能设定有延迟,常被综合成组合逻辑电路。

        3)关系运算符>、<、>=、<=

        4)逻辑运算符&&、||、!

          &&和 || 是双目运算符,优先级低于算术运算符

          ! 是单目运算符,优先级高于算术运算符

    1     (a>b) && (x>y) 相当于 a>b && x>y
    2     (a==b) || (x==y) 相当于 a==b || x==y
    3     (!a) || (a>b) 相当于 !a || a>b

        5)条件运算符 ? :

        6)位运算符~、|、^、&、^~

          取反、或、异或、与、同或

    1       // 除相应双目位运算外还可用作单目运算符缩减运算
    2 
    3     reg [3:0] A = 0101;
    4        reg B;
    5     B = &A;
    6     // 相当于B = 0 & 1 & 0 & 1
    7     // 即将A的所有位进行位运算

         7)移位运算符<<、>>

          a>>n;   // 将操作数a右移n位,去尾,缩小
          a<<n;   // 将操作数a左移n位,补0  ,放大
     

        8)拼接运算符{ }

          把两个/多个信号的某些位拼接起来运算。

     1      a = 1'b0;
     2      b = 8'b11101100;
     3      c = 1'b1;
     4 
     5      //用法1
     6      r = {a, b[3:0], c, 3'b101};
     7      //此时r = 0 1100 1 101
     8 
     9      //用法2
    10      r = {4{a}};
    11      //此时r = 0000
    12      //嵌套用法
    13      r = {b[7:5], {3{c,a}}};
    14      //此时r = 111 101010

    易混知识点:

    位运算符:按位进行运算,原来的操作数有几位,结果就有几位,若2个操作数位数不同,则位短的数据左端会自动补0

    逻辑运算符:如果操作数是多位的,则将操作数看作整体,若操作数中每一位都是0值,则为逻辑0值,若操作数中有1,则为逻辑1值

    4 块语句

      4.1 顺序块

        块内语句顺序执行,上一条语句行完毕后,下一条语句才能执行

        每条语句的延迟时间是相对于前一条语句的仿真时间而言的(也就是说,顺序块内一条语句的延迟时间是指从前一条语句仿真完毕到当前语句仿真完毕的间隔)

        直到最后一条语句执行完,程序流程控制才跳出该语句块。

     1     begin
     2        语句1;
     3        语句2;
     4     end
     5 
     6 ​    begin:block_name
     7        assignments;
     8        语句1;
     9        语句2;
    10     end

      4.2 并行块

        1)块内语句同时执行,程序流程控制一进入到该并行块,块内语句则开始同时并行地执行,

        2)块内每条语句的延迟时间是相对于程序流程控制进入到块内的仿真时间的(也就是说,并行块内一条语句的延迟时间是指从程序流程控制进入到块内到该条语句执行完毕的间隔;这个延迟时间是用来给赋值语句提供执行时序的),

        3)当按延迟时间的时序中排在最后的语句执行完毕或一个disable语句执行时,程序流程控制跳出该程序块。

     1       fork
     2          语句1;
     3          语句2;
     4       join
     5 
     6 ​      fork:块名
     7        assignments;
     8          语句1;
     9          语句2;
    10       end

      4.3 生成块

      generate生成块的本质是使用循环内的一条语句来代替多条重复的Verilog语句,简化用户的编程
        用法:
        1. generate 语法有 generate for 、genreate if 和 generate case 三种
        2. generate for 语句必须有 genvar 关键字定义 for 的变量
        3. for 的内容必须加 begin 和 end
        4. 必须给 for 语段起个名字

     1 1. generate for例子:
     2 generate
     3 genvar i; //generate 8 samll fifo for in_data[i] 8X72
     4     for(i=0; i<NUM_QUEUES; i=i+1) 
     5         begin: in_arb_queues //NUM_QUEUES = 8
     6             small_fifo
     7             #( .WIDTH(DATA_WIDTH+CTRL_WIDTH), .MAX_DEPTH_BITS(2))
     8             in_arb_fifo
     9             (// Outputs
    10             .dout ({fifo_out_ctrl[i], fifo_out_data[i]}),
    11             .full (),
    12             .nearly_full (nearly_full[i]),
    13             .prog_full (),
    14             .empty (empty[i]),
    15             // Inputs
    16             .din ({in_ctrl[i], in_data[i]}),
    17             .wr_en (in_wr[i]),
    18             .rd_en (rd_en[i]),
    19             .reset (reset),
    20             .clk (clk));
    21         end // block: in_arb_queues
    22 endgenerate
    23 
    24 2.generate if例子:
    25 generate
    26     if (REG_WIDTH == WRITE_WIDTH) 
    27         begin : new_data_a_generation
    28             assign new_data_a = merge_update ? merge_wr_data : held_wr_data_a;
    29         end
    30     else begin
    31             assign new_data_a = merge_update ?
    32 {{(REG_WIDTH - WRITE_WIDTH - 1){merge_wr_data_sign}}, merge_wr_data} :
    33 {{(REG_WIDTH - WRITE_WIDTH){held_wr_data_sign_a}}, held_wr_data_a};
    34         end
    35 endgenerate
    36 
    37 3.generate还可以进行多个assign赋值!
    38 module anytest_v(
    39 input clk,
    40 input[7:0] datain,
    41 output[7:0] dataout,
    42 output finish
    43 );
    44 
    45 wire[7:0] mem[31:0];
    46 wire[32*8-1:0] xxx;
    47 //reg[7:0] i;
    48 
    49 generate
    50     genvar i;
    51         for(i=0;i<=31;i=i+1)
    52             begin :wiertech
    53                 assign mem[i]= 8'b0;
    54             end
    55 endgenerate
    56 
    57 endmodule                        
  • 相关阅读:
    深搜的剪枝技巧(二)——生日蛋糕(优化搜索顺序、可行性剪枝,最优性剪枝)
    深搜的剪枝技巧(一)——树的划分(可行性剪枝、上下界剪枝)
    MATLAB 线性规划实例应用
    七大排序算法(下)
    七大排序算法(中)
    七大排序算法(上)
    二叉树的遍历
    链表的排序
    数据结构(三):链表的Java实现
    数据结构(二):队列的Java实现
  • 原文地址:https://www.cnblogs.com/streetlive/p/12640060.html
Copyright © 2011-2022 走看看