• verilog练习——组合逻辑


    目录

    组合逻辑

    VL11 4位数值比较器电路

    VL12 4bit超前进位加法器电路

    VL13 优先编码器电路①

    VL14 用优先编码器①实现键盘编码电路

    VL15 优先编码器Ⅰ

    VL16 使用8线-3线优先编码器Ⅰ

    VL17 用3-8译码器实现全减器

    VL18 实现3-8译码器①

    VL19 使用3-8译码器①实现逻辑函数L

    VL20 数据选择器实现逻辑电路


    工程源码

    GitHub - ningbo99128/verilog: 牛客网练习题工程

    组合逻辑

    VL11 4位数值比较器电路

            至于为什么不选择更底层的题解?原因有,刷题是为了走数字ic设计,用这种门级电路搭出来的功能,其实没必要,面试也不会考。在代码上,底层到&、|、!、<<等位操作就可以了,没必要用xnor、or、and、not等描述。下面这个解题思路不错,还可以练习一下“例化”的for循环调用,挺好的。

    4位数值比较器电路_牛客题霸_牛客网

            从RTL图中,可以看出代码的逻辑是先计算A[3]、B[3]和A[2]、B[2]和A[1]、B[1]和A[0]、B[0]等2位比较的结果,再通过真值表写出对应的逻辑表达式即可。

    4位数值比较器电路RTL图

    1. //根据题目的真值表
    2. assign Y2 = result_y2[3]|(result_y1[3]&result_y2[2])|
    3. (result_y1[3]& result_y1[2]&result_y2[1])|
    4. (result_y1[3]& result_y1[2]&result_y1[1]&result_y2[0]);
    5. assign Y1 = result_y1[3]&result_y1[2]&result_y1[1]&result_y1[0];
    6. assign Y0 = result_y0[3]|(result_y1[3]&result_y0[2])|
    7. (result_y1[3]& result_y1[2]&result_y0[1])|
    8. (result_y1[3]& result_y1[2]&result_y1[1]&result_y0[0]);

     for循环例化


    VL12 4bit超前进位加法器电路

    多位加法器和超前进位加法器相比,为什么速度慢?

            主要原因是高位相加时,要等待低位相加产生的进位,如果这个A、B是32位的,最高位要等31个1位全加器的耗时,才能等到进位。

            超前进位加法器,就是把所有位的进位提前算出来,然后同时计算S[i] = A[i] + B[i] + C[i]。这样就快很多了。

     注意:C_1是最初的进位,用来计算A_in[0]和B_in[0]的进位。

     代码如下:

    1. module lca_4(
    2. input [3:0] A_in ,
    3. input [3:0] B_in ,
    4. input C_1 ,
    5. output wire CO ,
    6. output wire [3:0] S
    7. );
    8. wire [3:0] G; //G=A_in&B_in
    9. wire [3:0] P; //P=A_in^B_in
    10. wire [3:0] C;
    11. genvar i;
    12. generate
    13. for(i = 0; i < 4;i = i + 1)
    14. begin: PG_bit
    15. assign G[i] = A_in[i] & B_in[i];
    16. assign P[i] = A_in[i] ^ B_in[i];
    17. end
    18. endgenerate
    19. assign C[0] = G[0] | (P[0]&C_1);
    20. assign S[0] = P[0] ^ C_1;
    21. genvar c_i;//c_i范围1-3
    22. generate
    23. for(c_i = 1; c_i < 4;c_i = c_i + 1)
    24. begin: SC_bit
    25. assign C[c_i] = G[c_i] | (P[c_i] & C[c_i-1]);
    26. assign S[c_i] = P[c_i] ^ C[c_i-1];
    27. end
    28. endgenerate
    29. assign CO = C[3];
    30. endmodule

    VL13 优先编码器电路①

    概念:优先编码器可以同时输入几个信号,但在设计时已经将各输入信号的优先顺序排好。当几个信号同时输入时,优先权最高的信号优先编码

    (9选4)优先编码器实现最方便的是使用 case语句,如下:

    1. always @(*)begin
    2. casex(I_n)
    3. 9'b111111111 : Y_n = 4'b1111;
    4. 9'b0xxxxxxxx : Y_n = 4'b0110;
    5. 9'b10xxxxxxx : Y_n = 4'b0111;
    6. 9'b110xxxxxx : Y_n = 4'b1000;
    7. 9'b1110xxxxx : Y_n = 4'b1001;
    8. 9'b11110xxxx : Y_n = 4'b1010;
    9. 9'b111110xxx : Y_n = 4'b1011;
    10. 9'b1111110xx : Y_n = 4'b1100;
    11. 9'b11111110x : Y_n = 4'b1101;
    12. 9'b111111110 : Y_n = 4'b1110;
    13. default : Y_n = 4'b1111;
    14. endcase
    15. end

    case、casez、casex辨析:

    1、在case语句中,敏感表达式中与各项值之间的比较是一种全等比较,每一位都相同才认为匹配。

    2、在casez语句中,如果分支表达式某些位的值为高阻z,那么对这些位的比较就会忽略,不予考虑,而只关注其他位的比较结果。

    3、在casex语句中,则把这种处理方式进一步扩展到对x的处理,即如果比较双方有一方的某些位的值是z或x,那么这些位的比较就不予考虑。

    参考文章:Verilog语言中case、casex、casez的用法和区别_摆渡沧桑的博客-CSDN博客_casex和casez


    VL14 用优先编码器①实现键盘编码电路

    题目:

            请使用优先编码器①实现键盘编码电路,可添加并例化题目中已给出的优先编码器代码。10个按键分别对应十进制数0-9,按键9的优先级别最高;按键悬空时,按键输出高电平,按键按下时,按键输出低电平;键盘编码电路的输出是8421BCD码。要求:键盘编码电路要有工作状态标志,以区分没有按键按下和按键0按下两种情况。

     题目解析:

    键盘状态

    S[9:0]

    L[3:0]

    GS

    无按键按下

    11_1111_1111

    0000

    0

    按键0按下

    11_1111_1110

    0000

    1

    其他按键按下

    xx_xxxx_xxx1

    xx

    1

    代码:

    1. module key_encoder(
    2. input [9:0] S_n ,
    3. output wire[3:0] L ,
    4. output wire GS
    5. );
    6. wire [3:0] L_reg;
    7. encoder_0 u1_encoder_0(
    8. .I_n(S_n[9:1]),
    9. .Y_n(L_reg)
    10. );
    11. //有按键按下 GS == 1
    12. assign GS = ~((&L_reg) & S_n[0]);
    13. assign L = (GS == 1)? ~L_reg : 4'b0;
    14. endmodule

    VL15 优先编码器Ⅰ

            VL15和VL13的区别是 这次题目8-3优先编码器只给定了wire型的输出变量,意味着要找到逻辑关系用assign来描述实现,而不能用case语句去描述。

     解析:

    ①当EI=1,I=0时,EO=1,其余为0;因此EO = EI &  ~(|I)。

    ②当EI=1,I ≠ 0时,GS = 1,其余为0;因此GS = EI &  (|I)。

    ③同理,当EI=1,I = 8'b1xxx_xxxx、I = 8'b01xx_xxxx、I = 8'b0000_1xxx、I = 8'b0000_01xx4种状态时,Y[1] = 1。因此我们可以描述为assign Y[1] = EI & (I[7] | I[6] | (~I[7]&~I[6]&~I[5]&~I[4]&I[3]) | (~I[7]&~I[6]&~I[5]&~I[4]&~I[3]&I[2]) );

    但是,为什么最终代码把红色部分省略了?

    因为红色部分省略后并不影响表达式的逻辑功能,可以减少冗余。例如,I[7]和I[6]的状态1已经使用过,那么剩下的只有假状态。因此~I[7]&~I[6] 没有必要再写出来。

    1. assign Y[2] = EI & (I[7] | I[6] | I[5] | I[4]);
    2. assign Y[1] = EI & (I[7] | I[6] | (~I[5]&~I[4]&I[3]) | (~I[5]&~I[4]&I[2]));
    3. assign Y[0] = EI & (I[7] | (~I[6]&I[5]) | (~I[6]&~I[4]&I[3]) | (~I[6]&~I[4]&~I[2]&I[0]));
    4. assign GS = EI & (|I); //I的每一位相或
    5. assign EO = EI & ~(|I);

    VL16 使用8线-3线优先编码器Ⅰ

    题目:请使用2片8线-3线优先编码器Ⅰ及必要的逻辑电路实现16线-4线优先编码器。优先编码器Ⅰ的真值表和代码已给出(VL15)。

    解析:看逻辑图写代码

    1. module encoder_164(
    2. input [15:0] A ,
    3. input EI ,
    4. output wire [3:0] L ,
    5. output wire GS ,
    6. output wire EO
    7. );
    8. wire GS_1;
    9. wire EO_1;
    10. wire GS_2;
    11. wire EO_2;
    12. wire [2:0] Y_1;
    13. wire [2:0] Y_2;
    14. encoder_83 u1_encoder_83( //高位
    15. .I(A[15:8]) ,
    16. .EI(EI) ,
    17. .Y (Y_1 ) ,
    18. .GS(GS_1) ,
    19. .EO(EO_1)
    20. );
    21. encoder_83 u2_encoder_83( //低位
    22. .I(A[7:0]) ,
    23. .EI(EO_1) ,
    24. .Y (Y_2 ) ,
    25. .GS(GS_2) ,
    26. .EO(EO_2)
    27. );
    28. assign L[3] = GS_1;
    29. assign L[2] = Y_1[2] | Y_2[2];
    30. assign L[1] = Y_1[1] | Y_2[1];
    31. assign L[0] = Y_1[0] | Y_2[0];
    32. assign GS = GS_1 | GS_2;
    33. assign EO = EO_2;
    34. endmodule

    VL17 用3-8译码器实现全减器

    题目分析:

            先写出一位全减器真值表,再给 D 和 Co 分别例化一个3-8译码器,再将有输出的位进行与非。

     例如:采用3-8译码器和与非门实现D的逻辑功能。

    代码实现:

    1. module decoder1(
    2. input A , //被减数
    3. input B ,
    4. input Ci , //借位
    5. output wire D , //
    6. output wire Co //借位
    7. );
    8. wire D_0,D_1,D_2,D_3,D_4,D_5,D_6,D_7;
    9. wire Co_0,Co_1,Co_2,Co_3,Co_4,Co_5,Co_6,Co_7;
    10. decoder_38 u1_decoder_38( //差D
    11. .E (E ),
    12. .A0 (Ci ),
    13. .A1 (B ),
    14. .A2 (A ),
    15. .Y0n (D_0 ),
    16. .Y1n (D_1 ),
    17. .Y2n (D_2 ),
    18. .Y3n (D_3 ),
    19. .Y4n (D_4 ),
    20. .Y5n (D_5 ),
    21. .Y6n (D_6 ),
    22. .Y7n (D_7 )
    23. );
    24. decoder_38 u2_decoder_38( //借位Co
    25. .E (E ),
    26. .A0 (Ci ),
    27. .A1 (B ),
    28. .A2 (A ),
    29. .Y0n (Co_0 ),
    30. .Y1n (Co_1 ),
    31. .Y2n (Co_2 ),
    32. .Y3n (Co_3 ),
    33. .Y4n (Co_4 ),
    34. .Y5n (Co_5 ),
    35. .Y6n (Co_6 ),
    36. .Y7n (Co_7 )
    37. );
    38. //1、全减器真值表 2、按真值表代入
    39. assign D = ~((D_1) & (D_2) & (D_4) & (D_7));
    40. assign Co = ~((Co_1) & (Co_2) & (Co_3) & (Co_7));
    41. endmodule

    VL18 实现3-8译码器①

    看真值表写代码:

    1. `timescale 1ns/1ns
    2. module decoder_38(
    3. input E1_n ,
    4. input E2_n ,
    5. input E3 ,
    6. input A0 ,
    7. input A1 ,
    8. input A2 ,
    9. output wire Y0_n ,
    10. output wire Y1_n ,
    11. output wire Y2_n ,
    12. output wire Y3_n ,
    13. output wire Y4_n ,
    14. output wire Y5_n ,
    15. output wire Y6_n ,
    16. output wire Y7_n
    17. );
    18. wire E;
    19. assign E = E3 & (~E2_n) & (~E1_n);
    20. assign Y0_n = ~(E & (~A2) & (~A1) & (~A0));
    21. assign Y1_n = ~(E & (~A2) & (~A1) & (A0));
    22. assign Y2_n = ~(E & (~A2) & (A1) & (~A0));
    23. assign Y3_n = ~(E & (~A2) & (A1) & (A0));
    24. assign Y4_n = ~(E & (A2) & (~A1) & (~A0));
    25. assign Y5_n = ~(E & (A2) & (~A1) & (A0));
    26. assign Y6_n = ~(E & (A2) & (A1) & (~A0));
    27. assign Y7_n = ~(E & (A2) & (A1) & (A0));
    28. endmodule

    VL19 使用3-8译码器①实现逻辑函数L

            请使用3-8译码器①和必要的逻辑门实现函数L=(~A)·C+A·B

    1. module decoder0(
    2. input A ,
    3. input B ,
    4. input C ,
    5. output wire L
    6. );
    7. decoder_38 u1_decoder_38(
    8. .E1_n (0 ) ,
    9. .E2_n (0 ) ,
    10. .E3 (1 ) ,
    11. .A0 (C ) ,
    12. .A1 (B ) ,
    13. .A2 (A ) ,
    14. .Y0_n (Y0_n ) ,
    15. .Y1_n (Y1_n ) ,
    16. .Y2_n (Y2_n ) ,
    17. .Y3_n (Y3_n ) ,
    18. .Y4_n (Y4_n ) ,
    19. .Y5_n (Y5_n ) ,
    20. .Y6_n (Y6_n ) ,
    21. .Y7_n (Y7_n )
    22. );
    23. //38译码器 有效输出为0
    24. assign L = ~(Y1_n & Y3_n & Y6_n & Y7_n);
    25. endmodule

    VL20 数据选择器实现逻辑电路

    题目分析:四选一数据选择器实现3变量逻辑电路,会要用到降维,否则表达的情况不够。

    L = AB + AC' + BC = AC' + BC

    真值表 L = AC' + BC
    卡诺图降维
    1. `timescale 1ns/1ns
    2. module data_sel(
    3. input S0 ,
    4. input S1 ,
    5. input D0 ,
    6. input D1 ,
    7. input D2 ,
    8. input D3 ,
    9. output wire Y
    10. );
    11. assign Y = ~S1 & (~S0&D0 | S0&D1) | S1&(~S0&D2 | S0&D3);
    12. endmodule
    13. module sel_exp(
    14. input A ,
    15. input B ,
    16. input C ,
    17. output wire L
    18. );
    19. data_sel u0_data_sel( //高位
    20. .S1(A ),
    21. .S0(B ),
    22. .D3(1 ),
    23. .D2(~C ),
    24. .D1(C ),
    25. .D0(0 ),
    26. .Y (L )
    27. );
    28. endmodule

            耶,到这里就结束了组合逻辑,下面就是时序逻辑学习啦!放一张哆啦A梦

  • 相关阅读:
    【自学笔记】如何在 Python 中使用 YAML 文件? 了解 YAML 格式和规范
    Linux 13:TCP编程 / UDP编程
    Databend 开源周报 #69
    html所有标签和DOCTYPE的总结
    树形dp题单训练
    回归分析中的异方差性
    【字符串】函数的独占时间 栈
    【Hadoop】二、Hadoop MapReduce与Hadoop YARN
    自学SAP是学习ECC版本还是S4版本?
    .NET应用程序--Helloworld(C#)
  • 原文地址:https://blog.csdn.net/qq_40528849/article/details/128052955