zoukankan      html  css  js  c++  java
  • 基础数字电路的Verilog写法

      Verilog是硬件描述电路,我对此一直稀里糊涂,于是将锆石科技开发板附带的的一些基础数字电路Verilog程序整理记录下来,并且查看他们的RTL视图,总算有点理解了。

      1.基本运算符

     1 module Example_Operation
     2 ( 
     3     input  [3:0]         a       ,
     4     input  [3:0]         b       ,
     5     input  [3:0]        c       ,
     6     
     7     output [3:0]        c1      ,
     8     output [3:0]        c2      ,
     9     output [5:0]        c3      ,
    10     output [3:0]        c4      ,
    11     output [3:0]        c5      ,
    12     output [3:0]        d1      ,
    13     output [3:0]        d2      ,
    14     output [3:0]        d3      ,
    15     output [3:0]        d4      ,
    16     output [3:0]        e1      ,
    17     output [3:0]        e2      ,
    18     output [3:0]        e3      ,
    19     output [3:0]        f1      ,
    20     output [3:0]        f2      ,
    21     output [3:0]        d11     ,
    22     output [3:0]        c11     ,
    23     output [3:0]        c22     ,
    24     output [3:0]        c33     ,
    25     output [3:0]        c44     ,
    26     output [3:0]        c55     ,
    27     output [3:0]        c66     ,
    28     output [3:0]        e11     ,
    29     output [3:0]        e22     ,
    30     output [7:0]        f11     ,
    31     output [7:0]        f22
    32 );
    33 
    34 //== waveform1 算数运算符
    35 //======================================================================
    36 assign c1 = a + b;      //
    37 assign c2 = a - b;      //
    38 assign c3 = a * b;      //
    39 assign c4 = a / b;      //
    40 assign c5 = a % b;      //求余
    41 
    42 //== waveform2 关系运算符
    43 //======================================================================
    44 assign d1 = a >  b;     //大于
    45 assign d2 = a <  b;     //小于
    46 assign d3 = a >= b;     //大于等于
    47 assign d4 = a <= b;     //小于等于
    48 
    49 //== waveform3 逻辑运算符
    50 //======================================================================
    51 assign e1 = !a;         //
    52 assign e2 = a && b;     //
    53 assign e3 = a || b;     //54 
    55 //== waveform4 逻辑等式运算符
    56 //======================================================================
    57 assign f1 = a == b;     //判断相等
    58 assign f2 = a != b;     //判断不等
    59 
    60 //== waveform5 三目条件运算符
    61 //======================================================================
    62 assign d11 = a ? b : c; //a为真,则d11 = b
    63                         //a为假,则d11 = c
    64 
    65 //== waveform6 位运算符
    66 //======================================================================
    67 assign c11 = ~a;        //取反
    68 assign c22 = a & b;     //按位与
    69 assign c33 = a | b;     //按位或
    70 assign c44 = a ^ b;     //按位异或
    71 assign c55 = a ~^ b;    //按位同或
    72 assign c66 = a ^~ b;    //按位同或
    73 
    74 //== waveform7 移位运算符 
    75 //======================================================================
    76 assign e11 = a << b;    //左移
    77 assign e22 = a >> b;    //右移
    78 
    79 //== waveform8 位拼接运算符
    80 //======================================================================
    81 assign f11 = {a , b};   //拼接a和b,a和b位宽均为4,f11位宽为8
    82 assign f22 = {2'd2{b}}; //拼接b低2位
    83 
    84 endmodule
    View Code

      2.三人表决器 --- 结构描述方式

     1 module Example_Structure
     2 (
     3     input       A   ,   //模块的输入端口A
     4     input       B   ,   //模块的输入端口B
     5     input       C   ,   //模块的输入端口C
     6     output      L       //模块的输出端口L
     7 );
     8 
     9 //== 信号定义
    10 //======================================================================
    11 wire AB,BC,AC;          //内部信号声明AB,BC,AC
    12 
    13 and U1(AB,A,B);         //与门(A,B信号进入)(A与B信号即AB输出)          
    14 and U2(BC,B,C);         //与门 同上
    15 and U3(AC,A,C);         //与门 同上
    16   
    17 or  U4(L,AB,BC,AC);     //或门 同上
    18      
    19 endmodule
    View Code

      3.三人表决器 --- 数据流描述方式

     1 module Example_Dataflow
     2 (
     3     input   A   ,     //模块的输入端口A
     4     input   B   ,     //模块的输入端口B
     5     input   C   ,     //模块的输入端口C
     6     output  L         //模块的输出端口L
     7 );
     8 
     9 assign L = ((!A) & B & C) | (A & (!B) & C) | (A & B & (!C)) | (A & B & C);
    10 
    11 endmodule
    View Code

      4.三人表决器 --- 行为描述方式

     1 module Example_Behavior
     2 (
     3     input           A   ,    //模块的输入端口A
     4     input           B   ,    //模块的输入端口B
     5     input           C   ,    //模块的输入端口C
     6     output reg      L        //模块的输出端口L
     7 );
     8 
     9 always @(A,C,B)begin        //敏感列表只需要A、B、C,也可以写成always @(*)
    10     case({A,B,C})           //注意{A,B,C}是位拼接,合成一条总线
    11         3'b000: L = 1'b0;
    12         3'b001: L = 1'b0;
    13         3'b010: L = 1'b0;
    14         3'b011: L = 1'b1;
    15         3'b100: L = 1'b0;
    16         3'b101: L = 1'b1;
    17         3'b110: L = 1'b1;
    18         3'b111: L = 1'b1;
    19         default:L = 1'bx;   //default不要省略
    20     endcase
    21 end
    22 
    23 endmodule
    View Code

       5.模块化设计实现半加器

     1 module Example_Module
     2 (
     3     input       a       ,
     4     input       b       ,
     5     output      s       ,
     6     output      c
     7 );
     8 
     9 //== 实例化 与门
    10 //======================================================================
    11 Example_yumen yumen_module
    12 (
    13     .yumen_a(a),
    14     .yumen_b(b),
    15     .yumen_c(c)
    16 );
    17 
    18 //== 实例化 异或
    19 //======================================================================
    20 Example_yihuo yihuo_module
    21 (
    22     .yihuo_a(a),
    23     .yihuo_b(b),
    24     .yihuo_s(s)
    25 );
    26 
    27 endmodule
    Top
     1 module Example_yihuo
     2 (
     3     input       yihuo_a     ,
     4     input       yihuo_b     ,
     5     output      yihuo_s
     6 );
     7 
     8 assign yihuo_s = yihuo_a ^ yihuo_b;
     9 
    10 endmodule
    Yihuo
     1 module Example_yumen
     2 (
     3     input       yumen_a     ,
     4     input       yumen_b     ,
     5     output      yumen_c
     6 );
     7 
     8 assign yumen_c = yumen_a && yumen_b;
     9 
    10 endmodule
    Yumen

    6.8-1数据选择器

     1 module Digital_Selector
     2 (
     3     input               D0          ,
     4     input               D1          ,
     5     input               D2          ,
     6     input               D3          ,
     7     input               D4          ,
     8     input               D5          ,
     9     input               D6          ,
    10     input               D7          ,
    11     input      [ 2:0]   A           ,
    12     output reg [ 7:0]   Y
    13 );
    14 
    15 always @(*)begin
    16     case(A)
    17         3'b000 : Y = D0;
    18         3'b001 : Y = D1;
    19         3'b010 : Y = D2;
    20         3'b011 : Y = D3;
    21         3'b100 : Y = D4;
    22         3'b101 : Y = D5;
    23         3'b110 : Y = D6;
    24         3'b111 : Y = D7;
    25         default: Y = 1'b0;
    26     endcase
    27 end
    28 
    29 endmodule
    View Code

    7.8-3编码器

     1 module Digital_Encoder
     2 (
     3     input      [ 7:0]   I               ,
     4     output reg [ 2:0]   A
     5 );
     6 
     7 //== case判断I,8位数转为3位数
     8 //======================================================================
     9 always @(*)begin
    10     case(I)
    11         8'b0000_0001 : A = 3'b000;
    12         8'b0000_0010 : A = 3'b001;
    13         8'b0000_0100 : A = 3'b010;
    14         8'b0000_1000 : A = 3'b011;
    15         8'b0001_0000 : A = 3'b100;
    16         8'b0010_0000 : A = 3'b101;
    17         8'b0100_0000 : A = 3'b110;
    18         8'b1000_0000 : A = 3'b111;
    19         default:       A = 3'b000;
    20     endcase
    21 end
    22 
    23 
    24 /*
    25 //== if...else优先级写法,优先级从上到下
    26 //======================================================================
    27 always @(*)begin
    28     if(I[7] == 1'b0)          A = 3'b000;
    29     else if(I[6] == 1'b0)     A = 3'b001;
    30     else if(I[5] == 1'b0)     A = 3'b010;
    31     else if(I[4] == 1'b0)   A = 3'b011;
    32     else if(I[3] == 1'b0)     A = 3'b100;
    33     else if(I[2] == 1'b0)     A = 3'b101;
    34     else if(I[1] == 1'b0)     A = 3'b110;
    35     else if(I[0] == 1'b0)    A = 3'b111;
    36     else                      A = 3'b000;
    37 end
    38 */
    39 
    40 endmodule
    View Code

    8.3-8译码器

     1 module Digital_Decoder
     2 (
     3     input      [ 2:0]   A           ,
     4     output reg [ 7:0]   I
     5 );
     6 
     7 always @(*)begin
     8     case(A)
     9         3'b000 : I = 8'b01111111;
    10         3'b001 : I = 8'b10111111;
    11         3'b010 : I = 8'b11011111;
    12         3'b011 : I = 8'b11101111;
    13         3'b100 : I = 8'b11110111;
    14         3'b101 : I = 8'b11111011;
    15         3'b110 : I = 8'b11111101;
    16         3'b111 : I = 8'b11111110;
    17         default: I = 8'b11111111;
    18     endcase
    19 end
    20 
    21 endmodule
    View Code

    9.D触发器

     1 module Digital_Data_Flip_Flop
     2 (
     3     input               clk         ,
     4     input               rst_n       ,
     5     input               D           ,
     6     output reg          Q
     7 );
     8 
     9 always @(posedge clk or negedge rst_n)begin
    10     if(!rst_n)
    11         Q <= 1'b0;
    12     else
    13         Q <= D;
    14 end
    15 
    16 endmodule
    View Code

    10.4bit移位寄存器

     1 module Digital_Shift_Reg
     2 (
     3     input               clk         ,
     4     input               rst_n       ,
     5     input               data_in     ,
     6     input               data_en     ,
     7     output reg [ 3:0]   data_out    ,
     8     output reg [ 3:0]   data_out_n
     9 );
    10 
    11 //== 时序逻辑,寄存data_out_n的值,所以看起来比data_out_n慢一拍
    12 //======================================================================
    13 always @(posedge clk or negedge rst_n)begin
    14     if(!rst_n)
    15         data_out <= 4'b0;
    16     else
    17         data_out <= data_out_n;
    18 end
    19 
    20 //== 组合逻辑,不断移位
    21 //======================================================================
    22 always @(*)begin
    23     if(data_en)
    24         data_out_n = {data_out[2:0],data_in};
    25     else
    26         data_out_n = data_out;
    27 end
    28 
    29 /*----------------------------------------------------------------------
    30 --补充:如果要实现循环右移,则写成[data_in,data_out[3:1]]
    31 ----------------------------------------------------------------------*/
    32 
    33 
    34 endmodule
    View Code

    11.反馈回环的正误解析

     1 //== 错误写法:data_out既是条件又是结果
     2 //======================================================================
     3 module Example_Feedback
     4 (
     5     input     data_in1    ,
     6     input     data_in2    ,
     7     output     data_out
     8 );
     9                             //data_out是最终结果,可又是形成条件
    10 assign data_out = (data_in2) ? data_in1 : (~data_out | data_in1);
    11 
    12 endmodule
    13 
    14 
    15 /*
    16 //== 正确写法:用data_out_r寄存一下,再给data_out
    17 //======================================================================
    18 module Example_Feedback
    19 (
    20     input     clk         ,
    21     input     rst_n       ,
    22     input     data_in1    ,
    23     input     data_in2    ,
    24     output     data_out
    25 );
    26 
    27 //信号定义
    28 reg         data_out_r  ;
    29 
    30 //时序逻辑,寄存结果
    31 always @ (posedge clk or negedge rst_n)
    32 begin
    33     if(!rst_n)
    34         data_out_r <= 1'b0;
    35     else
    36         data_out_r <= (data_in2) ? (data_in1) : (~data_out_r | data_in1);
    37 end
    38 
    39 //寄存后的结果再输出
    40 assign data_out = data_out_r;
    41 
    42 endmodule
    43 */
    View Code

    12.阻塞赋值和非阻塞赋值

     1 module Example_Block
     2 (
     3     input        clk             ,
     4     input        block_in        ,
     5     output         block_out1      ,
     6     output         block_out2      ,
     7     output         no_block_out1   ,
     8     output         no_block_out2
     9 );
    10 
    11 //block模块例化
    12 block block_init
    13 (
    14     .clk            (clk        ),
    15     .block_in        (block_in    ),
    16     .block_out1        (block_out1    ),
    17     .block_out2        (block_out2    )
    18 );
    19 
    20 //no_block模块例化
    21 no_block no_block_init
    22 (
    23     .clk            (clk            ),
    24     .no_block_in    (block_in        ),
    25     .no_block_out1    (no_block_out1    ),
    26     .no_block_out2    (no_block_out2    )
    27 );
    28 
    29 endmodule
    Top
     1 module block
     2 (
     3     input        clk         ,
     4     input        block_in    ,
     5     output reg  block_out1  ,
     6     output reg  block_out2
     7 );
     8 
     9 always @(posedge clk)begin
    10     block_out1 = block_in;
    11     block_out2 = block_out1;
    12 end
    13 
    14 endmodule
    Block
     1 module no_block
     2 (
     3     input        clk             ,
     4     input        no_block_in     ,
     5     output reg  no_block_out1   ,
     6     output reg  no_block_out2
     7 );
     8 
     9 always @(posedge clk)begin
    10     no_block_out1 <= no_block_in;
    11     no_block_out2 <= no_block_out1;
    12 end
    13 
    14 endmodule
    no_Block

      这些基础数字电路的Verilog描述应该非常熟悉,才能够为后面的学习打下扎实的基础。

    参考资料:[1]锆石科技FPGA教程

  • 相关阅读:
    Oracle 创建表并设置主键自增
    Oracle 基本知识回顾
    关于JAVAweb的一些东西
    JAVA获取运行环境的信息
    关于正则表达式的一些东西
    关于jQuery的一些东西
    关于JS的一些东西
    thymeleaf 的使用
    小程序flex容器
    Vue组件化
  • 原文地址:https://www.cnblogs.com/xianyufpga/p/10907302.html
Copyright © 2011-2022 走看看