set_global_assignment -name RESERVE_ASDO_AFTER_CONFIGURATION "AS INPUT TRI-STATED"
#set_global_assignment -name TOP_LEVEL_ENTITY calc
- set_global_assignment -name TOP_LEVEL_ENTITY parser
+ set_global_assignment -name TOP_LEVEL_ENTITY alu
set_global_assignment -name VHDL_FILE ../../src/gen_pkg.vhd
#set_global_assignment -name VHDL_FILE ../../src/calc.vhd
set_global_assignment -name VHDL_FILE ../../src/alu.vhd
- set_global_assignment -name VHDL_FILE ../../src/parser.vhd
+ #set_global_assignment -name VHDL_FILE ../../src/parser.vhd
set_location_assignment PIN_N3 -to sys_clk
set_location_assignment PIN_AF17 -to sys_res_n
op2 : in csigned;
op3 : out csigned;
do_calc : in std_logic;
- calc_done : out std_logic
- -- TODO: calc_error : out std_logic;
+ calc_done : out std_logic;
+ calc_error : out std_logic
);
end entity alu;
architecture beh of alu is
- type ALU_STATE is (SIDLE, SADD, SSUB, SMUL, SDIV, SDIV_CALC, SDIV_DONE, SDONE);
+ type ALU_STATE is (SIDLE, SADD, SSUB, SMUL, SDIV, SDIV_CALC, SDIV_DONE,
+ SDONE, SERROR);
signal state_int, state_next : ALU_STATE;
- signal done_intern, div_calc_done, div_go_calc : std_logic;
+ signal done_intern, error_intern, div_calc_done, div_go_calc : std_logic;
signal op3_int, op3_next : csigned := (others => '0');
signal calc_done_int, calc_done_next : std_logic;
+ signal calc_error_int, calc_error_next : std_logic;
-- signale fuer division
signal dividend_msb_int, dividend_msb_next, laengediv_int, laengediv_next : natural;
signal quo_int, quo_next, aktdiv_int, aktdiv_int_next, op1_int, op1_next, op2_int, op2_next : csigned;
begin
op3 <= op3_int;
calc_done <= calc_done_int;
+ calc_error <= calc_error_int;
-- sync
process(sys_clk, sys_res_n)
state_int <= SIDLE;
op3_int <= (others => '0');
calc_done_int <= '0';
+ calc_error_int <= '0';
--div
dividend_msb_int <= 0;
laengediv_int <= 0;
state_int <= state_next;
op3_int <= op3_next;
calc_done_int <= calc_done_next;
+ calc_error_int <= calc_error_next;
-- div
dividend_msb_int <= dividend_msb_next;
laengediv_int <= laengediv_next;
end process;
-- next state
- process(state_int, opcode, done_intern, do_calc, div_calc_done, div_go_calc)
+ process(state_int, opcode, done_intern, error_intern, do_calc,
+ div_calc_done, div_go_calc)
begin
-- set a default value for next state
state_next <= state_int;
if done_intern = '1' then
state_next <= SDONE;
end if;
+ if error_intern = '1' then
+ state_next <= SERROR;
+ end if;
when SDIV =>
if div_go_calc = '1' then
state_next <= SDIV_CALC;
end if;
+ if error_intern = '1' then
+ state_next <= SERROR;
+ end if;
when SDIV_CALC =>
if div_calc_done = '1' then
state_next <= SDIV_DONE;
end if;
- when SDONE =>
+ when SDONE | SERROR =>
if do_calc = '0' then
state_next <= SIDLE;
end if;
-- output
process(state_int, op1, op2, dividend_msb_int, laengediv_int, quo_int, aktdiv_int, sign_int, op1_int, op2_int, op3_int)
- variable multmp : signed(((2*CBITS)-1) downto 0);
+ variable multmp, multmp2 : signed(((2*CBITS)-1) downto 0);
+ variable mulsign : std_logic;
+ variable tmp : csigned;
-- vars fuer div
variable laengediv_var, dividend_msb_var : natural;
variable aktdiv_int_var, quo_var, op1_var, op2_var : csigned;
begin
calc_done_next <= '0';
+ calc_error_next <= '0';
div_calc_done <= '0';
div_go_calc <= '0';
done_intern <= '0';
+ error_intern <= '0';
-- default fuer div
dividend_msb_next <= 0;
laengediv_next <= 0;
when SIDLE =>
null;
when SADD =>
- op3_next <= op1 + op2;
- done_intern <= '1';
+ tmp := op1 + op2;
+ op3_next <= tmp;
+
+ -- over- bzw. underflow?
+ if (op1(CBITS-1) = op2(CBITS-1)) and (op1(CBITS-1) /= tmp(CBITS -1)) then
+ error_intern <= '1';
+ else
+ done_intern <= '1';
+ end if;
when SSUB =>
- op3_next <= op1 - op2;
- done_intern <= '1';
+ tmp := op1 - op2;
+ op3_next <= tmp;
+
+ -- over- bzw. underflow?
+ if (op1(CBITS-1) /= op2(CBITS-1)) and (op1(CBITS-1) /= tmp(CBITS -1)) then
+ error_intern <= '1';
+ else
+ done_intern <= '1';
+ end if;
when SMUL =>
+ mulsign := op1(CBITS-1) xor op2(CBITS-1);
multmp := op1 * op2;
- op3_next(CBITS-1) <= multmp((2*CBITS)-1);
op3_next((CBITS-2) downto 0) <= multmp((CBITS-2) downto 0);
- done_intern <= '1';
+ op3_next(CBITS-1) <= mulsign;
+
+ if mulsign = '1' then
+ multmp2 := not (multmp + 1);
+ else
+ multmp2 := multmp;
+ end if;
+ -- overflow?
+ if(multmp2((2*CBITS)-2 downto (CBITS-1)) > 0) then
+ error_intern <= '1';
+ else
+ done_intern <= '1';
+ end if;
+
when SDIV =>
-- division implementiert nach ~hwmod/doc/division.pdf
- if op2 = to_signed(0,CBITS) then
- -- TODO: err out signal
- done_intern <= '1';
+ if ((op1 = x"80000000" and op2 = to_signed(-1, CBITS)) or op2 = to_signed(0, CBITS)) then
+ error_intern <= '1';
else
-- sign check
op1_var := op1;
when SDIV_DONE =>
op3_next <= quo_int;
done_intern <= '1';
- when SDONE =>
+ when SDONE | SERROR =>
calc_done_next <= '1';
+ if (state_int = SERROR) then
+ calc_error_next <= '1';
+ end if;
op3_next <= op3_int;
end case;
end process;
alias rr "restart -f"
#signale hinzufuegen
-add wave sys_clk
-add wave sys_res_n
-add wave -radix decimal op1
-add wave opcode
-add wave -radix decimal op2
-add wave -radix decimal op3
-add wave do_calc
-add wave calc_done
+add wave inst/*
+
+delete wave /beh_alu_tb/inst/op1_int
+delete wave /beh_alu_tb/inst/op1
+delete wave /beh_alu_tb/inst/op1_next
+add wave -radix decimal inst/op1_int
+
+delete wave /beh_alu_tb/inst/op2_int
+delete wave /beh_alu_tb/inst/op1
+delete wave /beh_alu_tb/inst/op2_next
+add wave -radix decimal inst/op2_int
+
+delete wave /beh_alu_tb/inst/op3_int
+delete wave /beh_alu_tb/inst/op1
+delete wave /beh_alu_tb/inst/op3_next
+add wave -radix decimal inst/op3_int
+
#rauszoomen
wave zoomout 500.0
end entity beh_alu_tb;
architecture sim of beh_alu_tb is
- signal sys_clk, sys_res_n, do_calc, calc_done : std_logic;
+ signal sys_clk, sys_res_n, do_calc, calc_done, calc_error : std_logic;
signal opcode : alu_ops;
signal op1, op2, op3 : csigned;
signal stop : boolean := false;
op1 => op1,
op2 => op2,
op3 => op3,
- opcode => opcode
+ opcode => opcode,
+ calc_error => calc_error
);
process
o : alu_ops;
o2 : cinteger;
expected : cinteger;
+ errcase : boolean;
end record alu_testv;
-- ggf. groesse des arrays erhoehen
- type alu_testv_array is array (natural range 0 to 30) of alu_testv;
+ type alu_testv_array is array (natural range 0 to 44) of alu_testv;
variable testmatrix : alu_testv_array :=
- ( 0 => (-5, ALU_DIV, 3, -1),
- 1 => (7, ALU_ADD, 3, 10),
- 2 => (7, ALU_SUB, 1, 6),
- 3 => (7, ALU_DIV, 1, 7),
- 4 => (7, ALU_DIV, 3, 2),
- 5 => (7, ALU_ADD, 1, 8),
- 6 => (7, ALU_MUL, 3, 21),
- 7 => (-7, ALU_MUL, 3, -21),
- 8 => (268435456, ALU_MUL, -2, -536870912),
- 9 => (268435456, ALU_MUL, 2**5, 0), -- um fuenf nach links shiften
- 10 => (268435456 + 5, ALU_MUL, 2**5, 160), -- = 5 * (2^5)
- 11 => (100, ALU_DIV, 10, 10),
- 12 => (100, ALU_DIV, 51, 1),
- 13 => (100, ALU_DIV, 49, 2),
- 14 => (153156, ALU_DIV, 3543, 43),
- 15 => (-153156, ALU_DIV, 3543, -43),
- 16 => (153156, ALU_DIV, -3543, -43),
- 17 => (-153156, ALU_DIV, -3543, 43),
- others => (0, ALU_ADD, 0, 0)
+ ( 0 => (-5, ALU_DIV, 3, -1, false),
+ 1 => (7, ALU_ADD, 3, 10, false),
+ 2 => (7, ALU_SUB, 1, 6, false),
+ 3 => (7, ALU_DIV, 1, 7, false),
+ 4 => (7, ALU_DIV, 3, 2, false),
+ 5 => (7, ALU_ADD, 1, 8, false),
+ 6 => (7, ALU_MUL, 3, 21, false),
+ 7 => (-7, ALU_MUL, 3, -21, false),
+ 8 => (268435456, ALU_MUL, -2, -536870912, false),
+ 9 => (268435456, ALU_MUL, 2**5, 0, false), -- um fuenf nach links shiften
+ 10 => (268435456 + 5, ALU_MUL, 2**5, 160, false), -- = 5 * (2^5)
+ 11 => (100, ALU_DIV, 10, 10, false),
+ 12 => (100, ALU_DIV, 51, 1, false),
+ 13 => (100, ALU_DIV, 49, 2, false),
+ 14 => (153156, ALU_DIV, 3543, 43, false),
+ 15 => (-153156, ALU_DIV, 3543, -43, false),
+ 16 => (153156, ALU_DIV, -3543, -43, false),
+ 17 => (-153156, ALU_DIV, -3543, 43, false),
+ -- add: sign and under-/overflow check
+ 18 => (2147483647, ALU_ADD, -1, 2147483646, false),
+ 19 => (2147483647, ALU_ADD, 1, 0, true),
+ 20 => (-2147483645, ALU_ADD, -100, 0, true),
+ 21 => (7, ALU_ADD, 1, 8, false),
+ 22 => (7, ALU_ADD, -1, 6, false),
+ 23 => (-7, ALU_ADD, 1, -6, false),
+ 24 => (-7, ALU_ADD, -1, -8, false),
+ -- sub: sign and under-/overflow check
+ 25 => (-7, ALU_SUB, 1, -8, false),
+ 26 => (-7, ALU_SUB, -1, -6, false),
+ 27 => (7, ALU_SUB, 1, 6, false),
+ 28 => (7, ALU_SUB, -1, 8, false),
+ 29 => (-2147483645, ALU_SUB, 1000, 0, true),
+ 30 => (2147483645, ALU_SUB, -1000, 0, true),
+ 31 => (-1000, ALU_SUB, 2147483645, 0, true),
+ 32 => (1000, ALU_SUB, -2147483645, 0, true),
+ -- mul: sign and under-/overflow check
+ 33 => (3, ALU_MUL, 2, 6, false),
+ 34 => (3, ALU_MUL, -2, -6, false),
+ 35 => (-3, ALU_MUL, 2, -6, false),
+ 36 => (-3, ALU_MUL, -2, 6, false),
+ 37 => (90000, ALU_MUL, 100000, 0, true),
+ 38 => (90000, ALU_MUL, -100000, 0, true),
+ 39 => (-90000, ALU_MUL, 100000, 0, true),
+ 40 => (-90000, ALU_MUL, -100000, 0, true),
+ -- mul: overflow check und division durch null
+ 41 => (-2147483648, ALU_DIV, -1, 0, true),
+ 42 => (-2147483648, ALU_DIV, 0, 0, true),
+ others => (0, ALU_ADD, 0, 0, false)
);
variable checkall : boolean := true;
begin
wait on calc_done;
icwait(sys_clk, 1);
- assert op3 = to_signed(testmatrix(i).expected,CBITS)
- report "" & cinteger'image(testmatrix(i).o1) &
- " " & integer'image(to_integer(signed(opcode))) &
- " " & cinteger'image(testmatrix(i).o2) &
- "/= " & integer'image(to_integer(op3)) &
- " -- erwartet: " & cinteger'image(testmatrix(i).expected);
+ if testmatrix(i).errcase then
+ if (calc_error = '0') then
+ assert(false) report "sollte ein error sein";
+ assert op3 = to_signed(testmatrix(i).expected,CBITS)
+ report "" & cinteger'image(testmatrix(i).o1) &
+ " " & integer'image(to_integer(signed(opcode))) &
+ " " & cinteger'image(testmatrix(i).o2) &
+ "/= " & integer'image(to_integer(op3)) &
+ " -- erwartet: " & cinteger'image(testmatrix(i).expected);
+ checkall := false;
+ else
+ assert(false) report "testfall war ein error (passt)";
+ end if;
+ else
+ assert op3 = to_signed(testmatrix(i).expected,CBITS)
+ report "" & cinteger'image(testmatrix(i).o1) &
+ " " & integer'image(to_integer(signed(opcode))) &
+ " " & cinteger'image(testmatrix(i).o2) &
+ "/= " & integer'image(to_integer(op3)) &
+ " -- erwartet: " & cinteger'image(testmatrix(i).expected);
- if op3 /= to_signed(testmatrix(i).expected,CBITS) then
- checkall := false;
+ if op3 /= to_signed(testmatrix(i).expected,CBITS) then
+ checkall := false;
+ end if;
end if;
icwait(sys_clk, 2);
if checkall then
report "alle testfaelle der ALU waren erfolgreich!";
else
- report "nicht alle testfaelle der ALU waren erfolgreich!";
+ report "einige testfaelle schlugen fehl";
end if;
stop <= true;
wait;
constant CBITS : integer := 32;
subtype csigned is signed((CBITS-1) downto 0);
- --TODO: bei CBITS-1 gibts einen overflow :/
- subtype cinteger is integer range -(2**(CBITS-2)) to ((2**(CBITS-2))-1);
+ -- integer ist 32bit (31bit + sign)
+ subtype cinteger is integer;
subtype hspalte is std_logic_vector(6 downto 0);
subtype hzeile is std_logic_vector(4 downto 0);
-- out
process(state_int, p_read, p_write_int, z_int, rbyte_int, p_rget_int,
strich_int, aktop_int, opp_int, opcode_int, op1_int, op2_int, op3,
- do_calc_int)
+ do_calc_int, wtmp_int)
function hbyte2csigned (x : hbyte) return csigned is
variable y : csigned;
begin
op2 : in std_logic_vector(31 downto 0);
op3 : out std_logic_vector(31 downto 0);
do_calc : in std_logic;
- calc_done : out std_logic
+ calc_done : out std_logic;
+ calc_error : out std_logic
);
end component alu;
- signal sys_clk, sys_res_n, do_calc, calc_done : std_logic;
+ signal sys_clk, sys_res_n, do_calc, calc_done, calc_error : std_logic;
signal opcode : alu_ops;
- signal op1, op2, op3 : std_logic_vector(31 downto 0);
+ signal op1, op2, op3 : std_logic_vector((CBITS-1) downto 0);
signal stop : boolean := false;
begin
inst : alu
op1 => op1,
op2 => op2,
op3 => op3,
- opcode => opcode
+ opcode => opcode,
+ calc_error => calc_error
);
process
o : alu_ops;
o2 : cinteger;
expected : cinteger;
+ errcase : boolean;
end record alu_testv;
-- ggf. groesse des arrays erhoehen
- type alu_testv_array is array (natural range 0 to 20) of alu_testv;
+ type alu_testv_array is array (natural range 0 to 44) of alu_testv;
variable testmatrix : alu_testv_array :=
- ( 0 => (-5, ALU_DIV, 3, -1),
- 1 => (7, ALU_ADD, 3, 10),
- 2 => (7, ALU_SUB, 1, 6),
- 3 => (7, ALU_DIV, 1, 7),
- 4 => (7, ALU_DIV, 3, 2),
- 5 => (7, ALU_ADD, 1, 8),
- 6 => (7, ALU_MUL, 3, 21),
- 7 => (-7, ALU_MUL, 3, -21),
- 8 => (268435456, ALU_MUL, -2, -536870912),
- 9 => (268435456, ALU_MUL, 2**5, 0), -- um fuenf nach links shiften
- 10 => (268435456 + 5, ALU_MUL, 2**5, 160), -- = 5 * (2^5)
- 11 => (100, ALU_DIV, 10, 10),
- 12 => (100, ALU_DIV, 51, 1),
- 13 => (100, ALU_DIV, 49, 2),
- 14 => (153156, ALU_DIV, 3543, 43),
- 15 => (-153156, ALU_DIV, 3543, -43),
- 16 => (153156, ALU_DIV, -3543, -43),
- 17 => (-153156, ALU_DIV, -3543, 43),
- others => (0, ALU_ADD, 0, 0)
+ ( 0 => (-5, ALU_DIV, 3, -1, false),
+ 1 => (7, ALU_ADD, 3, 10, false),
+ 2 => (7, ALU_SUB, 1, 6, false),
+ 3 => (7, ALU_DIV, 1, 7, false),
+ 4 => (7, ALU_DIV, 3, 2, false),
+ 5 => (7, ALU_ADD, 1, 8, false),
+ 6 => (7, ALU_MUL, 3, 21, false),
+ 7 => (-7, ALU_MUL, 3, -21, false),
+ 8 => (268435456, ALU_MUL, -2, -536870912, false),
+ 9 => (268435456, ALU_MUL, 2**5, 0, false), -- um fuenf nach links shiften
+ 10 => (268435456 + 5, ALU_MUL, 2**5, 160, false), -- = 5 * (2^5)
+ 11 => (100, ALU_DIV, 10, 10, false),
+ 12 => (100, ALU_DIV, 51, 1, false),
+ 13 => (100, ALU_DIV, 49, 2, false),
+ 14 => (153156, ALU_DIV, 3543, 43, false),
+ 15 => (-153156, ALU_DIV, 3543, -43, false),
+ 16 => (153156, ALU_DIV, -3543, -43, false),
+ 17 => (-153156, ALU_DIV, -3543, 43, false),
+ -- add: sign and under-/overflow check
+ 18 => (2147483647, ALU_ADD, -1, 2147483646, false),
+ 19 => (2147483647, ALU_ADD, 1, 0, true),
+ 20 => (-2147483645, ALU_ADD, -100, 0, true),
+ 21 => (7, ALU_ADD, 1, 8, false),
+ 22 => (7, ALU_ADD, -1, 6, false),
+ 23 => (-7, ALU_ADD, 1, -6, false),
+ 24 => (-7, ALU_ADD, -1, -8, false),
+ -- sub: sign and under-/overflow check
+ 25 => (-7, ALU_SUB, 1, -8, false),
+ 26 => (-7, ALU_SUB, -1, -6, false),
+ 27 => (7, ALU_SUB, 1, 6, false),
+ 28 => (7, ALU_SUB, -1, 8, false),
+ 29 => (-2147483645, ALU_SUB, 1000, 0, true),
+ 30 => (2147483645, ALU_SUB, -1000, 0, true),
+ 31 => (-1000, ALU_SUB, 2147483645, 0, true),
+ 32 => (1000, ALU_SUB, -2147483645, 0, true),
+ -- mul: sign and under-/overflow check
+ 33 => (3, ALU_MUL, 2, 6, false),
+ 34 => (3, ALU_MUL, -2, -6, false),
+ 35 => (-3, ALU_MUL, 2, -6, false),
+ 36 => (-3, ALU_MUL, -2, 6, false),
+ 37 => (90000, ALU_MUL, 100000, 0, true),
+ 38 => (90000, ALU_MUL, -100000, 0, true),
+ 39 => (-90000, ALU_MUL, 100000, 0, true),
+ 40 => (-90000, ALU_MUL, -100000, 0, true),
+ -- mul: overflow check und division durch null
+ 41 => (-2147483648, ALU_DIV, -1, 0, true),
+ 42 => (-2147483648, ALU_DIV, 0, 0, true),
+ others => (0, ALU_ADD, 0, 0, false)
);
variable checkall : boolean := true;
begin
wait on calc_done;
icwait(sys_clk, 1);
- assert op3 = std_logic_vector(to_signed(testmatrix(i).expected,CBITS))
- report "" & cinteger'image(testmatrix(i).o1) &
- " " & integer'image(to_integer(signed(opcode))) &
- " " & cinteger'image(testmatrix(i).o2) &
- "/= " & integer'image(to_integer(signed(op3))) &
- " -- erwartet: " & cinteger'image(testmatrix(i).expected);
- if op3 /= std_logic_vector(to_signed(testmatrix(i).expected,CBITS)) then
- checkall := false;
+ if testmatrix(i).errcase then
+ if (calc_error = '0') then
+ assert(false) report "sollte ein error sein";
+ assert op3 = std_logic_vector(to_signed(testmatrix(i).expected,CBITS))
+ report "" & cinteger'image(testmatrix(i).o1) &
+ " " & integer'image(to_integer(signed(opcode))) &
+ " " & cinteger'image(testmatrix(i).o2) &
+ "/= " & integer'image(to_integer(signed(op3))) &
+ " -- erwartet: " & cinteger'image(testmatrix(i).expected);
+ checkall := false;
+ else
+ assert(false) report "testfall war ein error (passt)";
+ end if;
+ else
+ assert op3 = std_logic_vector(to_signed(testmatrix(i).expected,CBITS))
+ report "" & cinteger'image(testmatrix(i).o1) &
+ " " & integer'image(to_integer(signed(opcode))) &
+ " " & cinteger'image(testmatrix(i).o2) &
+ "/= " & integer'image(to_integer(signed(op3))) &
+ " -- erwartet: " & cinteger'image(testmatrix(i).expected);
+
+ if op3 /= std_logic_vector(to_signed(testmatrix(i).expected,CBITS)) then
+ checkall := false;
+ end if;
end if;
icwait(sys_clk, 2);
if checkall then
report "alle testfaelle der ALU waren erfolgreich!";
else
- report "nicht alle testfaelle der ALU waren erfolgreich!";
+ report "einige testfaelle schlugen fehl";
end if;
stop <= true;
wait;