【hdlbits】个人学习交流分享(带答案)——combinational logic部分

hdlbits网站:HDLBits (01xz.net)

verilog language部分:【hdlbits】个人学习交流分享(带答案)——verilog language部分-CSDN博客

正文:

Basic gates

basic gates这一块内容很简单,很多之前verilog language部分就做过,这部分直接放答案

wire

module top_module (
    input in,
    output out);
    assign out=in;
endmodule

GND

module top_module (
    output out);
    assign out=1'b0;
endmodule

NOR

module top_module (
    input in1,
    input in2,
    output out);
    assign out=~(in1|in2);
endmodule

another gate

module top_module (
    input in1,
    input in2,
    output out);
    assign out=in1&(~in2);
endmodule

two gates

module top_module (
    input in1,
    input in2,
    input in3,
    output out);
    wire a;
    assign a=~(in1^in2);
    assign out=a^in3;
endmodule

more logic gates

module top_module( 
    input a, b,
    output out_and,
    output out_or,
    output out_xor,
    output out_nand,
    output out_nor,
    output out_xnor,
    output out_anotb
    );
    assign out_and=a&b;
    assign out_or=a|b;
    assign out_xor=a^b;
    assign out_nand=~(a&b);
    assign out_nor=~(a|b);
    assign out_xnor=~(a^b);
    assign out_anotb=a&(~b);
endmodule

7420 chip

module top_module ( 
    input p1a, p1b, p1c, p1d,
    output p1y,
    input p2a, p2b, p2c, p2d,
    output p2y );
    assign p1y=~(p1a&p1b&p1c&p1d);
    assign p2y=~(p2a&p2b&p2c&p2d);
endmodule

truth tables

module top_module( 
    input x3,
    input x2,
    input x1,  // three inputs
    output f   // one output
);
    assign f=(x2&~x3)|(x1&x3);
endmodule

two-bit equality

module top_module ( input [1:0] A, input [1:0] B, output z ); 
    assign 	z=(A==B)?1'b1:1'b0;
endmodule

simple circuit A

module top_module (input x, input y, output z);
    assign z=(x^y)&x;
endmodule

simple circuit B

module top_module ( input x, input y, output z );
    assign z=~(x^y);
endmodule

combine circuit A and B

module top_module (input x, input y, output z);
wire o1, o2, o3, o4;
	
	A ia1 (x, y, o1);
	B ib1 (x, y, o2);
	A ia2 (x, y, o3);
	B ib2 (x, y, o4);
	
	assign z = (o1 | o2) ^ (o3 & o4);
	
endmodule

module A (
	input x,
	input y,
	output z);

	assign z = (x^y) & x;
	
endmodule

module B (
	input x,
	input y,
	output z);

	assign z = ~(x^y);
endmodule

ring or vibrate?

答案1:从输入条件思考,编写if else语句

module top_module (
    input ring,
    input vibrate_mode,
    output ringer,       // Make sound
    output motor         // Vibrate
);
    always @(*)begin
        if(ring)begin//来电
            if(vibrate_mode)begin//振动模式,打开电机关闭铃声
                motor=1;
                ringer=0;
            end
            else begin//关闭振动模式,打开铃声关闭电机
                motor=0;
                ringer=1;
            end
        end
        else begin//不来电
            motor=0;
            ringer=0;
        end
    end
endmodule

我们当然可以如上代码先查看条件和输入,寻找得到什么样的输出,即“输入→输出”的逻辑。

设计电路时,我们还可以“倒着”思考问题,从输出开始,向前寻找满足条件的输入,当得到这种输出时候,对应可以有那些情况的输入条件,就是“输出→输入”的思考逻辑。

module top_module (
    input ring,
    input vibrate_mode,
    output ringer,       // Make sound
    output motor         // Vibrate
);
    assign ringer=(vibrate_mode==0&ring==1)?1:0;//当响铃声时候,输入要求是来电且关闭振动模式
    assign motor=(vibrate_mode==1&ring==1)?1:0;//当开电机时候,输入要求是来电且开启振动模式
endmodule

这里assign语句就是“输出→输入”的思考逻辑。

thermostat

module top_module (
    input too_cold,
    input too_hot,
    input mode,
    input fan_on,
    output heater,
    output aircon,
    output fan
); 
    assign heater=(too_cold==1&mode==1)?1:0;
    assign aircon=(too_hot==1&mode==0)?1:0;
    assign fan=fan_on|heater|aircon;//同上一题,三个assign是从输出结果寻找满足条件的输入
endmodule

3-bit population count

module top_module( 
    input [2:0] in,
    output [1:0] out );
    assign out=in[0]+in[1]+in[2];
endmodule

gates and vectors

module top_module( 
    input [3:0] in,
    output [2:0] out_both,
    output [3:1] out_any,
    output [3:0] out_different );
    assign out_both=in[2:0]&in[3:1];
    assign out_any=in[2:0]|in[3:1];
    assign out_different[2:0]=in[2:0]^in[3:1];
    assign out_different[3]=in[3]^in[0];
endmodule

even longer vectors

module top_module( 
    input [99:0] in,
    output [98:0] out_both,
    output [99:1] out_any,
    output [99:0] out_different );
    assign out_both=in[98:0]&in[99:1];
    assign out_any=in[98:0]|in[99:1];
    assign out_different[98:0]=in[98:0]^in[99:1];
    assign out_different[99]=in[99]^in[0];
endmodule

Multiplexers

2-to-1 multiplexers

module top_module( 
    input a, b, sel,
    output out ); 
    assign out=(sel)?b:a;
endmodule

2-to-1 bus multiplexers

module top_module( 
    input [99:0] a, b,
    input sel,
    output [99:0] out );
    assign out=(sel)?b:a;
endmodule

9-to-1 multiplexers

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)
            4'd0:out=a;
            4'd1:out=b; 
            4'd2:out=c; 
            4'd3:out=d; 
            4'd4:out=e; 
            4'd5:out=f; 
            4'd6:out=g; 
            4'd7:out=h; 
            4'd8:out=i;
            default:out=16'b1111111111111111;
       endcase 
    end
endmodule

256-to-1 multiplexers

module top_module( 
    input [255:0] in,
    input [7:0] sel,
    output out );
    assign out=in[sel];//数据流写法,SEL=0 选择 IN[0],SEL=1 选择 IN[1],类推
endmodule

256-to-1 4-bit multiplexers

题目要求:创建一个 4 位宽、256:1 的多路复用器。256 个 4 位输入全部封装到一个 1024 位输入向量中。SEL=0 应选择 [3:0] 中的位,SEL=1 选择 [7:4] 中的位,SEL=2 选择 [11:8] 中的位,依此类推。

根据题目描述,结合上一题的数据流写法,很自然会想到这样写:

module top_module( 
    input [1023:0] in,
    input [7:0] sel,
    output [3:0] out );
    assign out=in[4*sel+3:4*sel];
endmodule

从数据传输意思上是对的,但是verilog没有这样的语法,所以语法错误综合报错。

正确的写法可以这样写:

module top_module( 
    input [1023:0] in,
    input [7:0] sel,
    output [3:0] out );
    assign out=in[sel*4+:4];//+号代表向上取,:后面4代表向上取共4位
endmodule

也可以写成拼接的形式,拼接形式算是比较原始不高级但是很有效的办法:

module top_module( 
    input [1023:0] in,
    input [7:0] sel,
    output [3:0] out );
    assign out={in[sel*4+3], in[sel*4+2], in[sel*4+1], in[sel*4]};
endmodule

Arithmetic cirucits

half adder

module top_module( 
    input a, b,
    output cout, sum );
    assign{cout,sum}=a+b;
endmodule

full adder

module top_module( 
    input a, b, cin,
    output cout, sum );
    assign{cout,sum}=a+b+cin;
endmodule

3-bit binary adder

module top_module( 
    input [2:0] a, b,
    input cin,
    output [2:0] cout,
    output [2:0] sum );
    assign {cout[0],sum[0]}=a[0]+b[0]+cin;
    assign {cout[1],sum[1]}=a[1]+b[1]+cout[0];
    assign {cout[2],sum[2]}=a[2]+b[2]+cout[1];
endmodule

adder

module top_module (
    input [3:0] x,
    input [3:0] y, 
    output [4:0] sum);
    wire a,b,c;
    assign{a,sum[0]}=x[0]+y[0];
    assign{b,sum[1]}=x[1]+y[1]+a;
    assign{c,sum[2]}=x[2]+y[2]+b;
    assign{sum[4],sum[3]}=x[3]+y[3]+c;
endmodule

signed addition overflow

这里需要介绍一点判断有符号数溢出的知识,判断两个有符号数运算后是否溢出,有多种办法,其中一种办法是这样的:

设有符号数A与B相加,A的符号位是As,B的符号位是Bs,运算结果符号位是Ss,则

V=(As&Bs&(~Ss))+((~As)&(~Bs)&Ss),V=0无溢出,V=1有溢出。

无溢出的结果,As、Bs、Ss全为0或者全为1,两种情况分别代入上式V均为0

有溢出,As=0、Bs=0、Ss=1或As=1、Bs=1、Ss=0,了;两种情况分别代入上式V均为1

关于溢出判断更多了解可参考: 2.2.4_加减运算和溢出判断_哔哩哔哩_bilibili

回到本题,补码最高位[7]位是符号位,所以代码如下:

module top_module (
    input [7:0] a,
    input [7:0] b,
    output [7:0] s,
    output overflow
); //
    assign s=a+b;
    assign overflow=(a[7]&b[7]&~s[7])|(~a[7]&~b[7]&s[7]);
endmodule

100-bit binary adder

module top_module( 
    input [99:0] a, b,
    input cin,
    output cout,
    output [99:0] 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 c,d,e;
    bcd_fadd bcd_fadd_1(a[3:0],b[3:0],cin,c,sum[3:0]);
    bcd_fadd bcd_fadd_2(a[7:4],b[7:4],c,d,sum[7:4]);
    bcd_fadd bcd_fadd_3(a[11:8],b[11:8],d,e,sum[11:8]);
    bcd_fadd bcd_fadd_4(a[15:12],b[15:12],e,cout,sum[15:12]);
endmodule

Karnaugh Map to circuit

3-variable

module top_module(
    input a,
    input b,
    input c,
    output out  ); 
    assign out=a|c|b;
endmodule

4-variable

module top_module(
    input a,
    input b,
    input c,
    input d,
    output out  ); 
    assign out=(~a&~d)|(~b&~c)|(a&~b&d)|(b&c&d);
endmodule

4-variable

module top_module(
    input a,
    input b,
    input c,
    input d,
    output out  ); 
    assign out= a|(~b&c);
endmodule

4-variable

这种卡诺图,ab和cd是按照格雷码写的,里面的0和1全都不相邻,就是经典的各个元素异或,这是数电的知识。

module top_module(
    input a,
    input b,
    input c,
    input d,
    output out  ); 
    assign out=a^b^c^d;
endmodule

minimum SOP and POS

做这道题需要清楚SOP和POS,卡诺图化简时候,

SOP形式是找出所有当输出为1(最小项)的输入组合(最小项之和)

POS形式则是找出所有当输出为0(最大项)的输入组合(最大项之积)

具体可以参考:卡诺图化简及逻辑函数的规范范式:SOP与POS形式_sop和pos-CSDN博客

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|b)&(~b|~c|d);
endmodule

Karnaugh Map

module top_module (
    input [4:1] x, 
    output f );
    assign f=(~x[1]&x[3])|(x[2]&x[4]);
endmodule

Karnaugh Map

module top_module (
    input [4:1] x,
    output f
); 
    assign f=(~x[2]&~x[4])|(~x[1]&x[3])|(x[2]&x[3]&x[4]);
endmodule

K-Map implemented with a multiplexer

题目描述:对于下面的Karnaugh图,给出使用一个4对1多路复用器和所需数量的2对1多路复用器的电路实现,但使用尽可能少的多路复用器。不允许使用任何其他逻辑门,必须使用 a 和 b 作为多路复用器选择器输入,如下面的 4 对 1 多路复用器所示。您要实现标记为 top_module 的部分,以便整个电路(包括 4 对 1 多路复用器)实现 K 映射。

因为ab是多路选择器的选择端,所以我们可以从ab入手分析

ab=00输出mux_in[0],就是卡诺图第一列,输出什么取决于cd,由卡诺图知c是1时候输出为1,c是0时候输出同d;

ab=01输出mux_in[1],就是卡诺图第二列,输出为0;

ab=10输出mux_in[2],就是卡诺图第四列,输出什么取决于d,d是1时候输出是0,d是0时候输出是1;

ab=11输出mux_in[3],就是卡诺图第三列,输出什么取决于cd,c是1时候输出取决于d,c是0时候输出是0;

module top_module (
    input c,
    input d,
    output [3:0] mux_in
); 
    assign mux_in[0] = c?1:d;        
	assign mux_in[1] = 0;                
    assign mux_in[2] = d?0:1;          
	assign mux_in[3] = c?d:0;
endmodule

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值