Reputation: 59
I am working on a project which one part pivots around finding X mod 3 with and FPGA spartan 3 (Xilinx), inside a combinatorial process. in fact in this project there are some other modules which are sequential, before this ALU module. but inside the ALU module, it is not allowed to use sequential process. so I tried to use one method from here:
Here is an simple way to do it by hand. Since 1 = 22 mod 3, we get 1 = 22n mod 3 for every positive integer. Furthermore 2 = 22n+1 mod 3. Hence one can determine if an integer is divisible by 3 by counting the 1 bits at odd bit positions, multiply this number by 2, add the number of 1-bits at even bit posistions add them to the result and check if the result is divisible by 3.
Example: 5710=1110012. There are 2 bits at odd positions, and 2 bits at even positions. 2*2 + 2 = 6 is divisible by 3. Hence 57 is divisible by 3.
I have posted my codes down there. the problem is that after I concatenate the odd bits and even bits in two different signals:
mod_un_t1 <= A(6) & A(4)& A(2) & A(0);
mod_un_t2 <= A(7) & A(5)& A(3) & A(1);
I lose all data and no if statement works after that. I simulated my code with a test-bench. but it always gives:
result <= "00000000";
I have tested it and I found out that no data would be pass down after that concatenation. I cannot use sequential network and count-up and count-down methods, or shift register method which all of them work with clk and sequential process.
Could any one please help me, to solve the problem in my code, and if anyone has a better method or better implementation way let me be through this nowhere!!!
and this is my code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
Use Ieee.std_logic_unsigned.all;
entity ALU is
port ( A : in std_logic_vector (7 downto 0); -- Input A
B : in std_logic_vector (7 downto 0); -- Input B
FN : in std_logic_vector (3 downto 0); -- ALU functions provided by the ALU_Controller (see the lab manual)
result : out std_logic_vector (7 downto 0); -- ALU output (unsigned binary)
overflow : out std_logic; -- '1' if overflow ocurres, '0' otherwise
sign : out std_logic -- '1' if the result is a negative value, '0' otherwise
);
end ALU;
architecture behavioral of ALU is
signal mod_un_t1: std_logic_vector (3 downto 0);
signal mod_un_t2: std_logic_vector (3 downto 0);
signal mod_un_t3: std_logic_vector (3 downto 0);
signal mod_un_t4: std_logic_vector (3 downto 0);
signal mod_unsigned: std_logic_vector (3 downto 0);
signal mod_si_t1: std_logic_vector (3 downto 0);
signal mod_si_t2: std_logic_vector (3 downto 0);
signal mod_si_t3: std_logic_vector (3 downto 0);
signal mod_si_t4: std_logic_vector (3 downto 0);
signal mod_signed: std_logic_vector (3 downto 0);
begin
process ( FN, A, B , result_tmp)
begin
result <= (others => '0');
mod_un_t1 <= (others => '0');
mod_un_t2 <= (others => '0');
mod_un_t3 <= (others => '0');
mod_un_t4 <= (others => '0');
mod_unsigned <= (others => '0');
mod_si_t1 <= (others => '0');
mod_si_t2 <= (others => '0');
mod_si_t3 <= (others => '0');
mod_si_t4 <= (others => '0');
mod_signed <= (others => '0');
if (FN = "0100") then -- Unsigned (A) mod 3
mod_un_t1 <= A(6) & A(4)& A(2) & A(0);
mod_un_t2 <= A(7) & A(5)& A(3) & A(1);
if(mod_un_t1= "1111") then
mod_un_t3 <= "1000";
elsif(mod_un_t1 = "1110" or mod_un_t1 = "1101" or mod_un_t1 = "1011" or mod_un_t1 = "0111") then
mod_un_t3 <= "0110";
elsif(mod_un_t1 = "1100" or mod_un_t1 = "1010" or mod_un_t1 = "1001" or mod_un_t1 = "0110" or mod_un_t1 = "0101" or mod_un_t1 = "0011") then
mod_un_t3 <= "0100";
elsif(mod_un_t1 = "0001" or mod_un_t1 = "0010" or mod_un_t1 = "0100" or mod_un_t1 = "1000") then
mod_un_t3 <= "0010";
elsif (mod_un_t1 = "0000") then
mod_un_t3 <= "0000";
end if;
if (mod_un_t2 = "1111") then
mod_un_t4 <= "0100";
elsif (mod_un_t2 = "1110" or mod_un_t2 = "1101" or mod_un_t2 = "1011" or mod_un_t2 = "0111") then
mod_un_t4 <= "0011";
elsif(mod_un_t2 = "1100" or mod_un_t2 = "1010" or mod_un_t2 = "1001" or mod_un_t2 = "0110" or mod_un_t2 = "0101" or mod_un_t2 = "0011") then
mod_un_t4 <= "0010";
elsif(mod_un_t2 = "0001" or mod_un_t2 = "0010" or mod_un_t2 = "0100" or mod_un_t2 = "1000") then
mod_un_t4 <= "0001";
elsif(mod_un_t2 = "0000") then
mod_un_t4 <= "0000";
end if;
mod_unsigned <= mod_un_t3 + mod_un_t4;
if (mod_unsigned = "0010" or mod_unsigned = "0101" or mod_unsigned ="0111" or mod_unsigned = "1010") then
result <= "00000001";
elsif (mod_unsigned = "0001" or mod_unsigned = "0100" or mod_unsigned = "1000" or mod_unsigned = "1011") then
result <= "00000010";
elsif (mod_unsigned = "0000" or mod_unsigned = "0011" or mod_unsigned = "0110" or mod_unsigned = "1001") then
result <= "00000000";
end if;
end if;
end process;
end behavioral;
Upvotes: 1
Views: 270
Reputation:
The signals that don't seem to have assignments are missing from the process sensitivity list. They could otherwise be variables, allowing their use during the current simulation cycle without generating delta cycles because signal assignment doesn't take effect until the end or the current simulation cycle.
Candidates for variables appear to be:
signal mod_un_t1: std_logic_vector (3 downto 0);
signal mod_un_t2: std_logic_vector (3 downto 0);
signal mod_un_t3: std_logic_vector (3 downto 0);
signal mod_un_t4: std_logic_vector (3 downto 0);
signal mod_unsigned: std_logic_vector (3 downto 0);
signal mod_si_t1: std_logic_vector (3 downto 0);
signal mod_si_t2: std_logic_vector (3 downto 0);
signal mod_si_t3: std_logic_vector (3 downto 0);
signal mod_si_t4: std_logic_vector (3 downto 0);
signal mod_signed: std_logic_vector (3 downto 0);
These declarations could be changed to object class variable and moved to the process (before the begin
). The signal assignments for them (<=
) would be switched to variable assignment (:=
).
You could simply put those that show up on the right hand side of an assignment in the sensitivity list, but that would cause extra delta cycles.
If there's a reason to keep them signals you could consider breaking your process up into multiple processes and/or other concurrent statements.
There's a result_tmp
in the sensitivity list that doesn't have a declaration or an assignment in the code you've shown.
... could you please also give a short example for breaking the process up into multiple processes and/or other concurrent statements?
Aarchitecture foo of ALU is
signal mod_un_t1: std_logic_vector (3 downto 0);
signal mod_un_t2: std_logic_vector (3 downto 0);
signal mod_un_t3: std_logic_vector (3 downto 0);
signal mod_un_t4: std_logic_vector (3 downto 0);
signal mod_unsigned: std_logic_vector (3 downto 0);
signal mod_si_t1: std_logic_vector (3 downto 0);
signal mod_si_t2: std_logic_vector (3 downto 0);
signal mod_si_t3: std_logic_vector (3 downto 0);
signal mod_si_t4: std_logic_vector (3 downto 0);
signal mod_signed: std_logic_vector (3 downto 0);
-- dummy
signal result_tmp: std_logic_vector(7 downto 0);
begin
-- Concurrent signal assignments - these are just wires
mod_un_t1 <= A(6) & A(4)& A(2) & A(0);
mod_un_t2 <= A(7) & A(5)& A(3) & A(1);
UNPROC1:
process (FN, mod_un_t1)
begin
if FN = "0100" then
case mod_un_t1 is
when "0000" =>
mod_un_t3 <= "0000";
when "0001" | "0010" | "0100" | "1000" =>
mod_un_t3 <= "0010";
when "1100" | "1010" | "1001" | "0110" =>
mod_un_t3 <= "0100";
when "1110" | "1101" | "1011" | "0111" =>
mod_un_t3 <= "0100";
when others =>
end case;
else
--
end if;
end process;
UNPROC2:
process (FN, mod_un_t2)
begin
if FN = "0100" then
if mod_un_t2 = "1111" then
mod_un_t4 <= "0100";
elsif mod_un_t2 = "1110" or mod_un_t2 = "1101" or mod_un_t2 = "1011" or mod_un_t2 = "0111" then
mod_un_t4 <= "0011";
elsif mod_un_t2 = "1100" or mod_un_t2 = "1010" or mod_un_t2 = "1001" or mod_un_t2 = "0110" or mod_un_t2 = "0101" or mod_un_t2 = "0011" then
mod_un_t4 <= "0010";
elsif mod_un_t2 = "0001" or mod_un_t2 = "0010" or mod_un_t2 = "0100" or mod_un_t2 = "1000" then
mod_un_t4 <= "0001";
elsif mod_un_t2 = "0000" then
mod_un_t4 <= "0000";
end if;
else
--
end if;
end process;
ALU_PROC: -- keep all the arithemetic operations in one process
process (FN, mod_un_t3, mod_un_t4)
begin
if FN = "0100" then
mod_unsigned <= mod_un_t3 + mod_un_t4;
else
end if;
end process;
OUT_PROC: -- keep all the result assignment in one process
process (FN, mod_unsigned)
begin
if FN = "0100" then
if mod_unsigned = "0010" or mod_unsigned = "0101" or mod_unsigned ="0111" or mod_unsigned = "1010" then
result <= "00000001";
elsif mod_unsigned = "0001" or mod_unsigned = "0100" or mod_unsigned = "1000" or mod_unsigned = "1011" then
result <= "00000010";
elsif mod_unsigned = "0000" or mod_unsigned = "0011" or mod_unsigned = "0110" or mod_unsigned = "1001" then
result <= "00000000";
else
--
end if;
end if;
end process;
end architecture foo;
Upvotes: 1