From e4d17ff9b56af5b05d5b610bac24127f697c8419 Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Wed, 12 May 2010 01:04:27 +0200 Subject: [PATCH] alu: rest wird auch uebernommen, geht aber nur fuer positive paare. TB fuer postlayout wurde nicht angepasst --- spec/speck.tex | 1 + src/alu.vhd | 67 ++++++++++++++++-------- src/beh_alu_tb.do | 17 +++++- src/beh_alu_tb.vhd | 128 ++++++++++++++++++++++++++------------------- src/gen_pkg.vhd | 9 ++-- 5 files changed, 140 insertions(+), 82 deletions(-) diff --git a/spec/speck.tex b/spec/speck.tex index 7fb8b2d..96cbd6b 100644 --- a/spec/speck.tex +++ b/spec/speck.tex @@ -618,6 +618,7 @@ jeweils im Modul Parser und History vertauscht. \item TODO: \emph{p\_rw} und \emph{p\_spalte} unnoetig (wenn man es in history richtig behandelt??) \item aussagekr\"aftigere Fehlermeldungen. +\item ALU: signal \emph{opM} fuer restberechnung \end{itemize} \end{document} diff --git a/src/alu.vhd b/src/alu.vhd index a1b7a41..014fc76 100644 --- a/src/alu.vhd +++ b/src/alu.vhd @@ -12,6 +12,7 @@ entity alu is op1 : in csigned; op2 : in csigned; op3 : out csigned; + opM : out csigned; do_calc : in std_logic; calc_done : out std_logic; calc_error : out std_logic @@ -22,16 +23,20 @@ architecture beh of alu is 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, error_intern, div_calc_done, div_go_calc : std_logic; - signal op3_int, op3_next : csigned; + signal done_intern, error_intern : std_logic; + signal div_calc_done_int : std_logic; + signal div_calc_done2_int : std_logic; + signal div_go_calc_int : std_logic; + signal op3_int, op3_next, opM_int, opM_next : csigned; 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 dividend_msb_int, dividend_msb_next, laengediv_int, laengediv_next : divinteger; signal quo_int, quo_next, aktdiv_int, aktdiv_int_next, op1_int, op1_next, op2_int, op2_next : csigned; signal sign_int, sign_next : std_logic; begin op3 <= op3_int; + opM <= opM_int; calc_done <= calc_done_int; calc_error <= calc_error_int; @@ -41,6 +46,7 @@ begin if sys_res_n = '0' then state_int <= SIDLE; op3_int <= (others => '0'); + opM_int <= (others => '0'); calc_done_int <= '0'; calc_error_int <= '0'; --div @@ -54,6 +60,7 @@ begin elsif rising_edge(sys_clk) then state_int <= state_next; op3_int <= op3_next; + opM_int <= opM_next; calc_done_int <= calc_done_next; calc_error_int <= calc_error_next; -- div @@ -69,7 +76,7 @@ begin -- next state process(state_int, opcode, done_intern, error_intern, do_calc, - div_calc_done, div_go_calc) + div_calc_done_int, div_calc_done2_int, div_go_calc_int) begin -- set a default value for next state state_next <= state_int; @@ -98,14 +105,17 @@ begin state_next <= SERROR; end if; when SDIV => - if div_go_calc = '1' then + if div_go_calc_int = '1' then state_next <= SDIV_CALC; end if; + if div_calc_done2_int = '1' then + state_next <= SDIV_DONE; + end if; if error_intern = '1' then state_next <= SERROR; end if; when SDIV_CALC => - if div_calc_done = '1' then + if div_calc_done_int = '1' then state_next <= SDIV_DONE; end if; when SDONE | SERROR => @@ -116,33 +126,37 @@ begin end process; -- output - process(state_int, op1, op2, dividend_msb_int, laengediv_int, quo_int, aktdiv_int, sign_int, op1_int, op2_int, op3_int) + process(state_int, op1, op2, dividend_msb_int, laengediv_int, quo_int, + aktdiv_int, sign_int, op1_int, op2_int, op3_int, opM_int) 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 laengediv_var, dividend_msb_var, divtmp : divinteger; 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'; + div_calc_done_int <= '0'; + div_calc_done2_int <= '0'; + div_go_calc_int <= '0'; done_intern <= '0'; error_intern <= '0'; -- default fuer div dividend_msb_next <= 0; laengediv_next <= 0; quo_next <= (others => '0'); - aktdiv_int_next <= (others => '0'); + aktdiv_int_next <= aktdiv_int; op1_next <= (others => '0'); op2_next <= (others => '0'); sign_next <= '0'; op3_next <= op3_int; + opM_next <= opM_int; case state_int is when SIDLE => - null; + opM_next <= (others => '0'); + aktdiv_int_next <= (others => '0'); when SADD => tmp := op1 + op2; op3_next <= tmp; @@ -201,18 +215,26 @@ begin aktdiv_int_next <= op1_var srl (dividend_msb_var - laengediv_var + 1); - div_go_calc <= '1'; - dividend_msb_next <= dividend_msb_var; - laengediv_next <= laengediv_var; - quo_next <= (others => '0'); - op1_next <= op1_var; - op2_next <= op2_var; - sign_next <= op1(CBITS-1) xor op2(CBITS-1); + if op1_var < op2_var then + div_calc_done2_int <= '1'; + quo_next <= to_signed(0,CBITS); + aktdiv_int_next <= op1_var; + else + div_go_calc_int <= '1'; + dividend_msb_next <= dividend_msb_var; + laengediv_next <= laengediv_var; + quo_next <= (others => '0'); + op1_next <= op1_var; + op2_next <= op2_var; + sign_next <= op1(CBITS-1) xor op2(CBITS-1); + end if; end if; when SDIV_CALC => - if (dividend_msb_int - laengediv_int + 1) > 0 then + divtmp := dividend_msb_int - laengediv_int + 1; + + if divtmp > 0 then aktdiv_int_var := aktdiv_int sll 1; - aktdiv_int_var(0) := op1_int(dividend_msb_int - laengediv_int); + aktdiv_int_var(0) := op1_int(divtmp - 1); quo_var := quo_int sll 1; if aktdiv_int_var >= op2_int then @@ -233,10 +255,11 @@ begin else quo_next <= quo_int; end if; - div_calc_done <= '1'; + div_calc_done_int <= '1'; end if; when SDIV_DONE => op3_next <= quo_int; + opM_next <= aktdiv_int; done_intern <= '1'; when SDONE | SERROR => calc_done_next <= '1'; diff --git a/src/beh_alu_tb.do b/src/beh_alu_tb.do index 3a14770..a0e954d 100644 --- a/src/beh_alu_tb.do +++ b/src/beh_alu_tb.do @@ -10,15 +10,28 @@ 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 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 delete wave /beh_alu_tb/inst/op3_next add wave -radix decimal inst/op3_int +delete wave /beh_alu_tb/inst/opM_int +delete wave /beh_alu_tb/inst/opM +delete wave /beh_alu_tb/inst/opM_next +add wave -radix decimal inst/opM_int + +delete wave /beh_alu_tb/inst/quo_int +delete wave /beh_alu_tb/inst/quo_next +add wave -radix decimal inst/quo_int + +delete wave /beh_alu_tb/inst/aktdiv_int +delete wave /beh_alu_tb/inst/aktdiv_int_next +add wave -radix decimal inst/aktdiv_int + #rauszoomen wave zoomout 500.0 diff --git a/src/beh_alu_tb.vhd b/src/beh_alu_tb.vhd index cb303ce..632896f 100644 --- a/src/beh_alu_tb.vhd +++ b/src/beh_alu_tb.vhd @@ -9,7 +9,7 @@ end entity beh_alu_tb; architecture sim of beh_alu_tb is signal sys_clk, sys_res_n, do_calc, calc_done, calc_error : std_logic; signal opcode : alu_ops; - signal op1, op2, op3 : csigned; + signal op1, op2, op3, opM : csigned; signal stop : boolean := false; begin inst : entity work.alu(beh) @@ -22,6 +22,7 @@ begin op1 => op1, op2 => op2, op3 => op3, + opM => opM, opcode => opcode, calc_error => calc_error ); @@ -42,63 +43,78 @@ begin o1 : cinteger; o : alu_ops; o2 : cinteger; + om : cinteger; expected : cinteger; errcase : boolean; end record alu_testv; -- ggf. groesse des arrays erhoehen - type alu_testv_array is array (natural range 0 to 44) of alu_testv; + type alu_testv_array is array (natural range 0 to 60) of alu_testv; variable testmatrix : alu_testv_array := - ( 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), + ( 0 => (-5, ALU_DIV, 3, 2, -1, false), + 1 => (7, ALU_ADD, 3, 0, 10, false), + 2 => (7, ALU_SUB, 1, 0, 6, false), + 3 => (7, ALU_DIV, 1, 0, 7, false), + 4 => (7, ALU_DIV, 3, 1, 2, false), + 5 => (7, ALU_ADD, 1, 0, 8, false), + 6 => (7, ALU_MUL, 3, 0, 21, false), + 7 => (-7, ALU_MUL, 3, 0, -21, false), + 8 => (268435456, ALU_MUL, -2, 0, -536870912, false), + 9 => (268435456, ALU_MUL, 2**5, 0, 0, false), -- um fuenf nach links shiften + 10 => (268435456 + 5, ALU_MUL, 2**5, 0, 160, false), -- = 5 * (2^5) + 11 => (100, ALU_DIV, 10, 0, 10, false), + 12 => (100, ALU_DIV, 51, 49, 1, false), + 13 => (100, ALU_DIV, 49, 2, 2, false), + 14 => (153156, ALU_DIV, 3543, 807, 43, false), + 15 => (-153156, ALU_DIV, 3543, 807, -43, false), + 16 => (153156, ALU_DIV, -3543, 807, -43, false), + 17 => (-153156, ALU_DIV, -3543, 807, 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), + 18 => (2147483647, ALU_ADD, -1, 0, 2147483646, false), + 19 => (2147483647, ALU_ADD, 1, 0, 0, true), + 20 => (-2147483645, ALU_ADD, -100, 0, 0, true), + 21 => (7, ALU_ADD, 1, 0, 8, false), + 22 => (7, ALU_ADD, -1, 0, 6, false), + 23 => (-7, ALU_ADD, 1, 0, -6, false), + 24 => (-7, ALU_ADD, -1, 0, -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), + 25 => (-7, ALU_SUB, 1, 0, -8, false), + 26 => (-7, ALU_SUB, -1, 0, -6, false), + 27 => (7, ALU_SUB, 1, 0, 6, false), + 28 => (7, ALU_SUB, -1, 0, 8, false), + 29 => (-2147483645, ALU_SUB, 1000, 0, 0, true), + 30 => (2147483645, ALU_SUB, -1000, 0, 0, true), + 31 => (-1000, ALU_SUB, 2147483645, 0, 0, true), + 32 => (1000, ALU_SUB, -2147483645, 0, 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), - 43 => (-4, ALU_DIV, 2, -2, false), - others => (0, ALU_ADD, 0, 0, false) + 33 => (3, ALU_MUL, 2, 0, 6, false), + 34 => (3, ALU_MUL, -2, 0, -6, false), + 35 => (-3, ALU_MUL, 2, 0, -6, false), + 36 => (-3, ALU_MUL, -2, 0, 6, false), + 37 => (90000, ALU_MUL, 100000, 0, 0, true), + 38 => (90000, ALU_MUL, -100000, 0, 0, true), + 39 => (-90000, ALU_MUL, 100000, 0, 0, true), + 40 => (-90000, ALU_MUL, -100000, 0, 0, true), + -- div: overflow check und division durch null + 41 => (-2147483648, ALU_DIV, -1, 0, 0, true), + 42 => (-2147483648, ALU_DIV, 0, 0, 0, true), + 43 => (-4, ALU_DIV, 2, 0, -2, false), + -- div/mod: + 44 => (1234, ALU_DIV, 3, 1, 411, false), + 45 => (1, ALU_DIV, 10, 1, 0, false), + 46 => (2, ALU_DIV, 10, 2, 0, false), + 47 => (3, ALU_DIV, 10, 3, 0, false), + 48 => (4, ALU_DIV, 10, 4, 0, false), + 49 => (5, ALU_DIV, 10, 5, 0, false), + 50 => (6, ALU_DIV, 10, 6, 0, false), + 51 => (7, ALU_DIV, 10, 7, 0, false), + 52 => (8, ALU_DIV, 10, 8, 0, false), + 53 => (9, ALU_DIV, 10, 9, 0, false), + 54 => (0, ALU_DIV, 10, 0, 0, false), + 55 => (10, ALU_DIV, 10, 0, 1, false), + 56 => (5134123, ALU_DIV, 358015, 121913, 14, false), + others => (0, ALU_ADD, 0, 0, 0, false) ); variable checkall : boolean := true; begin @@ -132,21 +148,25 @@ begin 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); + " /= " & integer'image(to_integer(op3)) & + " ( " & integer'image(to_integer(opM)) & " ) " & + " -- erwartet: " & cinteger'image(testmatrix(i).expected) & + " ( " & cinteger'image(testmatrix(i).om) & " ) "; checkall := false; else assert(false) report "testfall war ein error (passt)"; end if; else - assert op3 = to_signed(testmatrix(i).expected,CBITS) + assert ((op3 = to_signed(testmatrix(i).expected,CBITS)) and (opM = to_signed(testmatrix(i).om,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); + " /= " & integer'image(to_integer(op3)) & + " ( " & integer'image(to_integer(opM)) & " ) " & + " -- erwartet: " & cinteger'image(testmatrix(i).expected) & + " ( " & cinteger'image(testmatrix(i).om) & " ) "; - if op3 /= to_signed(testmatrix(i).expected,CBITS) then + if not((op3 = to_signed(testmatrix(i).expected,CBITS)) and (opM = to_signed(testmatrix(i).om,CBITS))) then checkall := false; end if; end if; diff --git a/src/gen_pkg.vhd b/src/gen_pkg.vhd index 7f5e2dc..10f1389 100644 --- a/src/gen_pkg.vhd +++ b/src/gen_pkg.vhd @@ -13,6 +13,7 @@ package gen_pkg is constant CBITS : integer := 32; subtype csigned is signed((CBITS-1) downto 0); + subtype divinteger is integer range -33 to 33; -- integer ist 32bit (31bit + sign) subtype cinteger is integer; @@ -21,13 +22,13 @@ package gen_pkg is subtype hbyte is std_logic_vector(7 downto 0); subtype hstring is string(1 to 71); - function find_msb(a : csigned) return natural; - procedure icwait(signal clk_i : IN std_logic; cycles: Natural); + function find_msb(a : csigned) return divinteger; + procedure icwait(signal clk_i : IN std_logic; cycles: natural); end package gen_pkg; package body gen_pkg is - function find_msb(a : csigned) return natural is - variable r : natural := 0; + function find_msb(a : csigned) return divinteger is + variable r : divinteger := 0; begin for i in (CBITS-1) downto 0 loop exit when a(i) = '1'; -- 2.25.1