1、运行附件1的Verilog代码,编译运行。
运行成功后,点击“Create Symbol Files for current File”创建一个ALU181.bsf模块。
2.创建一个新的Block Diagram/Schematic File文件。
将步骤1创建的ALU181.bsf添加到当前文件中,并将输入输出端口连接。创建的原理图图如图5.1ALU生成的原理图文件。
图5.1 ALU生成的原理图文件
3.将步骤2的原理图进行编译运行。并创建仿真文件。
编译运行通过后,创建University Program vwf文件,首先测试M=1进行逻辑运算的结果分析。此时我设定的A和B均为1111_1111,S为0000_1111循环,CN为0(M=1时CN不影响F),仿真图如5.2 ALU进行逻辑运算的仿真图。
图5.2 ALU进行逻辑运算的仿真图
接下来测试M=0且CN=0进行算数运算的结果分析。此时我设定的A和B均为0000_1111,S为0000_1111循环,仿真图如5.3 ALU进行算数运算的仿真图1。
图5.3 ALU进行算数运算的仿真图1
最后测试M=0且CN=1进行算数运算的结果分析。此时我设定的A和B均为0000_1111,S为0000_1111循环,仿真图如5.4ALU进行算数运算的仿真图。
图5.4 ALU进行算数运算的仿真图2
4.验证ALU运算器的算术运算和逻辑运算功能后,并记录实验数据。
以下实验记录表都是根据5.2-5.4仿真图得出的。
ALU实验数据表1是对M=0时的结果记录,此时A=B=1111_1111。ALU实验数据表2是对M=0且CN=0时的结果记录,此时A=B=0000_1111。ALU实验数据表3是对M=0且CN=1时的结果记录,此时A=B=0000_1111。验证可知与实际结果一致。
ALU实验数据表1
选择方式 | M=1逻辑运算 | F[0..7] | FZ | CO |
S3S2S1S0 | 逻辑运算 | 运算结果 | 运算结果零标志位 | 运算后的进位标志 |
0000 | F=/A | 0000_0000 | 1 | 无 |
0001 | F=/(A+B) | 0000_0000 | 1 | 无 |
0010 | F=(/A)B | 0000_0000 | 1 | 无 |
0011 | F=0 | 0000_0000 | 1 | 无 |
0100 | F=/(AB) | 0000_0000 | 1 | 无 |
0101 | F=/B | 0000_0000 | 1 | 无 |
0110 | F=A⊕B | 0000_0000 | 1 | 无 |
0111 | F=A/B | 0000_0000 | 1 | 无 |
1000 | F=/A+B | 1111_1111 | 0 | 无 |
1001 | F=/(A⊕B) | 1111_1111 | 0 | 无 |
1010 | F=B | 1111_1111 | 0 | 无 |
1011 | F=AB | 1111_1111 | 0 | 无 |
1100 | F=1 | 0000_0001 | 0 | 无 |
1101 | F=A+/B | 1111_1111 | 0 | 无 |
1110 | F=A+B | 1111_1111 | 0 | 无 |
1111 | F=A | 1111_1111 | 0 | 无 |
ALU实验数据表2
选择方式 | M=0算术运算 | F[0..7] | FZ | CO |
S3S2S1S0 | CN为最低进位位 | 运算结果 | 运算结果零标志位 | 运算后的进位标志 |
0000 | F=A加CN | 0000_1111 | 0 | 0 |
0001 | F=(A+B) 加CN | 0000_1111 | 0 | 0 |
0010 | F=A+/B加CN | 1111_1111 | 0 | 0 |
0011 | F=-1(补码形式) | 0000_0000 | 1 | 0 |
0100 | F=A加A(/B)加CN | 0000_1111 | 0 | 0 |
0101 | F=(A+B)加A/B加CN | 0000_1111 | 0 | 0 |
0110 | F=A减B减CN | 0000_0000 | 1 | 0 |
0111 | F=A/B减CN | 0000_0000 | 1 | 0 |
1000 | F=A加AB加CN | 0001_1110 | 0 | 0 |
1001 | F=A加B加CN | 0001_1110 | 0 | 0 |
1010 | F=A+/B加AB加CN | 0000_1110 | 0 | 1 |
1011 | F=AB减CN | 0000_1111 | 0 | 0 |
1100 | F=A加A加CN | 0001_1110 | 0 | 0 |
1101 | F=A+B加A加CN | 0001_1110 | 0 | 0 |
1110 | F=A+/B加A加CN | 0000_1110 | 0 | 1 |
1111 | F=A-CN | 0000_1111 | 0 | 0 |
ALU实验数据表3
选择方式 | M=0算术运算 | F[0..7] | FZ | CO |
S3S2S1S0 | CN为最低进位位 | 运算结果 | 运算结果零标志位 | 运算后的进位标志 |
0000 | F=A加CN | 0001_0000 | 0 | 0 |
0001 | F=(A+B) 加CN | 0001_0000 | 0 | 0 |
0010 | F=A+/B加CN | 0000_0000 | 1 | 1 |
0011 | F=-1(补码形式) | 1111_1111 | 0 | 1 |
0100 | F=A加A(/B)加CN | 0001_0000 | 0 | 0 |
0101 | F=(A+B)加A/B加CN | 0001_0000 | 0 | 0 |
0110 | F=A减B减CN | 1111_1111 | 0 | 1 |
0111 | F=A/B减CN | 1111_1111 | 0 | 1 |
1000 | F=A加AB加CN | 0001_1111 | 0 | 0 |
1001 | F=A加B加CN | 0001_1111 | 0 | 0 |
1010 | F=A+/B加AB加CN | 0000_1111 | 0 | 1 |
1011 | F=AB减CN | 0000_1110 | 0 | 0 |
1100 | F=A加A加CN | 0001_1111 | 0 | 0 |
1101 | F=A+B加A加CN | 0001_1111 | 0 | 0 |
1110 | F=A+/B加A加CN | 0000_1111 | 0 | 1 |
1111 | F=A-CN | 0000_1110 | 0 | 0 |
5.改进后的ALU电路如下。
改进后的ALU电路有4个寄存器,充当数据缓存寄存器,LMP_LATCH数据宽度为8位,data[7:0]是数据输入端: q[7:0]是数据输出端: gate是数据锁存控制端。当gate为高电平时,数据进入锁存器;而当gate为低电平时,锁存器保持己输入的数据。同时增加了两个四选一的结构。四选一外连74273b数据寄存器,提供要参与运算的数据。
改进后的原理图见图5.5 改进后的ALU原理图。
图5.5 改进后的ALU原理图
6.对改进后的ALU电路进行仿真。
仿真图见图5.5 改进后的ALU原理图。假定D:0000_1111;CLK=1;LD_0,LD_1,LD_2,LD_3恒为1,IR为数据选择器在00和11之间循环,CLK1恒为1,CN=1,M=0(进行算数运算),S=0001(进行F=(A+B)加CN运算)。
图5.6 改进后的ALU仿真图
根据图5.6仿真图得出如下仿真结果
D | CLK | LD_R0,R1,R2,R3 | IR1[1..0] | IR2[3..2] | CLK1 | CN | M | S[3..0] | F[7..0] | FZ | CO |
0000_1111 | 1 | 1 | 00 | 00 | 1 | 1 | 0 | 0001 | 0000_0001 | 0 | 0 |
01 | 01 | 0001_0000 | 0 | 0 | |||||||
10 | 10 | 0001_0000 | 0 | 0 | |||||||
11 | 11 | 0001_0000 | 0 | 0 |
六、实验讨论与总结
1、带进位运算与不带进位运算有何区别?
解答:带进位运算会将进位结果存储在进位标志位里面,带进位运算加法或者减法时,可以提示你是否有溢出或者借位。
2、如何实现带进位运算,将上一次运算的进位位用于下一次的运算当中,并实现多个8位数据的(如两个24位数据的加法)运算?在控制电路上应作怎样的改动?给出24位加法详细的仿真波形图。
解答:设计过程如图6.1 24位的ALU所示。我设计的是串行的结构。
图6.1 24位的ALU
简单的仿真图如下,实现的是F=A加B+CN的算数运算。
图6.2 24位的ALU仿真图
3、改进设计,实现运算结果对标志位CO、FZ的锁定。
解答:经过老师指导明白了“锁定”的含义,就是将数据保持一定的时间不变,实现的方式用D触发器就可以实现,不过触发器得受到时钟信号CLK的控制。如图6.3 D触发器实现的CO,FZ的锁定。
图6.3 D触发器实现的CO,FZ的锁定
简单的仿真图如下。
图6.4 D触发器实现的CO,FZ的锁定的仿真图
4、通过本实验,你对基于FPGA构造算术逻辑运算器ALU有何认识,有什么心得体会?
体会:FPGA构造ALU运算模块的时候只需要考虑逻辑实现不需要考虑对应的电路,靠对应的Verilog代码就可以生成相应的功能模块。ALU不仅可以实现算数运算也可以实现逻辑运算。做实验遇到的最大的困难是存在读不懂实验的要求,辛亏老师帮忙,其次就是对quartus操作的不熟悉,再就是有些器件没见过不太会用。
附件一:程序源代码
1、程序一清单如下:
module ALU181a (S, A, B, F, M, CN, CO, FZ);
input[3:0] S;
input[7:0] A,B;
input M, CN;
output[7:0] F;
output CO, FZ;
//wire[7:0] F; wire CO;
wire[8:0] A9, B9;
reg FZ;
reg[8:0] F9;
reg [7:0] F;
reg CO;
assign A9 = {1'b0, A} ;
assign B9 = {1'b0, B} ;
always @(M or CN or A9 or B9 or S)
begin
case (S)
//yes
4'b0000 : if (M==0) F9<=A9+CN ;
else F9<=~A9 ;
//yes
4'b0001 : if (M==0) F9 <= (A9 |B9) + CN ;
else F9<=~(A9 | B9) ;
//yes
4'b0010 : if (M==0) F9 <= (A9 |((~B9)&9'b011111111))+ CN;
else F9<=(~A9) & B9 ;
//yes
4'b0011 : if (M==0) F9 <= 9'b000000000-CN;
else F9<=9'b000000000;
//yes
4'b0100:if(M==0)F9<=A9+(A9& ((~B9)&9'b011111111))+CN;
else F9<=~(A9 & B9) ;
//yes
4'b0101:if(M==0)F9<=(A9|B9)+(A9&((~B9)&9'b011111111))+CN;
else F9<= ~B9 ;
//yes
4'b0110 : if (M==0) F9 <= A9 - B9 - CN ;
else F9<= A9 ^ B9 ;
//yes
4'b0111 : if (M==0) F9 <= (A9 & (((~B9)&9'b011111111))) - CN ;
else F9<= A9 & (~B9) ;
// yes-no
4'b1000 : if (M==0) F9 <= A9 + (A9 & B9)+CN ;
else F9<= (~A9) | B9 ;
// yes
4'b1001 : if (M==0) F9 <= A9 + B9 + CN ;
else F9<= ~(A9 ^ B9) ;
// no-yes
4'b1010:if(M==0) F9<=(A9|(((~B9)&9'b011111111)))+(A9&B9)+CN;
else F9<= B9 ;
//yes
4'b1011 : if (M==0) F9 <= (A9 & B9) - CN ;
else F9<=A9 & B9 ;
//
4'b1100 : if (M==0) F9 <= A9 + A9 + CN ;
else F9<=9'b000000001 ;
4'b1101 : if (M==0) F9 <= (A9 | B9)+A9+CN;
else F9<= A9 | (~B9) ;
4'b1110 : if (M==0) F9 <= (A9 | (((~B9)&9'b011111111)))+A9+CN;
else F9<= A9 | B9 ;
4'b1111 : if (M==0) F9 <= A9 - CN ;
else F9<= A9 ;
default : F9 <= 9'b000000000 ;
endcase
//if (A9 == B9) FZ <= 1'b0 ; else FZ <= 1'b1 ;
F <= F9[7:0] ;
if(F==8'b00000000) FZ <= 1'b1 ; else FZ <= 1'b0 ;
if(M==0) CO <= F9[8];
end
endmodule