$$ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Self-defined math definitions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Math symbol commands \newcommand{\intd}{\,{\rm d}} % Symbol 'd' used in integration, such as 'dx' \newcommand{\diff}{{\rm d}} % Symbol 'd' used in differentiation ... $$

【FPGA学习】- 组合逻辑电路

组合逻辑电路

  组合逻辑电路是指任意时刻的输出,只与当前时刻的输入有关,而与电路原来的状态无关。组合逻辑电路没有记忆功能。组合逻辑电路的基本特征是:(1)可以有多个输入端和输出端,每一个输出变量,与全部输入变量或部分输入变量有着固定的逻辑关系。(2)输出时全部输入或部分输入的逻辑函数。

组合逻辑电路的分析方法

  1.根据给定的逻辑电路图,写出各输出端的逻辑表达式;

  2.对各逻辑表达式进行化简与变换;

  3.列出真值表;

  4.逻辑功能的评述。

竞争与冒险

  在数字逻辑设计中,并不是说最简的逻辑表达式在设计组合逻辑时一定是最优的,因为有可能会产生竞争与冒险。所谓竞争是指不同路径输入信号变化传输到同一点门级电路,时间上有先后,这种现象称为竞争。冒险是指由于竞争存在,输出信号要经过一段时间才达到期望状态,过渡时间内可能产生瞬间的错误输出,这种现象称为冒险,一般在输出端可能会产生“尖峰脉冲”的现象,也被称为“毛刺”。有竞争不一定有冒险,但有冒险一定会有竞争。

  冒险按照产生形式分为静态冒险和动态冒险。静态冒险是指如果一个组合电路输入有变化时,输出不应发生变化的情况下,出现一次瞬间的错误变化就叫做静态冒险。动态冒险是指当输入有变化时,输出应有变化,但输出在变化的过程中出现短暂的错误的现象。静态冒险根据产生条件的不同,分为功能冒险和逻辑冒险两大类。当有两个或两个以上输入信号同时产生变化时,在输出端产生毛刺,这种冒险称为功能冒险。如果只有一个变量产生变化时出现的冒险则是逻辑冒险。由于冒险往往会影响到逻辑电路的稳定性,所以在设计的过程中需要消除冒险。

冒险的判断

  1.代数法:检查函数表达式中是否存在具备竞争条件的变量,若有,则消去函数表达式中的其他变量,若表达式在一定条件下能简化成:X+X'或X·X'的形式,则电路可能产生竞争冒险。X+X’ , 存在 “0” 型竞争;X·X’ ,存在 “1” 型竞争。

  2.卡诺图法:如果一个逻辑函数的表达式的卡洛图中所画圈没有重叠并且相切,则判定有竞争冒险。

  3.仿真模拟法:用计算机辅助分析的手段来分析组合逻辑电路,通过在计算机上运行数字电路的模拟程序,能够通过输出是否有“尖峰脉冲”现象从而迅速地判断出电路是否会出现竞争冒险现象。

冒险的消除

  1.增加冗余项:使得原函数不可能化简成X+X’或X·X’ 形式,从而消除了可能产生的竞争与冒险。

  2.增加选通电路:当电路达到稳定状态后,最后一级门电路选通。

  3. 输出端并联电容器:用门电路的输出电阻和电容器构成低通滤波电路,对很窄的尖峰脉冲(其频率很高)起到了平波的作用。这时在输出端便不会出现逻辑错误。

 典型的组合逻辑电路示例

编解码器

  1.优先编码器

  编码器设计

module encoder(i, y, none);
    input [7: 0] i;
    output reg [2: 0] y;
    output reg none;

    always @(*)
    begin
        if(i[7])    y = 3'b111;
        else if(i[6])   y = 3'b110;
        else if(i[5])   y = 3'b101;
        else if(i[4])   y = 3'b100;
        else if(i[3])   y = 3'b011;
        else if(i[2])   y = 3'b010;
        else if(i[1])   y = 3'b001;
        else if(i[0])   y = 3'b000;
        else   y = 3'b111;
    end

    always @(i)
    begin
        if(i == 8'b0000_0000)    none = 1;
        else    none = 0;
    end
endmodule

  编码器测试

`timescale 10ns/1ns  //`timescale 仿真时间单位/仿真时间精度
module encoder_test;
    reg [7: 0] I;
    wire [2: 0] Y;
    wire NONE;

    encoder e1(I, Y, NONE);

    initial begin
        I = 8'b0000_0001;
        wait( I == 8'd0 )
            $stop;
    end

    always #10 I = I << 1;
endmodule

  测试结果:

   2.七段数码管显示译码器

  七段数码管显示译码器设计

module decoder_seven(bcd, sevenout);
    input [3: 0] bcd;
    output reg [6: 0] sevenout;

    always @(*)
    begin
        case(bcd)
        4'b0000:sevenout = 7'b100_0000;
        4'b0001:sevenout = 7'b111_1001;
        4'b0010:sevenout = 7'b010_0100;
        4'b0011:sevenout = 7'b011_0000;
        4'b0100:sevenout = 7'b001_1001;
        4'b0101:sevenout = 7'b001_0010;
        4'b0110:sevenout = 7'b000_0010;
        4'b0111:sevenout = 7'b111_1000;
        4'b1000:sevenout = 7'b000_0000;
        4'b1001:sevenout = 7'b001_0000;
        4'b1010:sevenout = 7'b000_1000;    //10以后按照a-f显示
        4'b1011:sevenout = 7'b000_0011;
        4'b1100:sevenout = 7'b100_0110;
        4'b1101:sevenout = 7'b010_0001;
        4'b1110:sevenout = 7'b000_0110;
        4'b1111:sevenout = 7'b000_1110;
        default:sevenout = 7'b000_0110;
        endcase
    end
endmodule

  测试流程由于没有开发板,仿真波形不明显,暂时不进行仿真测试。(********待更新**********)

数据选择器

  数据选择器是指经过选择,把多个通道的数据传到唯一的公共数据通道上去,实现数据选择功能的逻辑电路,相当于多个输入的单刀多掷开关。在《Modelsim仿真软件的使用》中,示例便是一个二选一选择器。

  四选一数据选择器设计

module MUX4to1(A, G, D, Y);
    input [1: 0] A;
    input  G;
    input [3: 0] D;
    output reg Y;

    always @(*)
    begin
        if( G )
        begin
        case( A )
        2'b00:Y = D[0];
        2'b01:Y = D[1];
        2'b10:Y = D[2];
        2'b11:Y = D[3];
        endcase
        end
        else
        Y = 0;
    end
endmodule

  四选一数据选择器测试

`timescale 1ns/1ns
module NUX4to1_test;
    reg [1: 0] a;
    reg  g;
    reg [3: 0] d;
    wire y;

    MUX4to1 m1(a, g, d,y);

    initial begin
        a = 2'b00; g = 0; d = 4'b1010;
    #2  a = 2'b01; g = 0; d = 4'b1010;
    #2  a = 2'b10; g = 0; d = 4'b1010;
    #2  a = 2'b11; g = 0; d = 4'b1010;
    #2  a = 2'b00; g = 1; d = 4'b1010;
    #2  a = 2'b01; g = 1; d = 4'b1010;
    #2  a = 2'b10; g = 1; d = 4'b1010;
    #2  a = 2'b11; g = 1; d = 4'b1010;
    #2  a = 2'b00; g = 0; d = 4'b1010;
    $stop;
    end

    initial begin
        $monitor($time, "\tA = %d\tG = %b\tY = %b", a, g, y);
    end
    
endmodule

  测试结果

加法器

  加法器是较为常见的算术运算电路,更是计算机中不可或缺的一部分。

  4位全加器设计

module adder4(A, B, Cin, Cout, SUM);
    input [3: 0] A, B;
    input Cin;
    output reg [3: 0] SUM;
    output reg Cout;

    always @(*)
        {Cout, SUM} = A + B + Cin;
endmodule

  4位全加器测试

`timescale 1ns/1ns
module adder4_test;
    reg [3: 0] a, b;
    reg cin;
    wire [3: 0] sum;
    wire cout;

    adder4 a1(a, b, cin, cout, sum);

    initial begin
        cin = 1'd0; a = 4'd1; b = 4'd10;
    #1  cin = 1'd0; a = 4'd2; b = 4'd10;
    #1  cin = 1'd0; a = 4'd3; b = 4'd10;
    #1  cin = 1'd0; a = 4'd4; b = 4'd10;
    #1  cin = 1'd0; a = 4'd5; b = 4'd10;
    #1  cin = 1'd0; a = 4'd6; b = 4'd10;
    #1  cin = 1'd0; a = 4'd7; b = 4'd10;
     #1  cin = 1'd1; a = 4'd1; b = 4'd10;    //有低位进位
    #1  cin = 1'd1; a = 4'd2; b = 4'd10;
    #1  cin = 1'd1; a = 4'd3; b = 4'd10;
    #1  cin = 1'd1; a = 4'd4; b = 4'd10;
    #1  cin = 1'd1; a = 4'd5; b = 4'd10;
    #1  cin = 1'd1; a = 4'd6; b = 4'd10;
    #1  cin = 1'd1; a = 4'd7; b = 4'd10;
    #1  $stop;
    end

    initial begin
        $monitor($time,"\tCin=%d\tA=%d\tB=%d\tSUM=%d\t",cin, a, b, {cout, sum});//十进制输出方便观察,SUM直接包含进位的值
    end
endmodule

  测试结果

参考资料

[1] 组合逻辑电路详解、实现及其应用,知乎,https://zhuanlan.zhihu.com/p/133404280

[2] 黄海,于斌,Verilog HDL 设计实用教程[M],北京:清华大学出版社,2021.

[3] 周润景,李志,张玉光,基于Quartus Prime的数字系统Verilog HDL设计实例详解(第3版)[M],北京:电子工业出版社,2018.

posted @ 2023-02-27 20:09  素衣叹风尘  阅读(238)  评论(0)    收藏  举报