Hardware vs simulation mismatch problem

P

Patrick

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!
 
Joined
Feb 14, 2011
Messages
7
Reaction score
0
Hi

1. There is a signal missing in sensitivity list of a process

sel_out: process (res_sel, inp1)

it should be

sel_out: process (res_sel, inp1, tx)

This MAY make the simulation run improperly, whilst the real hardware remains unaffected. Perhaps that's why you get different results.

2. In same process res is a nasty asynchronous latch. Every time when you make a non-clocked process, use case statement and do not describe what happens to a signal for all possible cases, you get a mux followed by asynchronous latch.

You should convert it to either synchronous latch (using clocked processes) or mux (by describing all possible cases, and NULL is not the solution).

good luck
 
P

Paul Uiterlinden

Patrick said:
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,

No, I haven't looked at the function of the code yet.
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?

First of all: look at the synthesis report. I would expect at least a
warning about tx: it is read in process sel_out and it is not in the
sensitivity list.

Secondly: why so many processes? It only complicates things.

That's why I see at first glance.
 
P

Patrick

First of all: look at the synthesis report. I would expect at least a
warning about tx: it is read in process sel_out and it is not in the
sensitivity list.

Hi again,

Thanks to your input, I implemented your suggestions, however the
problem remains the same. I checked the synthesis report and there are
no latches. 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
sincethe 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). 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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top