zoukankan      html  css  js  c++  java
  • 简单组合逻辑电路的verilog实现(包括三态门、38译码器、83优先编码器、8bit奇偶校验器)

    2013-06-14 15:20:28

    简单组合逻辑电路的verilog实现,包括三态门、3-8译码器、8-3优先编码器、8bit奇偶校验器,测试功能正确、可综合。


    小结:

    • assign与always都可实现组合逻辑,有什么区别?

    组合逻辑用数据流描述(一般将用assign描述的称为数据流描述)或者RTL描述(一般将用always描述的称为数据流描述)都可以实现;

    当组合逻辑较为简单时(如用一句话就可以实现的求反、求和assign sum = a + b; assign dout = ~din;等),用assign比较方便;

    若组合逻辑比较复杂,则用always比较合适。

    • 组合逻辑用always实现时,敏感列表一定要写全;
    • 写代码时,脑子里要有硬件的的概念,这是与C语言等软件语言的重要区别之一;
    • 为防止锁存器,对if语句要加上else,对case语句,要加上default

    如下面的就会产生锁存器:

     1 always@(din)
     2     begin
     3         if(din[7] == 1'b1) dout = 3'b111;
     4         else if(din[6] == 1'b1) dout = 3'b110;
     5         else if(din[5] == 1'b1) dout = 3'b101;
     6         else if(din[4] == 1'b1) dout = 3'b100;
     7         else if(din[3] == 1'b1) dout = 3'b011;
     8         else if(din[2] == 1'b1) dout = 3'b010;
     9         else if(din[1] == 1'b1) dout = 3'b001;
    10         else if(din[0] == 1'b1) dout = 3'b000;
    11         else dout = dout; 
    12     end

    改为如下,则不会有锁存器:

     1 always@(din)
     2     begin
     3         if(din[7] == 1'b1) dout = 3'b111;
     4         else if(din[6] == 1'b1) dout = 3'b110;
     5         else if(din[5] == 1'b1) dout = 3'b101;
     6         else if(din[4] == 1'b1) dout = 3'b100;
     7         else if(din[3] == 1'b1) dout = 3'b011;
     8         else if(din[2] == 1'b1) dout = 3'b010;
     9         else if(din[1] == 1'b1) dout = 3'b001;
    10         else dout = 3'b000;  //防止产生锁存器,将上面两行换为这一行
    11     end

    简单门电路的门级、数据流、RTL描述


    实现组合逻辑:f = ~(ab)|(bcd)

    代码:

     1 odule simple_gate(
     2                             a,
     3                             b,
     4                             c,
     5                             d,
     6                             f
     7                                  );
     8      
     9 input a;
    10 input b;     
    11 input c;
    12 input d;
    13 
    14 output f;
    15 /*
    16 //门级描述
    17 nand (f1,a,b);
    18 and (f2,b,c,d);
    19 
    20 or(f,f1,f2);
    21 
    22 //数据流描述
    23 assign f = ~(a & b) | (b & c & d);
    24 */
    25 //RTL描述
    26 reg f;
    27 always@(a,b,c,d)
    28     begin
    29         f = ~(a & b) | (b & c & d);
    30     end
    31 
    32 endmodule

    门级描述综合后得到的RTL级电路:

    数据流描述综合后得到的RTL级电路:

    RTL描述综合后得到的RTL级电路与数据流描述综合后得到的RTL级电路完全相同。


    三态门的门级、数据流、RTL描述:

    代码:

     1 module tri_gate(
     2                     din,
     3                     en,
     4                     dout
     5                          );
     6 
     7 
     8 input din;
     9 input en;
    10 
    11 output dout;
    12 
    13 //门级描述
    14 //bufif1 (dout,din,en);
    15 
    16 //数据流描述
    17 //assign dout = en ? din : 1'bz;
    18 
    19 //RTL描述
    20 reg dout;
    21 
    22 always@(din,en)
    23     if(en)
    24         dout = din;
    25     else
    26         dout = 1'bz;
    27 
    28 endmodule

    门级描述综合,RTL图:

    数据流描述综合,RTL图与门级的完全相同。

    RTL描述综合,RTL图同样与门级的完全相同。


    3-8译码器的verilog实现

    RTL描述,用case语句或if...if 语句实现,如下:

     1 module decode_3to8(
     2                         din,
     3                         dout
     4                              );
     5 
     6 input [2:0] din;
     7 output [7:0] dout;
     8 
     9 reg [7:0] dout;
    10 
    11 //case语句实现
    12 always@(din)
    13     case(din)
    14         3'b000 : dout = 8'b0000_0001;
    15         3'b001 : dout = 8'b0000_0010;
    16         3'b010 : dout = 8'b0000_0100;
    17         3'b011 : dout = 8'b0000_1000;
    18         3'b100 : dout = 8'b0001_0000;
    19         3'b101 : dout = 8'b0010_0000;
    20         3'b110 : dout = 8'b0100_0000;
    21         3'b111 : dout = 8'b1000_0000;
    22     endcase
    23 /*    
    24 //if...if语句实现
    25 always@(din)
    26     begin    
    27             if (din == 3'b000)  dout = 8'b0000_0001;
    28             if (din == 3'b001)  dout = 8'b0000_0010;
    29             if (din == 3'b010)  dout = 8'b0000_0100;
    30             if (din == 3'b011)  dout = 8'b0000_1000;
    31             if (din == 3'b100)  dout = 8'b0001_0000;
    32             if (din == 3'b101)  dout = 8'b0010_0000;
    33             if (din == 3'b110)  dout = 8'b0100_0000;
    34             if (din == 3'b111)  dout = 8'b1000_0000;
    35     end
    36 */    
    37 endmodule

    用case语句或if语句时:

     综合选项中Decoder Extraction设为YES,自动综合为用器件本身的硬件译码器实现,如下:

    若综合选项Decoder Extraction设为NO,用case语句或if语句,综合RTL图为:

    是用8bitROM实现的 


     8-3优先编码器的verilog实现

    RTL描述,用if...else的特点实现优先编码,如下:

     1 module encoder_8to3(
     2                             din,
     3                             dout
     4                                  );
     5 
     6 input [7:0] din;
     7 output [2:0] dout;
     8 
     9 reg [2:0] dout;
    10 
    11 //if语句中仅仅判断1个bit即可
    12 always@(din)
    13     begin
    14         if(din[7] == 1'b1) dout = 3'b111;
    15         else if(din[6] == 1'b1) dout = 3'b110;
    16         else if(din[5] == 1'b1) dout = 3'b101;
    17         else if(din[4] == 1'b1) dout = 3'b100;
    18         else if(din[3] == 1'b1) dout = 3'b011;
    19         else if(din[2] == 1'b1) dout = 3'b010;
    20         else if(din[1] == 1'b1) dout = 3'b001;
    21         //else if(din[0] == 1'b1) dout = 3'b000;
    22         //else dout = dout; 
    23         else dout = 3'b000;  //防止产生锁存器,将上面两行换为这一行
    24     end
    25 
    26 /*
    27 //if语句中仅仅判断1个bit即可,这种是错误的
    28 always@(din)
    29     begin
    30         if(din == 8'b1000_0000) dout = 3'b111;
    31         else if(din == 8'b0100_0000) dout = 3'b110;
    32         else if(din == 8'b0010_0000) dout = 3'b101;
    33         else if(din == 8'b0001_0000) dout = 3'b100;
    34         else if(din == 8'b0000_1000) dout = 3'b011;
    35         else if(din == 8'b0000_0100) dout = 3'b010;
    36         else if(din == 8'b0000_0010) dout = 3'b001;
    37         else if(din == 8'b0000_0001) dout = 3'b000;
    38     end
    39 */
    40 endmodule

    综合选项中Priority Encoder Extraction为YES,但是综合结果并没有使用优先编码器,原因未知。

    改变代码,去掉锁存器:

    //else if(din[0] == 1'b1) dout = 3'b000;
     //else dout = dout;
      else dout = 3'b000;  //防止产生锁存器,将上面两行换为这一行

    综合结果,可以看到,没有锁存器了:


     奇偶校验器的verilog实现

    数据流描述:

     1 module odd_even_check(
     2                             din,
     3                             dout_even,
     4                             dout_odd
     5                                  );
     6 
     7 input [7:0] din;
     8 output dout_even;
     9 output dout_odd;
    10 
    11 assign dout_odd = ^din;        //奇校验位
    12 assign dout_even = ~dout_odd;    //偶校验位
    13 
    14 endmodule

    综合RTL图:


     4选1数据选择器

    可以用case或者if语句实现:

     1 module mux(
     2                 din1,
     3                 din2,
     4                 din3,
     5                 din4,
     6                 sel,
     7                 dout
     8                      );
     9      
    10 input din1;
    11 input din2;
    12 input din3;
    13 input din4;
    14 input [1:0] sel;
    15 
    16 output dout;
    17 
    18 reg dout;
    19 /*
    20 //用case语句实现
    21 always@(din1,din2,din3,din4,sel)
    22     begin
    23         case(sel)
    24             2'b00 : dout = din1;
    25             2'b01 : dout = din2;
    26             2'b10 : dout = din3;
    27             default : dout = din4;    
    28         endcase
    29     end     
    30 */
    31 
    32 //用if语句实现
    33 always@(din1,din2,din3,din4,sel)
    34     begin
    35         if(sel == 2'b00) dout = din1;
    36         else if(sel == 2'b01) dout = din2;
    37         else if(sel == 2'b10) dout = din3;
    38         else dout = din4;
    39     end
    40 
    41 endmodule

    case语句与if语句描述综合结果完全相同,如下:

  • 相关阅读:
    利用Vista新技术WCF开发构建服务系统
    WCF开发入门的六个步骤
    C#开发WPF/Silverlight动画及游戏系列教程(Game Course):(一)让物体动起来①
    silverlight
    初探C#3.0
    通过托管代码和 Windows Vista 智能卡 API 来保护您的数据
    用例图
    类图
    Win7下MSN显示两个窗口问题
    设计模式初探
  • 原文地址:https://www.cnblogs.com/youngforever/p/3135874.html
Copyright © 2011-2022 走看看