【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.