Why doesn't this work in an XC9572XL?

Joined
Dec 9, 2008
Messages
88
Reaction score
0
I have a fairly simple program here, that is supposed to run on a XC2-XL evaluation board. In the past it simulated properly, but I haven't rerun a simulation in a while.

It takes the 1.8 MHz clock and divides it by 2^20 for a 2 Hz clock. It then cycles a pattern through four outputs on the part. I see the reset pattern happen, but nothing else. What am I missing?


Thanks in advance,

John

====================================
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
library UNISIM;
use UNISIM.VComponents.all;

entity GDC_top is
Port ( EncA_I : in STD_LOGIC;
EncB_I : in STD_LOGIC;
Reset_I : in STD_LOGIC;
GoLimA_I : in STD_LOGIC;
GoLimB_I : in STD_LOGIC;
Stop_I : in STD_LOGIC;
SetPos_I : in STD_LOGIC;
GoPos_I : in STD_LOGIC;
Scale_I : in STD_LOGIC;
LimAHit_I : in STD_LOGIC;
LimBHit_I : in STD_LOGIC;
Clk1p8_I : in STD_LOGIC;
Step_O : out STD_LOGIC;
Dir_O : out STD_LOGIC;
Scale0_O : out STD_LOGIC; -- active low
Scale1_O : out STD_LOGIC; -- active low
Scale2_O : out STD_LOGIC; -- active low
Scale3_O : out STD_LOGIC; -- active low
LimA_O : out STD_LOGIC;
LimB_O : out STD_LOGIC;
PosSet_O : out STD_LOGIC);
end GDC_top;


architecture Behavioral of GDC_top is

signal clk_scaler : unsigned(20 downto 0); -- Divides the clock and provides various divisors
signal clk : std_logic; -- Internal clock derived from oscillators
signal clk_180 : std_logic; -- clock with 180 degree shift
signal Scale_state : unsigned(1 downto 0); -- Scale_I state
signal Reset : std_logic; -- buffered reset
signal Scale_size : unsigned(7 downto 0); -- eight bit scale multipler (255 max)

begin

-- CLOCK PRESCALER, the fast synchronous timing block
process (Clk1p8_I, Reset_I, clk_scaler)
begin
if (Reset_I = '1') then
clk_scaler <= (others => '0');
elsif (Clk1p8_I'event) and (Clk1p8_I = '1')
then
clk_scaler <= clk_scaler + 1; -- Divides clock and provides various divisors
end if;

clk <= clk_scaler(20); -- change this to (20) when ready to implement in CPLD; (0) for sim
clk_180 <= not(clk_scaler(20)); -- change this to (20) when ready to implement in CPLD; (0) for sim
Reset <= not(Reset_I); -- this needs an inversion 1-23-09 JRD

end process; -- CLOCK prescaler


process(clk_180, Reset)
-- the other big slow synchronous clock that is 180 out of sync

variable old_state : unsigned(1 downto 0); -- previous state

begin
if (Reset = '1')
then
Scale0_O <= '1';
Scale1_O <= '0';
Scale2_O <= '1';
Scale3_O <= '1';
Scale_size <= "00000100"; -- one is the default scale
elsif (clk_180'event) and (clk_180 = '1')
then

-- Scaler output
case Scale_state is
when "00" =>
Scale0_O <= '0';
Scale1_O <= '1';
Scale2_O <= '1';
Scale3_O <= '1';
Scale_size <= "00000010"; -- one *2
when "01" =>
Scale0_O <= '1';
Scale1_O <= '0';
Scale2_O <= '1';
Scale3_O <= '1';
Scale_size <= "00000100"; -- two *2
when "10" =>
Scale0_O <= '1';
Scale1_O <= '1';
Scale2_O <= '0';
Scale3_O <= '1';
Scale_size <= "00000110"; -- three *2
when others => -- aka "11"
Scale0_O <= '1';
Scale1_O <= '1';
Scale2_O <= '1';
Scale3_O <= '0';
Scale_size <= "00001000"; -- four *2
end case;
end if;

end process; -- process(clk_180)


process(clk, Reset) -- one big slow synchronous timing block

variable previous_step : std_logic; -- previous step for change detector
variable previous_scale : std_logic; -- previous scale for change detection


begin
if (Reset = '1') then
Scale_state <= (others => '0');
LimA_O <= '0';
LimB_O <= '0';
PosSet_O <= '0';
Dir_O <= '0';
elsif (clk'event) and (clk = '1')
then
Scale_state <= Scale_state + 1; -- increment scale state
end if; -- risingedge(clk)
end process;


end Behavioral;


====================================
 
Joined
Dec 9, 2008
Messages
88
Reaction score
0
Hmm, and I just tried to simulate it and it doesn't work there anymore either...
Is there something wrong with my clocking technique? I'm using the old school technique of having signals change on one edge of the clock (rising edge of CLK) and then latching them on the other edge (rising edge of CLK_180). Here my dual clocking rate is thus half of CLK.

This used to work fine in ABEL, does it still work in VHDL?

John
 
Joined
Dec 9, 2008
Messages
88
Reaction score
0
Okay, it looks like I figured out what's going on. Here is my lesson's learned list from this project:

1. When I moved from simulation to real hardware I found the reset signal was inverted, so I then inverted it in some but not all of my logic (doh!). In 'C' I would set a constant like RESET_LEVEL = '1' and then use that in my logic later (if apple = RESET_LEVEL, if banana = not(RESET_LEVEL)) so then I would only have to make one change to accommodate hardware changes.

Is there a way to define constants in VHDL?


2. When designing synchronous logic, don't define variables, only define signals. Variables and signals will change on the same clock edge; variables will NOT change value at the end of the process as some of the VHDL tutorials on the web indicate. If you have a signal referencing a variable (or vice versa) in the same process you will get timing violations. Processes in synchronous logic are not serial; each statement will run in parallel WITHIN the process.
 
Joined
Jan 29, 2009
Messages
152
Reaction score
0
I haven't looked into your code in detail, but I'll try and reply on the things I know,
JohnDuq said:
Is there a way to define constants in VHDL?
Yea you declare them like this:
Code:
constant x : std_logic_vector(3 downto 0) := X"1001"; -- 9
(ofcourse any type can be declared like that.)

JohnDuq said:
2. When designing synchronous logic, don't define variables, only define signals. Variables and signals will change on the same clock edge; variables will NOT change value at the end of the process as some of the VHDL tutorials on the web indicate. If you have a signal referencing a variable (or vice versa) in the same process you will get timing violations. Processes in synchronous logic are not serial; each statement will run in parallel WITHIN the process.
It seems you have been confusing signal semantics and variable semantics. As far as I know, it works like this:

  • Variables are updated right at the point where an assignment occurs
  • Assigning a variable to a signal works as expected
  • A signal assignments in a process is special: it is only applied after the process has completed. During the process, referring to the signal returns the original value
  • Assigning a signal to a variable works as expected (that is, the original value should be assigned?)

In case I made a mistake in any of those, please tell!
 
Joined
Dec 9, 2008
Messages
88
Reaction score
0
hi Joris,

Thanks for the info on constants. That works great.

I had thought the variables were causing timing violations; I later realized I hadn't defined my main clock rate properly. I didn't realize this until after I had converted all the variables to signals, so I'll have to revisit this.

In a CPLD the process runs off a single clock, so I believe everything in a process latches at the same time, whether it is a variable or a signal. This makes the actual performance not match the simulation which is not good. ISE could get around this by adding another set of registers that get updated after the rest (or variables are combinatorial and not registered?). I'll investigate this later.

John
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top