使用verilog编写三八译码器及四位全加器


一、三八译码器原理

三八译码器的输入信号有三个,相当于有八个二进制编码可以输入,每个输入都对应着一个输出信号,其真值表如下图所示:

根据真值表使用logsim设计三八译码器的仿真电路图,该图如下:

二、使用verilog编写三八译码器

1.使用verilog代码如下:

module decoder_3_8(a,b,c,out);
    input a,b,c;
    output [7:0] out;
    reg [7:0] out;
    always @(a,b,c) begin
        case({a,b,c})
        3'b000:out=8'b0000_0001;
        3'b001:out=8'b0000_0010;
        3'b010:out=8'b0000_0100;
        3'b011:out=8'b0000_1000;
        3'b100:out=8'b0001_0000;
        3'b101:out=8'b0010_0000;
        3'b110:out=8'b0100_0000;
        3'b111:out=8'b1000_0000;
        endcase
    end
endmodule

 在Quartus里面创建工程,编写代码后生成的RTL电路如下图所示:

仿真结果如下:

       相较于原始设计电路来说Quartus生成的电路更为简洁,它将中间逻辑门实现的电路使用了一个模块封装起来,直观上来说只能看见输入与输出的形式,对其实现过程不甚了解,它的仿真测试结果与真值表一致。

2.verilog的数据类型

Verilog 最常用的 2 种数据类型就是线型(wire)与寄存器型(reg),其余类型可以理解为这两种数据类型的扩展或辅助。

(1)wire类型

      wire相当于一根导线,无数据储存功能,无驱动能力,通常用于以assign关键字指定的组合逻辑信号,模块的输入输出类型通常默认的是此类型。

(2)reg类型

always模块内被赋值的信号,必须定义为reg型,默认初始值是x。

reg表示一定要有触发,输出才会反映输入,可以用于组合逻辑或者时序逻辑,能存储数据,有驱动能力,在always @模块表达式左侧被赋值。

寄存器(reg)用来表示存储单元,它会保持数据原有的值,直到被改写。

因此不能将上面代码中的reg类型改为wire类型,否则会出现语法错误。

三、使用verilog编写全加器

1.一位全加器

首先在logsim中设计仿真电路图,如下所示:

根据仿真电路图就可以用verilog门级描述生成电路,代码和生成的RTL电路如下:

module adder_1bit(a,b,c,sum,cout);
	input a,b,c;
	output sum,cout;
	wire t1,t2,t3;
	xor x1(t1,a,b);
	and x2(t2,t1,c);
	and x3(t3,a,b);
	xor x4(sum,t1,c);
	or x5(cout,t2,t3);
endmodule

使用过门级电路过后,我们使用verilog的行为级语言进行描述,代码和RTL电路如下所示:

module shiyan1(
	//输入信号,ain表示被加数,bin表示加数,cin表示低位向高位的进位
	input ain,bin,cin,
	//输出信号,cout表示向高位的进位,sum表示本位的相加和
	output reg cout,sum

);
reg s1,s2,s3;
always @(ain or bin or cin) begin
	sum=(ain^bin)^cin;//本位和输出表达式
	s1=ain&cin;
	s2=bin&cin;
	s3=ain&bin;
	cout=(s1|s2)|s3;//高位进位输出表达式
end
endmodule

 

相较于门级电路描述方法而言 ,行为级描述更为简洁,但对于逻辑的要求性更高

 2.四位全加器

verilog使用门级电路,代码和电路图如下:

module full_adder_4(A,B,C,sum,cout);
	input A,B,C;
	output cout,sum;
	wire t1,t2,t3,t4;
	and U1(t1,A,B);
	and U2(t2,A,C);
	and U3(t3,B,C);
	or U4(cout,t1,t2,t3);
	xor U5(t4,A,B);
	xor U6(sum,t4,C);
endmodule

 verilog行为级描述如下:

module adder_4bit(A,B,C,cout,sum);
   input A,B,C;
	output sum,cout;
	wire t1,t2,t3;
	assign sum=A^B^C;
	assign t1=A&B,
			 t2=A&C,
			 t3=B&C;
	assign cout=t1|t2|t3;
endmodule

3.八位全加器 

      八位全加器是在一位全加器的基础上实现的,根据先前的一位全加器的原理将输入的八位信号依次相加。

//1位全加器模块
module adder_1bit(s, cout, a, b, cin);
	//输入输出端口定义
	output s, cout;
	input a, b, cin;
	
	//采用行为描述的方式实现1位全加器
	assign s = a ^ b ^ cin;
	assign cout = a & b | a & cin | b & cin;
endmodule

//8位加法器顶层模块
module adder_8bit(s, cout, a, b, cin);
	//输入输出端口及变量定义
	output [7 : 0] s;
	output cout;
	input [7 : 0] a, b;
	input cin;
	wire [6 : 0] carry;
	
	//采用结构描述的方式实现一个8位加法器
	adder_1bit m0(s[0], carry[0], a[0], b[0], cin);
	adder_1bit m1(s[1], carry[1], a[1], b[1], carry[0]);
	adder_1bit m2(s[2], carry[2], a[2], b[2], carry[1]);
	adder_1bit m3(s[3], carry[3], a[3], b[3], carry[2]);
	adder_1bit m4(s[4], carry[4], a[4], b[4], carry[3]);
	adder_1bit m5(s[5], carry[5], a[5], b[5], carry[4]);
	adder_1bit m6(s[6], carry[6], a[6], b[6], carry[5]);
	adder_1bit m7(s[7], cout, a[7], b[7], carry[6]);
endmodule


参考资料:

小梅哥——38译码器-CSDN博客


总结

       使用verilog编写代码可以用门级电路描述,也可以用行为描述。前者需要先画出电路图然后再写代码,过程比较繁琐且后期修改不易;后者需要弄清楚输入输出量的逻辑关系,然后再用赋值语句写对于编写者的逻辑要求较高,不过描述更加简洁,后期修改也更加容易。

  • 29
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值