第6章 基于EDA的组合电路设计综合及验证69综合性实例.docx
《第6章 基于EDA的组合电路设计综合及验证69综合性实例.docx》由会员分享,可在线阅读,更多相关《第6章 基于EDA的组合电路设计综合及验证69综合性实例.docx(21页珍藏版)》请在冰豆网上搜索。
第6章基于EDA的组合电路设计综合及验证69综合性实例
6.9组合逻辑电路的综合性实例
6.9.1实例一:
补码生成电路
1.设计说明
在通过VerilogHDL编程时,一个变量被赋值后,该变量保存的就是该值的补码,这种处理是仿真环境自动进行的。
如执行语句“i=-12;”,则8位的i变量中就会保存了-12的补码“11110100”,而不是保存原码“10001100”,这也是为什么在6.7.2节中要把带符号的数进行相应处理后才能计算的原因。
但在实际电路设计中,输入数据一般为原码形式(要求使用者直接输入补码是不大现实的),而大多IP核均要求采用补码进行数据通信。
因此,补码的转换需要逻辑电路设计者自行加入。
本例以8位二进制数(最高位为符号位)为例,希望帮助读者真正理解补码的含义及其使用场合,并理解编程工具及综合工具对负数的处理。
2.使用Verilog进行描述
moduleCom_2C(DataIn,DataOut);
input[7:
0]DataIn;//原码数据输入端
output[7:
0]DataOut;//补码数据输出端
reg[7:
0]DataOut,S;//S用于符号位的转换
always@(DataIn)
begin
S=8'b10000000;
if(DataIn[7])//判断首位是否为1,即是否负数
DataOut=-DataIn+S;//“-”操作对包括符号位在内的所有位取反再加1
else
DataOut=DataIn;//首位为0时表示正数,补码与原码相同
end
endmodule
程序说明:
(1)首先应注意的是,8位输入数据“DataIn”,是原码数据的输入。
(2)“-DataIn”操作可“把DataIn的8位数据包括符号位在内的所有位取反再加1”,该操作比较难以理解:
在执行“-DataIn”操作时,仿真器会把DataIn中的数据当成补码来处理,如DataIn中存放的是“11110100”,那么仿真器会认为该数是-12的补码,因此“-DataIn”操作会得到值12,即“00001100”,就是“11110100”所有位取反再加1的结果。
(3)“-DataIn”得到的是包括符号位在内所有位取反再加1的结果,因此再加上S(8'b10000000)就可把最高位(符号位)从0变为1,最终得到补码结果。
3.综合结果
4.测试平台设计
`timescale1ns/10ps
moduletestbench;
reg[7:
0]dataIn;
wire[7:
0]dataOut;
Com_2CCom_2C_1(.DataOut(dataOut),.DataIn(dataIn));
initial
begin
dataIn=8'b00011001;#20;
dataIn=8'b10110011;#20;
dataIn=8'b11110100;#20;
dataIn=8'b01110000;#20;
dataIn=8'b10011100;#20;
dataIn=8'b10000011;#20;
end
endmodule
5.功能验证
6.9.2实例二:
有符号数的比较电路设计
1.设计说明
在本例中,通过LiberoIDE中内嵌的比较器(Comparator)IP核,构造8位的有符号数据比较器。
需要注意的是,当直接利用LiberoIDE工具提供的比较器IP核进行设计与仿真时,工具自动将输入的信号“理解”为补码形式(或者说工具要求用户输入的数据为补码),所以读者在设计时应当理清输入信号是否已经转换成为补码,如果是,直接利用工具提供的相应IP核即可,如果不是,则需要进行相应的转换。
特别地,如果比较器模块是用户自行编程实现的,就要注意有符号数的比较与无符号数的比较有差别!
2.SmartDesign设计与连线
在SmartDesign中,进行以下操作:
(1)用IP核Comparator创建一个8位的有符号比较器(比较“>=”)。
(2)调入6.9.1节中的“Com_2C”模块,生成两个8位补码转换模块。
(3)进行连线操作。
(4)生成设计。
连接结果如图所示。
3.测试方法1
可以用以下的测试平台(并不是最佳)进行测试,仿真也会正常运行并给出结果。
`timescale1ns/10ps
moduletb_cmp;
reg[7:
0]ina,inb;
wireAGEB;
sign_cmpsign_cmp_1(.DataA(ina),.DataB(inb),.AGEB(AGEB));
//sign_cmp为画布设计名称
initial
begin
ina=0;
repeat(20)
#20ina=$random;
end
initial
begin
inb=0;
repeat(10)
#40inb=$random;
end
initial
#400$finish;
endmodule
但该测试平台的设计可能会引起误会,因为通过随机函数生成的数据是以补码形式存放的,而在此又当作原码数据进行处理。
例如ina产生了随机数-12(十进制),则存放到ina中的数据为11110100(-12的补码),而设计中会当作-116(-116的原码是11110100)来进行对比。
如果读者理解正确、思路清晰,倒也能达到测试目的。
4.测试方法2
可以用以下的测试平台,直接指定输入的原码数据,不容易产生误会。
`timescale1ns/10ps
moduletb_cmp;
reg[7:
0]ina,inb;
wireAGEB;
sign_cmpsign_cmp_1(.DataA(ina),.DataB(inb),.AGEB(AGEB));
initial
begin
ina=8'b00011001;#20;//原码数据输入
ina=8'b10110011;#20;
ina=8'b11110100;#20;
ina=8'b01110000;#20;
ina=8'b10011100;#20;
ina=8'b10000011;#20;
end
initial
begin
inb=0;#10;
inb=8'b11011001;#20;//原码数据输入
inb=8'b10000011;#20;
inb=8'b00110100;#20;
inb=8'b01111110;#20;
inb=8'b01011100;#20;
inb=8'b10000011;#20;
end
endmodule
功能仿真结果如图所示。
在查看仿真结果时,需清楚ina和inb是原码而不是补码数据,故不能设置显示为别的数制格式(仿真软件会当做补码处理)。
5.综合结果
6.9.3实例三:
有符号数的加法电路设计
1.设计说明
2.3.5节中讨论了有符号二进制数加法器的多种实现方法,在此则采用“饱和法”来实现。
第二章中的图2-45:
对图2-45稍作修改,可得下图。
虚线框选部分为一个4位串行进位加法器,而这部分其实可以用超前进位加法器替代。
不管用串行进位还是超前进位加法器,只需该加法器输出C3和C2即可。
在此通过SmartDesign软件,采用6.6.5节中设计的4位超前进位加法器模块(Add_prop_gen模块),按图进行连接,实现有符号4位二进制数的加法电路。
2.SmartDesign设计与连线
在SmartDesign中,进行以下操作:
(1)添加6.6.5节中的Add_prop_gen模块到设计中,将Shiftedcarry[2:
0]这3个端口标记为不使用(MarkUnused)。
(2)添加XOR2(异或)和INV(反向)宏单元到设计中。
(3)添加基本块“Multiplexor”(选择器),设置位宽为1,输入端口2个,并实例化4个选择器到设计中。
(4)进行连线操作。
(5)保存画布(命名为“adder4_of”),生成设计。
连线结果如图所示。
3.测试方法1
moduletestbench1;
reg[3:
0]ina,inb;
regcin;
wires3,s2,s1,s0,cout;
adder4_oftestadder(.A(ina),.B(inb),.C_in(cin),
.S3(s3),.S2(s2),.S1(s1),.S0(s0),.C_out(cout));
initial
begin
ina=0;
repeat(20)
#20ina=$random;
end
initial
begin
inb=0;
repeat(10)
#40inb=$random;
end
initial
begincin=0;#200cin=1;end
endmodule
仿真结果如图所示。
4.测试方法2(改进)
测试方法1的仿真结果看起来并不直观,可将测试平台修改为:
`timescale1ns/10ps
moduletestbench2;
reg[3:
0]ina,inb;
regcin;
wires3,s2,s1,s0,cout;
wire[3:
0]sum;
assignsum={s3,s2,s1,s0};//将4位输出合并为一个变量,方便显示
adder4_oftestadder(.A(ina),.B(inb),.C_in(cin),
.S3(s3),.S2(s2),.S1(s1),.S0(s0),.C_out(cout));
initial
begin
ina=0;
repeat(20)
#20ina=$random;
end
initial
begin
inb=0;
repeat(10)
#40inb=$random;
end
initial
begincin=0;#200cin=1;end
endmodule
在仿真波形窗口中进行以下操作:
(1)将cout、s3、s2、s1、s0从显示结果中去掉,只留下ina、inb、cin、sum变量的
显示。
(2)将ina、inb、sum变量设置为有符号十进制显示。
(3)在“sim”小窗口中,选择“testbench2”模块下的“testadder”实例,在“Objects”小窗口中选择“XOR2_0_Y”(该项为溢出标记),将其添加到波形显示中。
(4)清空结果并重新运行(选择“Restart”后选择“Run-All”),得到运行结果。
从波形中可看出,当运算结果超出[-8,+7]范围后,溢出标记“XOR2_0_Y”显示为1,而结果只保留-8或+7(饱和处理结果)。
5.综合结果
6.9.4实例四:
八位二进制数转换为十进制数的电路设计
1.设计方法1(课本里的)
moduleBIN_to_BCD(Data,Units,Tens,Hundreds);
input[7:
0]Data;//二进制输入数据
output[3:
0]Units,Tens,Hundreds;
reg[3:
0]units_r,tens_r,hundreds_r;//BCD数据输出寄存器
reg[7:
0]dat_r;
reg[11:
0]temp;//临时寄存器
integeri;
assignUnits=units_r;
assignTens=tens_r;
assignHundreds=hundreds_r;
always@(Data)
begin
dat_r=Data;
temp=0;
for(i=0;i<7;i=i+1)//循环7次而不是8次,因为第8次不需要修正
begin
temp={temp[10:
0],dat_r[7]};//左移一位
if(temp[3:
0]>4'd4)//大于4,加三
temp[3:
0]=temp[3:
0]+4'd3;
if(temp[7:
4]>4'd4)//大于4,加三
temp[7:
4]=temp[7:
4]+4'd3;
if(temp[11:
8]>4'd4)//大于4,加三
temp[11:
8]=temp[11:
8]+4'd3;
dat_r=dat_r<<1;//最高变为原来dat_r的第六位
{hundreds_r,tens_r,units_r}={temp[10:
0],Data[0]};
//最后一次(第8次)不用修正
end
end
endmodule
测试平台设计如下:
`timescale1ns/1ns
moduletestbench;
reg[7:
0]data;
wire[3:
0]units,tens,hundreds;
wire[11:
0]bcd;
BIN_to_BCDtb(.Data(data),.Units(units),.Tens(tens),.Hundreds(hundreds));
assignbcd=hundreds*100+tens*10+units;//处理为十进制数,更好地显示效果
initial
begin
data=8'h00;
#50data=8'h37;//2位十六进制数,即8位二进制数输入
#50data=8'hfe;
#50data=8'h78;
end
endmodule
仿真结果如下。
在波形窗口中,设置data为十六进制显示,设置bcd为无符号十进制显示。
2.设计方法2
方法1是自己编写代码描述转换的具体过程,其实可以直接用常规的行为风格描述设计:
moduleBIN_to_BCD_2(Data,Units,Tens,Hundreds);
input[7:
0]Data;
output[3:
0]Units;
output[3:
0]Tens;
output[3:
0]Hundreds;
reg[3:
0]Units,Tens,Hundreds;
reg[7:
0]dat_r;
always@(Data)
begin
dat_r=Data;
Hundreds=dat_r/100;
Tens=(dat_r-Hundreds*100)/10;
Units=dat_r%10;
end
endmodule
方法2的测试平台、综合结果和仿真结果同方法1。
6.9.5实例五:
编码器扩展电路设计
1.设计要求
模拟的实际运行效果:
当按下0~9的按键后,(7段)数码显示器显示相应数字。
当按下大于9的按键后,数码显示器不显示数字。
若同时按下几个按键,优先级别的顺序是9到0。
设计仿真要求:
有16个输入(位),每一位代表一个数字被按下(有信号输入)。
输出为8位的向量,输出显示译码结果。
如Seg[7:
0]从高位到低位表示“g、f、e、d、c、b、a”。
2.设计方法1
通过现有芯片实现的设计思路:
(1)将16位输入信号进行编码(由2个74HC148及相关器件构建16-4线编码器)。
(2)将编码结果跟9进行比较(74HC85)。
(3)符合条件的进行译码显示(74HC4511)。
以下利用LiberoSmartDesign图形化设计工具,采用图文混合设计方法,综合编码器、比较器、显示译码器及门电路进行设计。
按照如图所示的电路组装16-4编码器,该编码器原理同图2-12,但按照6.2.4的74HC148模块的电平特性进行定义。
注意该设计输入以低电平为有效,而输出A3、A2、A1、A0以高电平为有效(因为后续的模块以高电平为有效信号)。
设计过程如下:
(1)导入设计文件。
新建工程“extend_coder”,导入前面已经设计好的VerilogHDL模块文件,包括编码器(74HC148.v)、比较器(74HC85.v)、显示译码器(74HC4511.v)等模块文件。
(2) SmartDesign设计与连线。
在SmartDesign中进行以下操作:
①建立名为“extend_coder”的设计文件,并将其设为根文件。
②例化2个encoder8_3_1(HC148)模块、1个HC85模块、1个HC4511模块至画布中。
③从宏单元(ActelMacros)中例化3个二输入与门到画布中,将3个与门的输出Y都作反向(Invert)处理。
④进行16-4线编码器的扩展:
按照图6-41,分别将HC148_1(高位)及HC148_0(低位)的输入信号连至顶层;将HC148_1的GS输出端、HC148_0的EO和GS输出端标记为不使用;将HC148_1及HC148_0的Dataout[2:
0]分别连至三个与门的输入端;另外将HC148_1的输出EO连至HC148_0的EI输入端。
⑤设置HC85_0模块:
将16-4线编码器的对应输出接入HC85_0模块,设置B3、B1、IAEB端口接入高电平(TieHigh);设置B2、B0、IAGB、IASB接入低电平(TieLow);QAGB、QAEB设置为不使用。
⑥设置HC4511_0模块:
将16-4线编码器的对应输出接入HC4511_0模块;将HC85_0的QASB输出接入HC4511_0模块的BI_N端口;设置LT_N接入高电平、LE端口接入低电平;将Seg[7:
0]连接到顶层(即LED数码管输出驱动信号)。
⑦进行规则检查并生成设计。
连接结果如图所示。
设计说明:
①注意,HC148以低电平为1,而HC85和HC4511以高电平为1。
② HC85的接线表示判断输入数据是否比10小(输出QASB)。
③ HC85的QASB连接HC4511的BI_N端口,表示输入数据大于10的话,就清空输出结果。
(3)编写测试平台。
测试平台的设计如下:
`timescale1ns/1ns
moduletestbench;
reg[7:
0]datain,datain_0;
regei;
reg[15:
0]in,invec;
wire[7:
0]seg;
extend_codertestcoder(.DataIn(datain),.DataIn_0(datain_0),.EI(ei),.Seg(seg));
initial
begin
i=0;
in=16'b0000000000000001;
repeat(17)
begin
invec=~in;//148芯片中,输入数据作了反向处理
{datain,datain_0}=invec;
#20;
in=in<<1;
end
end
endmodule
(4)功能仿真。
仿真结果如图所示。
datain为高位(15~8)数据,datain_0为低位(7~0)数据。
仿真开始,当datain为11111111,datain_0为11111110时,即输入invec=111111*********0,表示第0位有信号输入(注意148是反向处理的),因此输出结果为seg=3f(即显示0,查看4511设计文件)。
查看完整波形信号:
发现在最后输入数据变为1111111111111111(16位),即表示什么输入都没有的时候,输出显示又会变回3f(即显示0),那是因为该电路结构只判断了大于9后清除显示,而没有处理当没有输入时的显示内容。
不按键时显示0,在实际要求中也是可以接受的。
如果不符合要求,则可以把目前的比较条件从“A<'b1010”改为“(A<'b1010)&(A=0)”,相应需增加一个比较器和与门,布线也需进行修改。
具体操作请读者自行进行。
(5)综合
3.设计方法2
设计方法1是通过HC148进行连接的,由于HC148芯片对输入输出信号进行了反向处理,因此加大了理解的难度。
如果使用没有进行反向处理的8-3编码器,也可以对设计进行修改。
如已有编码器代码如下:
//encoder8_3.v
moduleencoder8_3_1(DataIn,EO,Dataout,EI,GS);
input[7:
0]DataIn;
inputEI;
outputEO,GS;
output[2:
0]Dataout;
reg[2:
0]Dataout;
regEO,GS;
integerI;
always@(DataInorEI)
begin:
local
if(EI)
begin
Dataout=0;EO=1;GS=1;
end
elseif(DataIn==0)
begin
Dataout=0;EO=0;GS=1;
end
else
begin
for(I=0;I<8;I=I+1)
begin
if(DataIn[I])
begin
Dataout=I;EO=1;GS=0;
end
end
end
end
endmodule
该代码与HC148的结构与思路相同,只是(输入/输出信号的)高低电平代表含义不同,Datain和Dataout中高电平表示1,EI、EO、GS的含义和规定同HC148芯片。
由于该码器以高电平为1,因此不能使用设计方法1中的“与非”门,而改为“或”门。
电路结构改造为如图所示的设计。
测试平台也只是与设计方法1的稍有不同:
`timescale1ns/1ns
moduletestbench_extend_coder_2;
reg[7:
0]datain,datain_0;
regei;
reg[15:
0]invec;
wire[7:
0]seg;
extend_coder_2tb(.DataIn(datain),.DataIn_0(datain_0),.EI(ei),.Seg(seg));
//设计名称为extend_coder_2
initial
begin
ei=0;
invec=16'b000000000000001;
repeat(17)
begin
{datain,datain_0}=invec;
#20invec=invec<<1;
end
end
endmodule
4.设计方法3
设计方法1和2是通过现有模块组装成新的设计,因此设计思路和连接方法与通过相应实际芯片实现物理上的连接一样。
如果要在FPGA上实现,其实可以直接写出设计代码。
modulecoder0_