HDLbits-组合逻辑部分总结

Circuits_Combinational Logic

1.Multiplexers 总结

2-to1 multiplexer & 1.2 2-to1 bus multiplexer

2路选择器比较简单,可以直接用 ?:进行选择。

9-to1 multiplexer

在这里插入图片描述

9选1的直接用case语句即可,值得注意的有两点

  1. case语句中为了简便,可以用十六进制表示,相比二进制可以少写很多数字

  2. 对于case语句中没有提到的情况,一般用default写明,不过也可通过在always块中先赋初值来解决,如下所示:

always @(*) 
	begin
		out = 'hFFFF;		
		case (sel)
			...
		endcase
	end
module top_module( 
    input [15:0] a, b, c, d, e, f, g, h, i,
    input [3:0] sel,
    output [15:0] out );
	
    always@(*)
        begin
            case(sel)
                /*	both is ok
                4'b0000:out = a;
                4'b0001:out = b;
                4'b0010:out = c;
                4'b0011:out = d;
                4'b0100:out = e;
                4'b0101:out = f;
                4'b0110:out = g;
                4'b0111:out = h;
                4'b1000:out = i;
                default:out = 'hFFFF;
                */    
                'h0:out = a;
                'h1:out = b;
                'h2:out = c;
                'h3:out = d;
                'h4:out = e;
                'h5:out = f;
                'h6:out = g;
                'h7:out = h;
                'h8:out = i;
                default:out = 'hFFFF;
            endcase
        end
endmodule

Mux256to1

在这里插入图片描述
答案:

module top_module( 
    input [255:0] in,
    input [7:0] sel,
    output out );

    assign out = in[sel];
endmodule
  • 当case语句有很多的情况时,全部列出来就显得很不明智。这里就提供了一种讨巧的方法。直接sel和索引的一一对应关系,直接将sel当做索引。

Mux256to1v

在这里插入图片描述
然而,当你从上一题学到了这一讨巧的方法,想要依样画葫芦,写下

assign out = in [sel * 4 + 3:sel * 4];

编辑器会残酷的告诉你:NO!

这种讨巧的方法并不经常可行,原因是:

  • 使用变量索引从向量中选择一位是可行的,因为综合器可以确定所选位的宽度是恒定的。
  • 使用变量索引从向量中选择多位时不可行,因为综合器无法证明所选位的宽度是常数。

针对这个问题,有两种解决方法,一种是上一题讨巧方法的变种。不让我一起写,那我就分开写,再拼起来呗!

	assign out = {in[sel*4+3], in[sel*4+2], in[sel*4+1], in[sel*4+0]};

另外一种是采用有些不习惯的表达,也就是Verilog-2001的更新提供的位切片(索引矢量部分选择)的语法,具体如下

    assign out = in[4*sel+3 -: 4];	//起始:4*sel+3, “-:” 指往负方向,4表示4位,相当于[sel*4+3:sel*4]
    assign out = in[4*sel +: 4];		//起始:4*sel-3, “+:” 指往正方向,4表示4位,相当于[sel*4+3:sel*4]

2.Arithmetic Circuits 总结

3-bit binary adder & 4-digit BCD adder

在这里插入图片描述

在这里插入图片描述
这两题有以下共同点:
1.a和b的位数均大于1,因此在实例化的时候要注意输入和输出的位宽,比如

bcd_fadd u1_fadd(
       .a(a[3:0]),
       .b(b[3:0]),
       .cin(cin),
       .cout(cout_temp[0]),
       .sum(sum[3:0])
   );

2.要进行循环例化。注意不能直接用for,而要用generate语句搭配for循环。注意写的时候注意别漏了begin-end块的名字

generate
        genvar i;
        for(i=4;i<16;i=i+4)
            begin:fadder
                bcd_fadd u1_fadd(
                    .a(a[i+3:i]),
        			.b(b[i+3:i]),
                    .cin(cout_temp[i-4]),
        			.cout(cout_temp[i+3:i]),
                    .sum(sum[i+3:i]));
            end
    endgenerate

最后附上代码

//3-bit binary adder
module top_module( 
    input [2:0] a, b,
    input cin,
    output [2:0] cout,
    output [2:0] sum );

    fadd u1_fadd(
        .a(a[0]),
        .b(b[0]),
        .cin(cin),
        .cout(cout[0]),
        .sum(sum[0])
    				);
    generate				//多个例化不可只用for,要用generate
        genvar i;
            for(i=1;i<3;i=i+1)
                begin:adder	//注意别漏了模块名
                fadd u2_fadd(
                    .a(a[i]),
                    .b(b[i]),
                    .cin(cout[i-1]),
                    .cout(cout[i]),
                    .sum(sum[i])
    				);
                end
    endgenerate
endmodule

module fadd(input a,b,cin,
           output cout,sum);
    assign {cout,sum}=a+b+cin;
endmodule
    
//4-digit BCD adder
module top_module( 
    input [15:0] a, b,
    input cin,
    output cout,
    output [15:0] sum );

    wire [15:0] cout_temp;
    
    bcd_fadd u1_fadd(
        .a(a[3:0]),
        .b(b[3:0]),
        .cin(cin),
        .cout(cout_temp[0]),
        .sum(sum[3:0])
    );
    
    generate
        genvar i;
        for(i=4;i<16;i=i+4)
            begin:fadder
                bcd_fadd u1_fadd(
                    .a(a[i+3:i]),
        			.b(b[i+3:i]),
                    .cin(cout_temp[i-4]),
        			.cout(cout_temp[i+3:i]),
                    .sum(sum[i+3:i]));
            end
    endgenerate
                    
                    assign cout = cout_temp[12];
endmodule

Karnaugh Map to Circuit

Minimum SOP & POS

一个4输入a, b, c, d和一输出的逻辑电路,当输入为2, 7或15时,输出为1, 当输入为0, 1, 4, 5, 6, 9, 10, 13, 或 14 时,输出为0,当输入为3,8,11或12时输出为任意值。举例来说,7对应输入abcd为0,1,1,1.

module top_module (
    input a,
    input b,
    input c,
    input d,
    output out_sop,
    output out_pos
); 

    assign out_sop = (c & d) |  (~a & ~b & c);
    assign out_pos = c & (~a | ~c | d)&( ~b | ~c | d);
endmodule

在这里插入图片描述
解析:

  • SOP,按照卡诺图的原则,把1和x圈起来(如上图红圈),写出即可得出答案;
  • POS,把0圈起来(看黑圈),写出表达式。注意,此时是Y’,写成Y形式即可
    在这里插入图片描述

关于什么是SOP和POS,也就是最小项之和,最大项之积,大家可以参考下面这篇。
https://blog.51cto.com/physic/1305570

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hardworking_IC_boy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值