【HDLBits】Circuits_Combinational Logic_Arithmetic Circuits
I. Hadd (Halfadder)
1.代码编写
//==============================方法1==============================
module top_module(
input a, b,
output cout, sum );
assign {cout,sum}=a+b;
endmodule
//==============================方法2==============================
module top_module(
input a, b,
output cout, sum );
assign cout=a&b;
assign sum=a^b;
endmodule
2.提交结果
3.题目分析
两种方法,行为级与门级。另外{cout,sum}不要乱序,其次,可以发现“{ }”用在“=”右侧左侧都可以。
II. Fadd (Fulladder)
1.代码编写
//=================================方法一=================================
module top_module(
input a, b, cin,
output cout, sum );
assign {cout,sum}=a+b+cin;
endmodule
//=================================方法二=================================
module top_module(
input a, b, cin,
output cout, sum );
assign cout=a&b+cin&(a^b);
assign sum=a^b^cin;
endmodule
//门级电路表达
2.提交结果
success
3.题目分析
两种方式,行为级和门级。
III. Adder3 (3-bit binary adder)
1.代码编写
//=======================方法1========================
module top_module(
input [2:0] a, b,
input cin,
output [2:0] cout,
output [2:0] sum );
fadder instance1(.a(a[0]),.b(b[0]),.cin(cin),.cout(cout[0]),.sum(sum[0]));
fadder instance2(.a(a[1]),.b(b[1]),.cin(cout[0]),.cout(cout[1]),.sum(sum[1]));
fadder instance3(.a(a[2]),.b(b[2]),.cin(cout[1]),.cout(cout[2]),.sum(sum[2]));
endmodule
module fadder(
input a,b,cin,
output cout,sum);
assign {cout,sum}=a+b+cin;
endmodule
//========================这样写复习一下task(发现task A后面忘加;,已改正)========================
module top_module(
input [2:0] a, b,
input cin,
output [2:0] cout,
output [2:0] sum );
task A;
input a,b,cin;
output sum,cout;
{cout,sum}=a+b+cin;
endtask
always@(*) begin
A(a[0],b[0],cin,sum[0],cout[0]);
A(a[1],b[1],cout[0],sum[1],cout[1]);
A(a[2],b[2],cout[1],sum[2],cout[2]);
end
endmodule
2.提交结果
success
3.题目分析
有关verilog输入输出的介绍:
https://blog.csdn.net/qq_34670678/article/details/106432116
几点总结:
- input,output,inout未声明时的默认类型为wire型。
- test文件输入端口只能是net型(wire),输出端口可以是wire/reg。因为输入端不用储存数据,只是反映输入信号的变化,是连线关系,而输出端可能要存储数据。
- testbench文件的输入可以是wire/reg,而输出只能是net型(wire)。因为testbench用于产生虚拟信号时,需要输出至test文件的输入端,testbench的输出相当于test的输入,用net。而testbench文件用于存储test的输出结果时,testbench的输入相当于test的输出,可以用reg/net型。
IV. Exams/m2014 q4j (Adder)
1.代码编写
//=============================method 1=============================
module top_module (
input [3:0] x,
input [3:0] y,
output [4:0] sum);
wire c2,c3,c4;
FA instance1(.x(x[0]),.y(y[0]),.cin(),.cout(c2),.sum(sum[0]));
FA instance2(.x(x[1]),.y(y[1]),.cin(c2),.cout(c3),.sum(sum[1]));
FA instance3(.x(x[2]),.y(y[2]),.cin(c3),.cout(c4),.sum(sum[2]));
FA instance4(.x(x[3]),.y(y[3]),.cin(c4),.cout(sum[4]),.sum(sum[3]));
endmodule
module FA(
input x,y,cin,
output cout,sum);
assign {cout,sum}=x+y+cin; //verilog默认未声明的输入输出端口为net型,这里用assign,否则报错:‘near text: "{"; expecting "endmodule". ’
endmodule
//=============================review task=============================
module top_module (
input [3:0] x,
input [3:0] y,
output [4:0] sum);
wire c2,c3,c4;
task FA;
input x,y,cin;
output cout,sum;
{cout,sum}=x+y+cin;
endtask
always@(*) begin
FA(x[0],y[0],1'd0,c2,sum[0]);
FA(x[1],y[1],c2,c3,sum[1]);
FA(x[2],y[2],c3,c4,sum[2]);
FA(x[3],y[3],c4,sum[4],sum[3]);
end
endmodule
//实际上在最低位的全加器上多了一个输入 cin=1'd0。
2.提交结果
success
3.题目分析
用两种方法分别实现了一下,发现用module的方法时,新的module里赋值记得用assign,因为未声明的输入输出端口默认为net。
V. Exams/ece241 2014 q1c (signed addition overflow)
1.代码编写
- 正确代码:
- 方法1:
通过进位位来判断overflow,存在真值表:
可见overflow=c[7]^c[6]。
//=====================method 1=====================
module top_module (
input [7:0] a,
input [7:0] b,
output [7:0] s,
output overflow
); //
wire [7:0] c;
integer i;
assign {c[0],s[0]}=a[0]+b[0];
always@(*) begin
for(i=1;i<8;i++)begin
{c[i],s[i]}=a[i]+b[i]+c[i-1];
end
end
assign overflow=c[7]^c[6];
endmodule
- 方法2:
通过对比a[7],b[7],s[7]来解决:
overflow指的是:A signed overflow occurs when adding two positive numbers produces a negative result, or adding two negative numbers produces a positive result.
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
- 一种错误写法(运用行为级代码):
module top_module (
input [7:0] a,
input [7:0] b,
output [7:0] s,
output overflow
); //
wire [7:0] c;
// assign s = ...
// assign overflow = ...
assign {c,s}=a+b;
assign overflow=c[7]^c[6];
endmodule
这样写存在mismatch:
仿真发现c只能反映最高位是否进位了:
//======================test======================
module top_module (
input [7:0] a,
input [7:0] b,
output [7:0] s,
output [7:0] c,
output overflow
); //
// assign s = ...
// assign overflow = ...
assign {c,s}=a+b;
assign overflow=c[7]^c[6];
endmodule
//======================testbench======================
`timescale 1ns/1ps
module testbench();
reg [7:0] a,b;
wire [7:0] s,overflow,c;
initial begin
a=8'h0;
b=8'h0;
#5 b=8'h70;
#5 a=8'h70;
#5 b=8'h90;
#5
a=8'h90;
b=8'h70;
#5 b=8'h90;
#5 b=8'hff;
#5 $stop;
end
top_module instance1(
.a(a),
.b(b),
.s(s),
.c(c),
.overflow(overflow));
endmodule
波形:
证实c进反映了最高位的进位。
2.提交结果
success
3.题目分析
在代码编写部分。
VI. Adder100 (100-bit binary adder)
1.代码编写
module top_module(
input [99:0] a, b,
input cin,
output cout,
output [99:0] sum );
assign {cout,sum}=a+b+cin;
endmodule
2.提交结果
success
3.题目分析
Create a 100-bit binary adder. The adder adds two 100-bit numbers and a carry-in to produce a 100-bit sum and carry out.
Expected solution length: Around 1 line.
Hint:There are too many full adders to instantiate, but behavioural code works well here.
有关行为级、RTL级、门级:
行为级:行为级是RTL级的上一层。最符合人类思维的描述方式。主要用于快速验证算法的正确性,不关注电路的具体结构,不一定可以综合成实际电路结构。注重算法。以直接赋值的形式进行,只关注结果。常采用大量运算,延迟等无法综合的语句。其目的不在于综合,而在于算法。
RTL级:使用寄存器这一级别的描述方式来描述电路的数据流方式。RTL在很大程度上是对流水线原理图的描述。接近实际电路结构的描述,可以精确描述电路的原理、执行顺序等。其目的在于可综合。
门级:使用逻辑门这一级别来描述。RTL 中的寄存器和组合逻辑,其物理实现还是对应到具体门电路。但目前寄存器,组合逻辑等的电路结构基本稳定。一般EDA工具可以把RTL描述自动编译为门级描述。所以一般不直接使用门级编程。
————————————————
版权声明:本文为CSDN博主「YUI不可爱」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012694677/article/details/89601675
VII. Bcdadd4 (4-digit BCD Adder)
1.代码编写
module top_module (
input [15:0] a, b,
input cin,
output cout,
output [15:0] sum );
wire c2,c3,c4;
bcd_fadd instance1(.a(a[3:0]),.b(b[3:0]),.cin(cin),.cout(c2),.sum(sum[3:0]));
bcd_fadd instance2(.a(a[7:4]),.b(b[7:4]),.cin(c2),.cout(c3),.sum(sum[7:4]));
bcd_fadd instance3(.a(a[11:8]),.b(b[11:8]),.cin(c3),.cout(c4),.sum(sum[11:8]));
bcd_fadd instance4(.a(a[15:12]),.b(b[15:12]),.cin(c4),.cout(cout),.sum(sum[15:12]));
endmodule
2.提交结果
success
3.题目分析
You are provided with a BCD (binary-coded decimal) one-digit adder named bcd_fadd that adds two BCD digits and carry-in, and produces a sum and carry-out.
module bcd_fadd (
input [3:0] a,
input [3:0] b,
input cin,
output cout,
output [3:0] sum );
Instantiate 4 copies of bcd_fadd to create a 4-digit BCD ripple-carry adder. Your adder should add two 4-digit BCD numbers (packed into 16-bit vectors) and a carry-in to produce a 4-digit sum and carry out.
Hint:
- The BCD representation for the 5-digit decimal number 12345 is 20’h12345. This is not the same as 14’d12345 (which is 14’h3039).
- The circuit is structured just like a binary ripple-carry adder, except the adders are base-10 rather than base-2.
- BCD码是用4位二进制数来表示1位十进制数中的0~9这10个数码,是一种二进制的数字编码形式,用二进制编码的十进制代码。4位二进制相当于1位16进制,所以10进制12345表示成BCD码为(5*4)=20’h12345,而非简单的14’d12345。