实例题目:
书接上文,在这部分围绕经典的加法器展开。
一、简单门电路的实现:
加法器
例 3.1 现有两个输入 a、b,输出 sum、c,sum 表示和,c 表示进位,完成代码编写与仿真并在 SparkRoad 上实现。
解:
半加器称之为“半”,是因为它是没有进位的输入加法器电路,只能实现一位二进制数的加法电路。
Verilog 代码实现:
module banjiaqi( a,b,sum,c );
input a,b;
output sum,c;
wire a,b;
wire sum,c;
assign sum=a^b;
assign c=a*b;
endmodule
引脚设置如下:
set_pin_assignment { a } { LOCATION = T4; }
set_pin_assignment { b } { LOCATION = R15; }
set_pin_assignment { c } { LOCATION = M3; }
set_pin_assignment { sum } { LOCATION = M4; }
实物验证如下:
设置 SW0、SW 15 为输入 a、b,输出 c 为 LED0,sum 为 LED 1。
![[1688036366633.png]]
输入 1、1,输出 c=1,sum=0。
例 3.2 现有三个输入 a、b、c 0,输出 sum、c 1,sum 表示和,c 1 表示进位,完成代码编写与仿真并在 SparkRoad 上实现。
解:
Verilog 代码实现:
module quanjiaqi( a,b,c0,sum,c1);
input a,b,c0;
output sum,c1;
wire a,b,c0;
wire sum,c1;
assign sum=a^b^c0;
assign c1=a*b|(c0*(a^b));
endmodule
引脚设置如下;
set_pin_assignment { a } { LOCATION = T4; }
set_pin_assignment { b } { LOCATION = T15; }
set_pin_assignment { c0 } { LOCATION = R15; }
set_pin_assignment { c1 } { LOCATION = M3; }
set_pin_assignment { sum } { LOCATION = M4; }
实物验证如下:
设置 SW0、SW 14、SW 15 为输入 a、b、c 0,输出 c 1为 LED0,sum 为 LED 1。
![[1688039184871.png]]
输入 a=1、b=1、c 0=0,输出 c 1=1,sum=0。
![[1688039369417.png]]
输入 a=1、b=1、c 0=1,输出 c 1=1,sum=1。
上述实现的是最基础的半加器和全加器,我们来做一些更有意思的。
上述的实现方式都是数据流也即卡诺图实现,但如果要实现更多位的全加器,当然这也是在日常生活中基本在使用的一种功能,难道还要这样去一一化简卡诺图来实现吗?可以想象,这将会是一份很繁琐的工作,而且无法快速实现随时改变位数的功能,那这时不妨用描述级语言去尝试实现。
例 3.3 实现两个五位数字的加法器,sum 表示和,c 表示进位,完成代码编写与仿真并在 SparkRoad 上实现。
解:
module duowei_jiafaqi( x,y,sum,c );
input [k-1:0]x,y;
output [k-1:0]sum;
output c;
wire [k-1:0]x,y;
wire [k-1:0]sum;
wire c;
parameter k=5;
assign {c,sum}=x+y; //这一点我有点疑问,有些时候写+运行不成功,要写|,有些时候又反过来,比如说这一题,为什么...第二天运行,又编译成功了,离谱
endmodule
引脚设置如下:
set_pin_assignment { c } { LOCATION = M3; }
set_pin_assignment { sum[0] } { LOCATION = P4; }
set_pin_assignment { sum[1] } { LOCATION = M5; }
set_pin_assignment { sum[2] } { LOCATION = N4; }
set_pin_assignment { sum[3] } { LOCATION = N3; }
set_pin_assignment { sum[4] } { LOCATION = M4; }
set_pin_assignment { x[0] } { LOCATION = M6; }
set_pin_assignment { x[1] } { LOCATION = T6; }
set_pin_assignment { x[2] } { LOCATION = T5; }
set_pin_assignment { x[3] } { LOCATION = R5; }
set_pin_assignment { x[4] } { LOCATION = T4; }
set_pin_assignment { y[0] } { LOCATION = R15; }
set_pin_assignment { y[1] } { LOCATION = T15; }
set_pin_assignment { y[2] } { LOCATION = R14; }
set_pin_assignment { y[3] } { LOCATION = T14; }
set_pin_assignment { y[4] } { LOCATION = N9; }
实物验证如下:
设置 SW0-4 为 x,SW 11-15 为 y,LED 0 为 c,LED 1-5 为 sum。
![[1688044619133.png]]
X、y 分别为 10001 和 10011,输出为 100100。
例 3.4 实现两个五位数字的加减法器,sum 表示和,c 表示进位,sub 控制实现加法或者减法,设定 sub 为 0 实现加法,sub 为 1 实现减法,完成代码编写与仿真并在 SparkRoad 上实现。
解:
此题是可以使用 if-else 或者 case 语句来实现,但是用 Verilog 之后会简便许多,这也引出一个问题:
在门电路中很复杂的设计,例如使用 74 系列设计,这是最贴切现实电路的,但是在 Verilog 实现相同的事情,却很简单,比如一个乘法器,在门电路中很复杂,但是在 Verilog 中就是一个乘号,那么从这个乘号到现实很复杂的门电路是不是就是 eda 在做的事情?
(但是这个题出自 hdlbits 上的 add——sub,但是因为那个题目是一个有着十六位的,所以调用起来很有必要,我们仍然可以试着编写一下)
module jiajian( x,y,sub,sum,c );
input sub;
input [k-1:0]x,y;
output [k-1:0]sum;
output c;
wire sub;
wire [k-1:0]x,y;
reg [k-1:0]sum;
reg c;
parameter k=3;
always@(*)
begin
if(sub)
begin
{c,sum}=x-y;
end
else
begin
{c,sum}=x+y;
end
end
endmodule
引脚设置如下:
set_pin_assignment { c } { LOCATION = M3; }
set_pin_assignment { sub } { LOCATION = T4; }
set_pin_assignment { sum[0] } { LOCATION = N4; }
set_pin_assignment { sum[1] } { LOCATION = N3; }
set_pin_assignment { sum[2] } { LOCATION = M4; }
set_pin_assignment { x[0] } { LOCATION = T6; }
set_pin_assignment { x[1] } { LOCATION = T5; }
set_pin_assignment { x[2] } { LOCATION = R5; }
set_pin_assignment { y[0] } { LOCATION = R15; }
set_pin_assignment { y[1] } { LOCATION = T15; }
set_pin_assignment { y[2] } { LOCATION = R14; }
但是这个并没有考虑到小数减大数的处理方案,所以还要再改进。