Reputation: 458
i am newbie in vhdl, modelsim, waveform etc. i've developed a simple operational process and a testbench to test my operations one by one on modelsim waveform.
when i run at simulator i see there are some problems; at multiply operation result is not put to output variable (result_out1) although it is calculated correctly at temp variable (uQ2). furthermore mod and rem operations do not give any output.
although add, sub and div operations work as expected why mul, mod and rem operaions fail?
i am sharing my code and waveform result below.
my code and testbench are below;
rns.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity rns is
port(
en: in std_logic;
op: in std_logic_vector(2 downto 0);
reg_a_in: in std_logic_vector(7 downto 0);
reg_b_in: in std_logic_vector(7 downto 0);
reg_c_in: in std_logic_vector(7 downto 0);
result_out1: out std_logic_vector(7 downto 0);
result_out2: out std_logic_vector(7 downto 0)
);
end entity;
architecture behave of rns is
signal uA, uB, uC, uQ, uR: unsigned(8 downto 0);
signal uQ2: unsigned(17 downto 0);
signal result: std_logic_vector(8 downto 0);
begin
process(reg_a_in, reg_b_in, op)
begin
uA <= unsigned('0' & reg_a_in);
uB <= unsigned('0' & reg_b_in);
if op = "000" then
uQ <= uA + uB;
elsif op = "001" then
uQ <= uA - uB;
elsif op = "010" then
uQ2 <= uA * uB;
uQ <= resize(uQ2, uQ'length); --uQ2(8 downto 0);
elsif op = "011" then
uQ <= uA / uB;
elsif op = "100" then
uQ <= uA mod uB;
elsif op = "101" then
uQ <= uA rem uB;
end if;
end process;
result <= std_logic_vector(uQ) when en = '1' else (others=>'Z');
result_out1 <= result(7 downto 0) when en = '1' else (others=>'Z');
end behave;
rns_tb.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity rns_tb is
end entity;
architecture behave of rns_tb is
component rns is
port(
en: in std_logic;
op: in std_logic_vector(2 downto 0);
reg_a_in: in std_logic_vector(7 downto 0);
reg_b_in: in std_logic_vector(7 downto 0);
reg_c_in: in std_logic_vector(7 downto 0);
result_out1: out std_logic_vector(7 downto 0);
result_out2: out std_logic_vector(7 downto 0)
);
end component;
signal en_sig: std_logic;
signal op_sig: std_logic_vector(2 downto 0);
signal reg_a_in_sig: std_logic_vector(7 downto 0);
signal reg_b_in_sig: std_logic_vector(7 downto 0);
signal reg_c_in_sig: std_logic_vector(7 downto 0);
signal result_out1_sig: std_logic_vector(7 downto 0);
signal result_out2_sig: std_logic_vector(7 downto 0);
constant wait_period: time :=10 ns;
begin
rns1 : rns port map(en=>en_sig, op=>op_sig, reg_a_in=>reg_a_in_sig, reg_b_in=>reg_b_in_sig,
reg_c_in=>reg_c_in_sig, result_out1=>result_out1_sig, result_out2=>result_out2_sig);
process
begin
op_sig <= (others => 'Z');
wait for wait_period * 3;
reg_a_in_sig <= "00000011";
reg_b_in_sig <= "00000010";
reg_c_in_sig <= "00000101";
wait for wait_period;
en_sig <= '1';
op_sig <= "000";
wait for wait_period * 5;
op_sig <= "001";
wait for wait_period * 5;
op_sig <= "010";
wait for wait_period * 5;
op_sig <= "011";
wait for wait_period * 5;
op_sig <= "100";
wait for wait_period * 5;
op_sig <= "101";
wait;
end process;
end behave;
thanks in advance.
Upvotes: 0
Views: 549
Reputation: 1162
To be honest I'd suggest to use only clocked processes until you fully understand how they work. But let's see if we can fix your problem.
The problem is with the sensitivity list of your process. The simulation tool will evaluate the result of the process whenever a signal in the sensitivity list changes. For all operations this is signal op
that changes and the process re-evaluates uQ
.
Important note: Sensitivity lists only serve for simulation purpose and signals are assigned after the process evaluation is complete.
The above means that in case of your multiplication, the op
changes to 010
and the process evaluates
uQ2 <= uA * uB;
uQ <= resize(uQ2, uQ'length); --uQ2(8 downto 0);
but because signals are assigned after evaluation, uQ2
will have the result of the multiplication but uQ
is the resize of the previous uQ2
. To fix this you can either...
uQ2
and directly write uQ <= resize(uA * uB, uQ'length)
uQ2
so that uQ
is re-evaluated once uQ2
got updated.process
that are evaluated immediately use variables
instead of signal
types.The result assignment can be optimized and to be honest, I would't use Z
in this case.
--result <= std_logic_vector(uQ) when en = '1' else (others=>'Z');
result_out1 <= std_logic_vector(uQ(7 downto 0)) when en = '1' else (others=>'0');
In general, this implementation has some pitfalls and you might should add some additional control signals or even make it a clocked process. Check if this solves your issue, I didn't test it and my brain is still in Christmas mode.
Upvotes: 1