一、设计任务
一个8位简易ALU的功能如下:
(1)能实现两个8位数的加、减操作,得到8位结果;
(2)能实现对一个8位输入数据的算术移位(符号扩展),移位范围为左移0-8位、右移0-8位。
用硬件描述语言设计该ALU并进行功能仿真,并自选一款FPGA进行逻辑综合与布局布线,得到消耗的硬件资源情况及时序结果。
- 电路原理及代码
(1)verilog版
通过实验任务我们可以看到ALU的操作在Verilog中都有对应的表达,不需要自己再专门去写门电路,而且这些都是常用的操作,vivado因该有固定的优化后的设计模板。所以只需要一个case选择语句来选择ALU具体进行的操作即可。我们的设计有三个输入信号分别为a,b,sel和一个输出out。sel选择执行的操作。00:a+b 01:a-b 10: a向左移b位 11:为a向右移b位
(2)VHDL版
这个版本的加减法的实现采用了自己设计的加法器和算数移位运算。加法减法的实现没有考虑外界的进位的情况。a,b为输入数据,c保存进位。a,b每一位相加的结果相当于进位c,a,b三者相异或。进位相当于c(i-1),a,b任意两个相与再或。算数移位通过将输入的指定位到输出的指定位位,再根据移位法则补0或1。(算数移位:左移空缺位补0,右移空缺位根据最高的符号位确定是补0还是补1)。
具体代码如下
(1)verilog
`timescale 1ns / 1ps
module alu( input [7:0] a,
input [7:0] b,
input [1:0] sel,
output reg [7:0] out
);
always@(a or b or sel) begin
case(sel)
3'b00 : out = a + b;
3'b01 : out = a - b;
3'b10 : out = a <<< b;
3'b11 : out = a >>> b;
default: out = 5'bx;
endcase
end
endmodule
- VHDL
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_UNSIGNED.ALL;
entity ALU_B is
Port ( A : in STD_LOGIC_VECTOR (7 downto 0);
B : in STD_LOGIC_VECTOR (7 downto 0);
m : in integer;
sel : in STD_LOGIC_VECTOR (0 to 1);
F : out STD_LOGIC_VECTOR (7 downto 0)
);
end ALU_B;
architecture Behavioral of ALU_B is
begin
process (A,B,m,sel)
variable c : std_logic_vector(7 downto 0);
variable d : std_logic_vector(7 downto 0);
variable i: integer ;
begin
c:="00000000";
d:="11111111";
if sel = "00" then --计算A+B
f(0)<= a(0)xor b(0);
c(0):= a(0)and b(0);
for i in 1 to 7 loop
f(i)<= a(i) xor b(i) xor c(i-1);
c(i):= (a(i)and b(i))or(a(i)and c(i-1))or(b(i)and c(i-1));
end loop;
elsif sel = "01" then --计算A-B 如果是A小于B,计算的是A-B的绝对值
f(0)<=a(0) xor b(0);
c(0):=not a(0) and b(0);
for i in 1 to 7 loop
f(i)<=a(i) xor b(i) xor c(i-1);
c(i):=(b(i) and c(i-1)) or ((b(i) xor c(i-1)) and (not a(i)));
end loop;
elsif sel="10" then--A算数左移m位
--f<=to_stdlogicvector( to_bitvector(A) SLA conv_integer(B)) ;--A算数左移B位
--直接调用的话用上面的
f(7 downto m)<=A(7-m downto 0);
f(m-1 downto 0)<=c(m-1 downto 0);
elsif sel="11" then--A算数右移m位
--f<=to_stdlogicvector( to_bitvector(A) SRA conv_integer(B)) ;--A算数右移B位
--直接调用的话用上面的
f(7-m downto 0)<=A(7 downto m);
if A(7)='0' then
f(7 downto 7-m+1)<=c(7 downto 7-m+1);
else
f(7 downto 7-m+1)<=d(7 downto 7-m+1);
end if;
end if;
end process;
end Behavioral;
- 电路仿真和结果
testbench如下:
(1)verilog
`timescale 1ns / 1ps
module alu_testbench;
reg [7:0]a;
reg [7:0]b;
reg [1:0]sel;
wire [7:0]out;
alu UUT (
.a(a),
.b(b),
.sel(sel),
.out(out));
initial
begin
a=8'd0;
b=8'd0;
sel=2'd0;
end
always
fork
#10 sel= 2'b00 ;
#20 sel= 2'b01 ;
#30 sel= 2'b10 ;
#40 sel= 2'b11 ;
#50 sel= 2'b00 ;
#60 sel= 2'b01 ;
#70 sel= 2'b10 ;
#80 sel= 2'b11 ;
#10 a=8'd8;
#50 a=8'd16;
#90 $finish;
#10 b=8'd1;
#50 b=8'd3;
#90 $finish;
join
endmodule
仿真加减法都比较明显,重点是观察算数移位。当进行算数左移时,和逻辑左移相同,右侧补零。当进行算数右移时,右侧要补和符号位相同的数。
实验的结果和预期吻合良好
VHDL版
library ieee;
use ieee.STD_LOGIC_UNSIGNED.all;
use ieee.std_logic_1164.all;
-- Add your library and packages declaration here ...
entity alu_b_tb is
end alu_b_tb;
architecture TB_ARCHITECTURE of alu_b_tb is
-- Component declaration of the tested unit
component alu_b
port(
A : in STD_LOGIC_VECTOR(7 downto 0);
B : in STD_LOGIC_VECTOR(7 downto 0);
signal m : integer;
sel : in STD_LOGIC_VECTOR(0 to 1);
F : out STD_LOGIC_VECTOR(7 downto 0) );
end component;
-- Stimulus signals - signals mapped to the input and inout ports of tested entity
signal A : STD_LOGIC_VECTOR(7 downto 0);
signal B : STD_LOGIC_VECTOR(7 downto 0);
signal m : integer;
signal sel : STD_LOGIC_VECTOR(0 to 1);
-- Observed signals - signals mapped to the output ports of tested entity
signal F : STD_LOGIC_VECTOR(7 downto 0);
-- Add your code here ...
begin
-- Unit Under Test port map
UUT : alu_b
port map (
A => A,
B => B,
sel => sel,
F => F,
m=>m
);
-- Add your stimulus here ...
A<="00001001", "00000011" after 50 ns, "00000110" after 100 ns, "00000001" after 150 ns, "10000000" after 200 ns;
B<="00000001", "00000010" after 50 ns, "00000010" after 100 ns, "00000001" after 150 ns, "10100000" after 200 ns;
m<=0,2 after 150ns,1 after 200ns;
sel <="00" ,"00" after 50 ns, "01" after 100 ns,"10" after 150 ns, "11" after 200 ns;
end TB_ARCHITECTURE;
configuration TESTBENCH_FOR_alu_b of alu_b_tb is
for TB_ARCHITECTURE
for UUT : alu_b
use entity work.alu_b(behavioral);
end for;
end for;
end TESTBENCH_FOR_alu_b;