当前位置:   article > 正文

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

verilog 38译码器


一、三八译码器原理

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

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

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

1.使用verilog代码如下:

  1. module decoder_3_8(a,b,c,out);
  2.     input a,b,c;
  3.     output [7:0] out;
  4.     reg [7:0] out;
  5.     always @(a,b,c) begin
  6.         case({a,b,c})
  7.         3'b000:out=8'b0000_0001;
  8.         3'b001:out=8'b0000_0010;
  9.         3'b010:out=8'b0000_0100;
  10.         3'b011:out=8'b0000_1000;
  11.         3'b100:out=8'b0001_0000;
  12.         3'b101:out=8'b0010_0000;
  13.         3'b110:out=8'b0100_0000;
  14.         3'b111:out=8'b1000_0000;
  15.         endcase
  16.     end
  17. 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电路如下:

  1. module adder_1bit(a,b,c,sum,cout);
  2. input a,b,c;
  3. output sum,cout;
  4. wire t1,t2,t3;
  5. xor x1(t1,a,b);
  6. and x2(t2,t1,c);
  7. and x3(t3,a,b);
  8. xor x4(sum,t1,c);
  9. or x5(cout,t2,t3);
  10. endmodule

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

  1. module shiyan1(
  2. //输入信号,ain表示被加数,bin表示加数,cin表示低位向高位的进位
  3. input ain,bin,cin,
  4. //输出信号,cout表示向高位的进位,sum表示本位的相加和
  5. output reg cout,sum
  6. );
  7. reg s1,s2,s3;
  8. always @(ain or bin or cin) begin
  9. sum=(ain^bin)^cin;//本位和输出表达式
  10. s1=ain&cin;
  11. s2=bin&cin;
  12. s3=ain&bin;
  13. cout=(s1|s2)|s3;//高位进位输出表达式
  14. end
  15. endmodule

 

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

 2.四位全加器

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

  1. module full_adder_4(A,B,C,sum,cout);
  2. input A,B,C;
  3. output cout,sum;
  4. wire t1,t2,t3,t4;
  5. and U1(t1,A,B);
  6. and U2(t2,A,C);
  7. and U3(t3,B,C);
  8. or U4(cout,t1,t2,t3);
  9. xor U5(t4,A,B);
  10. xor U6(sum,t4,C);
  11. endmodule

 verilog行为级描述如下:

  1. module adder_4bit(A,B,C,cout,sum);
  2. input A,B,C;
  3. output sum,cout;
  4. wire t1,t2,t3;
  5. assign sum=A^B^C;
  6. assign t1=A&B,
  7. t2=A&C,
  8. t3=B&C;
  9. assign cout=t1|t2|t3;
  10. endmodule

3.八位全加器 

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

  1. //1位全加器模块
  2. module adder_1bit(s, cout, a, b, cin);
  3. //输入输出端口定义
  4. output s, cout;
  5. input a, b, cin;
  6. //采用行为描述的方式实现1位全加器
  7. assign s = a ^ b ^ cin;
  8. assign cout = a & b | a & cin | b & cin;
  9. endmodule
  10. //8位加法器顶层模块
  11. module adder_8bit(s, cout, a, b, cin);
  12. //输入输出端口及变量定义
  13. output [7 : 0] s;
  14. output cout;
  15. input [7 : 0] a, b;
  16. input cin;
  17. wire [6 : 0] carry;
  18. //采用结构描述的方式实现一个8位加法器
  19. adder_1bit m0(s[0], carry[0], a[0], b[0], cin);
  20. adder_1bit m1(s[1], carry[1], a[1], b[1], carry[0]);
  21. adder_1bit m2(s[2], carry[2], a[2], b[2], carry[1]);
  22. adder_1bit m3(s[3], carry[3], a[3], b[3], carry[2]);
  23. adder_1bit m4(s[4], carry[4], a[4], b[4], carry[3]);
  24. adder_1bit m5(s[5], carry[5], a[5], b[5], carry[4]);
  25. adder_1bit m6(s[6], carry[6], a[6], b[6], carry[5]);
  26. adder_1bit m7(s[7], cout, a[7], b[7], carry[6]);
  27. endmodule

参考资料:

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


总结

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/563555
推荐阅读
相关标签
  

闽ICP备14008679号