Reputation: 257
Here is the code:
entity main is
port(input:in unsigned(99 downto 0);
clk:in std_logic;
output:out unsigned(99 downto 0)
);
end main;
architecture Behavioral of main is
begin
process(clk)
variable x:unsigned(99 downto 0):=X"27c8a94a6fb72a00000000000";
begin
if(clk'event and clk='1') then
x:=(x*input);// this line is a problem!!
output<=x;
x:=X"27c8a94a6fb72a00000000000";// i have to rest x manually :S
end if;
end process;
end Behavioral;
first problem is that x although a variable and should reset each time process is run it doesn't and saves its value! and I have seen it step by step in simulation. 2nd problem is although input is fixed to this entity and doesn't change by each clk process x either is x * input( correct answer) or 0( wrong answer) by the time my clock stops ticking it stops at 0 answers, if I decrease clock a little it may stop at correct answer (which is input x) my problem is why inputx is not fixed if input and x are fixed, 2nd is why doesn't x resets when process is called again(from its sensitivity list). here is test code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use IEEE.numeric_std.all;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY test IS
END test;
ARCHITECTURE behavior OF test IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT main
PORT(
input : IN unsigned(99 downto 0);
clk : IN std_logic;
output : OUT unsigned(99 downto 0)
);
END COMPONENT;
--Inputs
signal input : unsigned(99 downto 0) := (others => '0');
signal clk : std_logic := '0';
--Outputs
signal output : unsigned(99 downto 0);
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: main PORT MAP (
input => input,
clk => clk,
output => output
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
wait for 100 ns;
input<=X"000000000000000000000000F";
--input<="000000000001";
wait for clk_period*10;
-- insert stimulus here
wait;
end process;
END;
///
Notice that at beginning of test the process is run several times without inserting input value, in this case I don't care about results, I am talking when input is inserted that this problem occurs.
Upvotes: 1
Views: 1547
Reputation: 1387
the problem is, that you multiply 2 unsigned values of length 100. this leads to a result of length 200 (see numeric_std package!). you can solve your issue as follows:
entity main is
port(
input:in unsigned(99 downto 0);
clk:in std_logic;
output:out unsigned(199 downto 0)
);
end main;
architecture Behavioral of main is
begin
process(clk)
variable x:unsigned(99 downto 0);
variable x_res:unsigned(199 downto 0);
begin
if(clk'event and clk='1') then
x:=(input);
x_res:=(x*x);
output<=x_res;
end if;
end process;
end Behavioral;
Upvotes: 0
Reputation:
The first thing to understand is that you never call a process!
A process is only started once - and so the variable is only initialised once.
It runs to completion and sleeps - the next clock event wakes it up and it executes from the beginning to completion in each clock cycle.
It may help to think of a process as being like a C main program with an event loop; it sleeps until the event happens, and the variable you have declared is a global variable (or "static" variable - it keeps its last value).
If you want the effect of a C function or procedure (cough, void function) write a VHDL function or procedure; the local variables in these will be re-initialised each time you call them within the process.
So after 1 clock cycle you see x * input
, after several clock cycles you see the least significant 100 bits of x * input * input * input ... * input
which, thanks to multiplication word growth, will eventually all be 0.
If all you want to do is multiply each new input by the initial value of X, then you would be better to declare X a constant, and simply write:
process(clk)
constant x:unsigned(99 downto 0):=X"27c8a94a6fb72a00000000000";
begin
if rising_edge(clk) then
output <= x * input;
end if;
end process;
Upvotes: 1