Simulation vs. Hardware mismatch

P

Patrick

Guest
Hi all,

I have a very simple problem but I do not get my head around what is
going wrong. Essentially, the whole thing works fine when simulating it,
however, having it in hardware gives me the wrong result. Basically I
have two ctrl signals that determine the behaviour of the entity:

GET (ctrl = "00000000") sets register tx to input of op1
SH1_L (ctrl = "00000001") outputs (op1 << 1) or register tx
shifts register tx to the right by 31 bits
(tx >> 31)


library ieee;
use ieee.std_logic_1164.all;

entity test is
port
(
op1 : in std_logic_vector(31 downto 0); -- Input operand
ctrl : in std_logic_vector(7 downto 0); -- Control signal
clk : in std_logic; -- clock
res : out std_logic_vector(31 downto 0) -- Result
);
end;

architecture rtl of test is

type res_sel_type is (GET, SH1_L);

constant Z : std_logic_vector(31 downto 0) := (others => '0');


signal res_sel : res_sel_type;
signal load : std_logic := '0';
signal shl : std_logic := '0';

signal tx : std_logic_vector(31 downto 0) := (others => '0');
signal inp1 : std_logic_vector(31 downto 0) := (others => '0');

begin

dec_op: process (ctrl, op1)
begin

res_sel <= GET;
load <= '0';
shl <= '0';
inp1 <= ( others => '0');

case ctrl is

-- store operand
when "00000000" =>
inp1 <= op1;
load <= '1';
res_sel <= GET;

-- 1-bit left-shift with carry
when "00000001" =>
inp1 <= op1;
shl <= '1';
res_sel <= SH1_L;

when others =>
-- Leave default values

end case;

end process;

-- Selection of output
sel_out: process (res_sel, inp1)
begin

case res_sel is

when GET => NULL;

when SH1_L =>
res <= ( inp1(30 downto 0) & '0' ) or tx;

when others =>
res <= (others => '0');

end case;

end process;

sync: process(clk)
begin
if clk'event and clk = '1' then
if load = '1' then
tx <= op1;
elsif shl = '1' then
tx <= Z(30 downto 0) & op1(31);
end if;
end if;
end process;

end rtl;

TESTPROGRAM

GET 0
SH1_L 0xfedcba90 exp. output: 0xfdb97520 act. output = 0xfdb97521
SH1_L 0x7654321f exp. output: 0xeca8643f act. output = 0xeca8643e
SH1_L 0x71234567 exp. output: 0xe2468ace act. output = 0xe2468ace

As you can see, the last bit is wrong for some reason. I must have
something wrong with the timing, so that the register tx is first
written before it is acutally used in the computation of the output.

Anyone an idea how to solve this problem?

Many thanks!
 
You should put "tx" on the sensitivity list.
Thanks, I tried that, but the result was unfortunately the same. Any
other ideas what could have gone wrong?

thanks!
 
Patrick wrote:
-- Selection of output
sel_out: process (res_sel, inp1)
begin

case res_sel is

when GET => NULL;

when SH1_L =
res <= ( inp1(30 downto 0) & '0' ) or tx;

when others =
res <= (others => '0');

end case;

end process;
You should put "tx" on the sensitivity list.

Best regards
 
On Feb 17, 7:06 pm, Patrick <Patr...@hotmail.com> wrote:
You should put "tx" on the sensitivity list.

Thanks, I tried that, but the result was unfortunately the same. Any
other ideas what could have gone wrong?

thanks!
Look carefully at all synthesis / map / par warnings. The above case
with 'tx' should have been highlighted in one of them.
There might be something else that is going wrong.
As an alternative, can you output intermediate signal also, and see
what their state is? Should help you zero in on the problem...
 
On 17 Feb., 18:59, Patrick <Patr...@hotmail.com> wrote:
Hi all,

I have a very simple problem but I do not get my head around what is
going wrong. Essentially, the whole thing works fine when simulating it,
however, having it in hardware gives me the wrong result. Basically I
have two ctrl signals that determine the behaviour of the entity:

  GET   (ctrl = "00000000") sets register tx to input of op1
  SH1_L (ctrl = "00000001") outputs (op1 << 1) or register tx
                            shifts register tx to the right by 31 bits
                           (tx >> 31)
[..]
Anyone an idea how to solve this problem?
First about your obvious part of the problem:

case res_sel is

when GET => NULL;
This leads to instatiation of a latch, this latch will likely store
the wrong value when you hope to have the output settle to the final
result.
In fact latch at the FF output (with little logic between) may lead to
unintended race-conditions.


Second your code and the solution to the described problem is
difficult to read and understand.
how about spending two registers for tx and the output and using only
one process to manage all?

if rising_edge(clk) then
case ctrl is
when GET => tx <= op1;
when SH1_L => tx <= (0 => op1(31), others => '0'); -- seems quite
silly, really needed?
res <= (op1(30 downto 0) & '0') or tx;
when others => null; -- or is res needed to be all 0?
end case;

regards Thomas
 
Hi again,

Thanks to all your input, I implemented your suggestions, however the
problem remains the same. The result in simulation works fine, but the
hardware
outputs something different. Just to briefly recap, I have two ctrl
signals that determine the behaviour of the entity:

GET (ctrl = "00000000") sets register tx to input of op1
SH1_L (ctrl = "00000001") res := (op1 << 1) | tx;
tx := tx >> 31;

library ieee;
use ieee.std_logic_1164.all;

entity test is
port
(
op1 : in std_logic_vector(31 downto 0); -- Input operand
ctrl : in std_logic_vector(7 downto 0); -- Control signal
clk : in std_logic; -- clock
res : out std_logic_vector(31 downto 0) -- Result
);
end;

architecture rtl of test is

type res_sel_type is (GET, SH1_L);

constant Z : std_logic_vector(31 downto 0) := (others => '0');

signal res_sel : res_sel_type;
signal load : std_logic := '0';
signal shl : std_logic := '0';

signal tx : std_logic_vector(31 downto 0) := (others => '0');
signal inp1 : std_logic_vector(31 downto 0) := (others => '0');

begin

dec_op: process (ctrl, op1)
begin

res_sel <= GET;
load <= '0';
shl <= '0';
inp1 <= ( others => '0');

case ctrl is

-- store operand
when "00000000" =>
inp1 <= op1;
load <= '1';
res_sel <= GET;

-- 1-bit left-shift with carry
when "00000001" =>
inp1 <= op1;
shl <= '1';
res_sel <= SH1_L;

when others =>
-- Leave default values

end case;

end process;

sel_out: process (res_sel, inp1, tx)
begin

case res_sel is

when SH1_L =>
res <= ( inp1(30 downto 0) & '0' ) or tx;

when others =>
res <= (others => '0');

end case;

end process;

sync: process(clk)
begin
if clk'event and clk = '1' then
if load = '1' then
tx <= op1;
elsif shl = '1' then
tx <= Z(30 downto 0) & op1(31);
end if;
end if;
end process;

end rtl;

TESTPROGRAM

GET 0 (this sets tx <= 0 )
SH1_L 0xfedcba90 exp. output: 0xfdb97520 act. output = 0xfdb97521
SH1_L 0x7654321f exp. output: 0xeca8643f act. output = 0xeca8643f
SH1_L 0x71234567 exp. output: 0xe2468ace act. output = 0xe2468ace

As you can see, the last bit is wrong for the first SH1_L operation. The
first SH1_L operation produces a carry for the NEXT SH1_L operation since
the MSB is set to one of the input, however, it seems that this carry is
already considered in the current SH1_L operation, which is wrong (tx
should be zero).
I checked the synthesis report and there are no latches, so I am a bit
clueless and almost desperate what is going wrong here. I use Xilinx ISE
12.1 for
synthesis, could there be a problem because I do not have a reset signal
in my architecture, that the wrong kind of latches are instantiated?

Many thanks for further helpful comments to solve this issue,
Patrick
 
On Feb 27, 11:02 am, Patrick <Patr...@hotmail.com> wrote:
Hi again,

Thanks to all your input, I implemented your suggestions, however the
problem remains the same. The result in simulation works fine, but the
hardware
outputs something different. Just to briefly recap, I have two ctrl
signals that determine the behaviour of the entity:

GET (ctrl = "00000000") sets register tx to input of op1
SH1_L (ctrl = "00000001") res := (op1 << 1) | tx;
tx := tx >> 31;

library ieee;
use ieee.std_logic_1164.all;

entity test is
port
(
op1 : in std_logic_vector(31 downto 0); -- Input operand
ctrl : in std_logic_vector(7 downto 0); -- Control signal
clk : in std_logic; -- clock
res : out std_logic_vector(31 downto 0) -- Result
);
end;

architecture rtl of test is

type res_sel_type is (GET, SH1_L);

constant Z : std_logic_vector(31 downto 0) := (others => '0');

signal res_sel : res_sel_type;
signal load : std_logic := '0';
signal shl : std_logic := '0';

signal tx : std_logic_vector(31 downto 0) := (others => '0');
signal inp1 : std_logic_vector(31 downto 0) := (others => '0');

begin

dec_op: process (ctrl, op1)
begin

res_sel <= GET;
load <= '0';
shl <= '0';
inp1 <= ( others => '0');

case ctrl is

-- store operand
when "00000000" =
inp1 <= op1;
load <= '1';
res_sel <= GET;

-- 1-bit left-shift with carry
when "00000001" =
inp1 <= op1;
shl <= '1';
res_sel <= SH1_L;

when others =
-- Leave default values

end case;

end process;

sel_out: process (res_sel, inp1, tx)
begin

case res_sel is

when SH1_L =
res <= ( inp1(30 downto 0) & '0' ) or tx;

when others =
res <= (others => '0');

end case;

end process;

sync: process(clk)
begin
if clk'event and clk = '1' then
if load = '1' then
tx <= op1;
elsif shl = '1' then
tx <= Z(30 downto 0) & op1(31);
end if;
end if;
end process;

end rtl;

TESTPROGRAM

GET 0 (this sets tx <= 0 )
SH1_L 0xfedcba90 exp. output: 0xfdb97520 act. output = 0xfdb97521
SH1_L 0x7654321f exp. output: 0xeca8643f act. output = 0xeca8643f
SH1_L 0x71234567 exp. output: 0xe2468ace act. output = 0xe2468ace

As you can see, the last bit is wrong for the first SH1_L operation. The
first SH1_L operation produces a carry for the NEXT SH1_L operation since
the MSB is set to one of the input, however, it seems that this carry is
already considered in the current SH1_L operation, which is wrong (tx
should be zero).
I checked the synthesis report and there are no latches, so I am a bit
clueless and almost desperate what is going wrong here. I use Xilinx ISE
12.1 for
synthesis, could there be a problem because I do not have a reset signal
in my architecture, that the wrong kind of latches are instantiated?

Many thanks for further helpful comments to solve this issue,
Patrick
I'm not sure what your results mean really. It depends on when you
are looking at the output. If you are applying the inputs to the UUT
(unit under test) and toggle the clock, then look at the outputs, then
I think this result is correct. As soon as you get a rising edge on
the clock, tx will change and your output will change. The tx
register is the only register in your design. The rest of the circuit
is combinatorial, sot that those signals all change as soon as the
inputs change.

So what is the timing between your input stimulus, the output
observation and the clock?

Rick
 

Welcome to EDABoard.com

Sponsor

Back
Top