[SOLVED] VHDL - Strange simulation behaviour (forcing unknown)

Status
Not open for further replies.

AlienObserver

Newbie level 2
Joined
Oct 22, 2013
Messages
2
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Visit site
Activity points
26
VHDL - Strange simulation behaviour

Greetings.

I have made a simple module for controlling the motion of a robot. It takes as inputs a setpoint 'sp' (i.e. desired position), and the actual measured position 'pos'. An error is then computed as the discrepancy between the two mentioned inputs, and appropriate outputs are produced. The problem I encounter is during simulation; the outputs 'motor_cw' and 'motor_ccw' appear glitched (i.e. uninitialized, forcing unknown).

The entity:
Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity p_ctrl is
port (
rst : in std_logic; -- Reset
clk : in std_logic; -- Clock
sp : in signed(7 downto 0); -- Set Point
pos : in signed(7 downto 0); -- Measured position
motor_cw : out std_logic; -- Motor Clock Wise direction
motor_ccw : out std_logic -- Motor Counter Clock Wise direction
);
end p_ctrl;

The archictecture:
Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

architecture rtl of p_ctrl is

type state_t is (IDLE, SAMPLE, MOTOR);

signal present_st : state_t;
signal next_st : state_t;
signal sp_sync : signed(7 downto 0);
signal pos_sync : signed(7 downto 0);
signal err : signed(7 downto 0) := (others => '0');
signal err_next : signed(7 downto 0) := (others => '0');
signal motor_cw_next : std_logic := '0';
signal motor_ccw_next : std_logic := '0';

begin

STATE_REG: process(clk, rst)
begin
if (rst = '1') then
present_st <= IDLE;
elsif (rising_edge(clk)) then
-- assign to cw/ccw/err the values from the previous
-- clock cycle as per the ASM chart
err <= err_next;
motor_cw <= motor_cw_next;
motor_ccw <= motor_ccw_next;
-- synchronize inputs
sp_sync <= sp;
pos_sync <= pos;
-- change state
present_st <= next_st;
end if;
end process STATE_REG;

COMB: process(sp_sync, pos_sync, present_st)
begin
case present_st is
when IDLE =>
motor_cw <= '0';
motor_ccw <= '0';
next_st <= SAMPLE;
when SAMPLE =>
err_next <= sp_sync - pos_sync;
next_st <= MOTOR;
when MOTOR =>
if (err > 0) then
motor_cw_next <= '1';
motor_ccw_next <= '0';
elsif (err < 0) then
motor_cw_next <= '0';
motor_ccw_next <= '1';
else
motor_cw_next <= '0';
motor_ccw_next <= '0';
end if;
next_st <= SAMPLE;
end case;
end process COMB;

end rtl;

The testbench:
Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity tb_p_ctrl is
-- empty
end tb_p_ctrl;

architecture beh of tb_p_ctrl is

component p_ctrl is
port (rst : in std_logic;
clk : in std_logic;
sp : in signed(7 downto 0);
pos : in signed(7 downto 0);
motor_cw : out std_logic;
motor_ccw : out std_logic);
end component p_ctrl;

signal rst : std_logic;
signal clk : std_logic := '0';
signal sp : signed(7 downto 0);
signal pos : signed(7 downto 0);
signal motor_cw : std_logic;
signal motor_ccw : std_logic;

begin

UUT : entity work.p_ctrl(rtl)
port map (rst => rst,
clk => clk,
sp => sp,
pos => pos,
motor_cw => motor_cw,
motor_ccw => motor_ccw);

-- stimuli
clk <= not clk after 10 ns;
rst <= '1', '0' after 40 ns;
sp <= to_signed(100, 8);
pos <= to_signed(50, 8), to_signed(80, 8) after 150 ns,
to_signed(115, 8) after 300 ns;

end beh;

The waveform result of the testbench:
https://i.imgur.com/4np3Kj2.jpg

What I don't understand is the uninitialized behaviour of the outputs. For instance, at time t=0ns, the present state is IDLE and per my code the outputs are both set to '0'. The outputs aren't updated again until rst = '0' and we have a rising edge on the clock, which occurs at time t=50ns. So why are the outputs uninitialized on this time interval? At time t=50ns the outputs get correct values, i.e. '0' for both. At time t=90ns, however, motor_cw_next = '1', motor_ccw_next = '0' and we have a rising edge on the clock, so the outputs motor_cw and motor_ccw should be set to '1' and '0' respectively. Instead motor_cw becomes forcing unknown 'X'.

So my question is, what produces this weird behaviour? If it makes a difference, this is part of a homework assignment in an FPGA class I'm taking. I hope I haven't made any extremely silly errors, but I can't seem to find any at the time of writing this.

Any help is greatly appreciated.
 
Last edited by a moderator:

I have nor completely gone through the code, but a superficial look tell me it is the assignment of motor_cw and and motor_ccw register that is causing problem, once you have assigned it as a synchronous logic, and in the same process you have applied it as the combination logic, hence the compiler may not understand the behavior...

Any ways it is not a good design at all, since the application to the signal can be either synchronous or combination.
 
On another note - you have created latches in your state machine process by not assigning all signals in all cases (specifcally err_next).
 
*bangs head against wall*

Thanks all! Tweaked it and it now works flawlessly.
 

Deleting your post is NOT acceptable. If you dont want it posted - you should not post it in the first place. I suspect you'll get a warning for deleting the code.
 

The content of the original post has been restored, such action (removing the content of a question after receiving help) is against the forum rules

Alex
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…