UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Visitor micorulez
Visitor
8,497 Views
Registered: ‎07-31-2010

Spartan 3-AN Clock & VHDL

Hi there, 
 
 
I'm actually learning VHDL by reading a book, so far so good. I've been messing around with modelsim in order to simulate some examples from the book.
 
 
Now I'd like to start experimenting something more practical on my Spartan 3-AN development board. 
 
I managed to compile and successfully run simple combinatory logic gates using some onboard switches and LEDs
 
 
The trouble begins as soon as I try to synthesize some sequential circuitry. The following is a behavioral description that works flawlessly in modelsim
 
 
[code] 
library ieee
use ieee.std_logic_1164.all; 
 
entity module is 
    Port ( CLK_OUT : out  STD_LOGIC); 
end module; 
 
architecture Behavioral of module is 
 
begin 
    process 
        variable dummy_var: STD_LOGIC := '0'; 
    begin 
       wait for 10 ns
        dummy_var := not dummy_var
        CLK_OUT <= dummy_var
    end process; 
end Behavioral; 
[/code] 
 
 
Trying to have ISE synthesize the above I get the following error message: 
 
 
Pack:198 - NCD was not produced.  All logic was removed from the design.  This is usually due to having no input or output PAD connections... 
 
 
Ok, what's going on here? 
 
By the way the code I tried to synthesize is missing the wait for line, I thought the FPGA would have introduced a Delta delay itself there, since the clock frequency, of course, is not infinite. 
 
I saw the DCMs inside the FPGA are the ones to deal with the clock, but as far as I understood I don't have to do any configuration there as far as I don't need to modify the CLKIN signal from the board (conditioning, multiplying ecc..), which should be 50MHz in my case. 
 
Do I have to do some sort of configuration for the clock? Do I have to declare something about it in my VHDL source? 
 
 
I know there's a lot of information about this on the internet, but at the moment I'm really lost. 
 
Any hint would be really appreciated. 
 
 
Thanks!

0 Kudos
16 Replies
Explorer
Explorer
8,483 Views
Registered: ‎11-26-2008

Re: Spartan 3-AN Clock & VHDL

The FPGA doesn't know about your 50 MHz clock input unless you actually use the clock input in your code - that is, it is not automagically used by the DCM's, whenever you write some timing specific code. Also remember that a rather large part of the VHDL language only works during simulation, and can't be synthesized (for instance the "wait for 10 ns" statement).

 

A version of you code that would work for synthesis also could be:

 
entity module is 
    Port ( CLK_OUT : out  STD_LOGIC;
           CLK_IN  : in   STD_LOGIC); 
end module; 
 
architecture Behavioral of module is 
begin 
  
process(CLK_IN) variable dummy_var : STD_LOGIC := '0';
begin
if(rising_edge(CLK_IN)) then
dummy_var := not dummy_var; CLK_OUT <= dummy_var;
end if;
end process;
end Behavioral;

 

 Just remember to assign the CLK_IN signal to whatever pin the external oscillator is connected to;)

 

The above code should also work fine in ModelSim, you'll just have to create a clock stimulus on CLK_IN yourself (for instance by rightclicking CLK_IN in the wave-window and choosing 'Clock', then assigning a 20 ns period to simulate a 50 MHz clock).

0 Kudos
Visitor micorulez
Visitor
8,479 Views
Registered: ‎07-31-2010

Re: Spartan 3-AN Clock & VHDL

Thanks sonicwave, that was helpful!

 

Anyway there's still a thing that I really don't manage to understand: what if I have a process with lots of sequential instructions? Do I have to wait for a clock event after each sequential instruction? If not, what's the delay between the actual execution of each one?

 

I believe that a process statement is actually implemented using sequantial state machines. If this is true, the actual delay between each instruction (well, let's say state) should be a function of the clock input of each flip-flop. At first I thought that there is an hard-wired clock line into the FPGA, which drives the clock input of each flip-flop of each slice. Anyway this seems to be wrong, but still, I don't get it :smileysad:

 

 

0 Kudos
Explorer
Explorer
8,470 Views
Registered: ‎11-26-2008

Re: Spartan 3-AN Clock & VHDL

As you can see in the code I posted earlier, the process has a sensitivity list containing the CLK_IN signal (the "process(CLK_IN);" line). It thus runs whenever there is a change to this signal.

 

The first statement in the process, "if(rising_edge(CLK_IN)) then", means that whatever statements are inside this 'if' will only run when a rising edge is detected - which is one of the standard ways to describe a rising-edge triggered flip-flop, running on CLK_IN. The delay between each execution of the process, is thus completely decided by how often you get a rising edge on your clock signal. For other of the standard constructs, try having a look at the language templates inside ISE (Edit -> Language Templates -> VHDL -> Synthesis Constructs -> Coding examples -> Flip Flops).

 

You could also use any other clock signal - from another external oscillator, a derived clock from a DCM, or from your own logic (this is usually not a good idea though ;) ) - instead of CLK_IN in your process, and the synthesizer should route the chosen signal to the clock-port of the flip-flop. There is thus no single hard-wired clock line - instead you have a number of low-skew clock lines, that can be used for routing whatever signals you choose to use as clocks.

 

The FPGA only does exactly what you tell it to! (most of the time at least :P )

0 Kudos
Explorer
Explorer
8,467 Views
Registered: ‎11-26-2008

Re: Spartan 3-AN Clock & VHDL

And by the way, I would probably recommend sticking to signals instead of variables while learning.

 

Signals assigned in a clocked process are always implemented as flip-flops, while the implementation of variables depends on how you use them (if you read the variable before assigning it, it is implemented as a flip-flop, it isn't if you assign it before reading it). It can thus be a bit easier to keep track of how everything works if sticking to signals... Others may have a different opinion on this of course;)

0 Kudos
Visitor micorulez
Visitor
8,463 Views
Registered: ‎07-31-2010

Re: Spartan 3-AN Clock & VHDL

Thank you for your help and your promptness one more time :smileyhappy:

 

To be really honest I still quite don't get a few things about this... Anyway I will try to think it over and do some further testing about the clock and process thing. Shouldn't I understand something, I will get here to ask for a little help :smileyhappy:

0 Kudos
Visitor micorulez
Visitor
8,413 Views
Registered: ‎07-31-2010

Re: Spartan 3-AN Clock & VHDL

Guess what, I'm stuck :smileysad:

 

Well, at first I tried to synthesize the following:

 

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 module is
Port ( CLK_50MHZ : in STD_LOGIC;
CLK_OUT : out STD_LOGIC );
end module;

architecture Behavioral of module is

begin
process (CLK_50MHZ)
variable dummy_var: STD_LOGIC := '0';
begin
if CLK_50MHZ = '1' then
dummy_var := not dummy_var;
CLK_OUT <= dummy_var;
end if;
end process;
end Behavioral;

 

I was expecting a 25MHz square wave output on CLK_OUT pin. Instead of that I get a weird 25MHz wave which looks like a square wave destroyed after passing a low-pass filter, it requires lots of imagination to tell it was born as a square wave.

 

At this point I thought something was wrong with either the FPGA configuration or the board (which is the Spartan 3AN starter kit). I also thought a lower frequency output would have solved (at least attenuated) the problem. As a consequence I tried with the following code (which I tested on modelsim and works great):

 

 

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 module is
Port ( CLK_50MHZ : in STD_LOGIC;
CLK_OUT : out STD_LOGIC );
end module;

architecture Behavioral of module is

begin
process (CLK_50MHZ)
variable dummy_var: STD_LOGIC := '0';
variable scaler: integer := 0;
begin
if CLK_50MHZ = '1' then
scaler := scaler + 1;
if scaler = 20 then
dummy_var := not dummy_var;
CLK_OUT <= dummy_var;
scaler := 0;
end if;
end if;
end process;
end Behavioral;

 

Well, with the above code all I get on CLK_OUT pin is nothing! 

 

Does anybody know what's going on here?

 

 

 

 

 

BTW the following is my UCF file, I guess something could be wrong there too:

 

 

NET "CLK_50MHZ" LOC = "E12"| IOSTANDARD = LVCMOS33 ;
NET "CLK_OUT" LOC = "AA21" | IOSTANDARD = LVCMOS33 | DRIVE = 8 | SLEW = FAST ;
# Define clock period for 50 MHz oscillator
NET "CLK_50MHZ" PERIOD = 20.0ns HIGH 40%;

 

 

 

0 Kudos
Visitor micorulez
Visitor
8,409 Views
Registered: ‎07-31-2010

Re: Spartan 3-AN Clock & VHDL

Nevermind, the problem was the "if (CLK_50MHZ = '1') then", the synthesizer was producing a transparent latch because of that.

Using either "if (CLK_50MHZ'EVENT) and (CLK_50MHZ = '1') then" or the code posted by sonicwave solves the problem.

 

Anyway I don't understand two things:

 

1) Why is a transparent latch such a big deal for the timings? What's wrong with it?

 

2) Why do I have to explicitly write "(CLK_50MHZ'EVENT)" anyways? Shouldn't the process be event-triggered already?

0 Kudos
Explorer
Explorer
8,388 Views
Registered: ‎11-26-2008

Re: Spartan 3-AN Clock & VHDL

There isn't really anything fundamentally wrong with a transparent latch - it's just that you don't have any of those in a normal FPGA, so creating the functionality requires ISE to try to cobble it together from luts and flip-flops ;) (which are available in abundance)

 

The reason for using either "if(rising_edge(clk)) then" or "if(clk'event and clk='1') then" is that this is the established way of describing a flip-flop for any signals that get assigned within the 'if' statement.

 

Also, if you were describing a flip-flop with an asynchronous reset, the code would look like this:

process(clk, reset)
begin
   if(reset='1') then   
      out <= '0';
   elsif(clk'event and clk='1') then 
      out <= in;
   end if;
end process;

						

 

If you lack the "'event" part, and the process loop runs everytime a transition happens on one of the signals in the sensitivity list, what would happen when clk = '1' and reset goes from '1' to '0'? ;)

 

0 Kudos
Teacher eilert
Teacher
8,364 Views
Registered: ‎08-14-2007

Re: Spartan 3-AN Clock & VHDL

Hi microrulez,

VHDL is tricky sometimes.

You already learned that there's only a subset of the language available for synthesis (e.g. no wait for x ns).

But there's even more. Most of the synthesis process is more or less converting simple patterns into predefined macros.

The register examples from sonicwave and much more can be found in the Language Template browser in ISE (click the light bulb icon).

 

The trouble with the latches is, that they are not just sampling at a single time but open a gate for some time. During this time al signal changes are forwarded to the output of the latch. Nowadays, routing delays are in the same range as logic delays, so in a fast circuit this means that a funny (almost unpredictable) signal pattern is generated when you put together some logic, wires and latches at high frequencies. so what you build in your first latch example was some kind of ring oscilator with a 50 MHz enable.

 

Also, forget about delta cycles. They are just a means to organize simulation. even if you are clever enough to write code that takes advantage of it during simulation, it's meaningless in synthesis (as well as sensitivity lists).

 

A simulator is event based (to reduce simulation time) and so processes are startet on events.

To give this a meaning for synthesis, the event-attribute has to be used. Either the old way (clk'event and clk = '1') or the new and better way with the rising_edge function. The function basically does the same thing, but more accurate. While the old condition took everything for an edge, that went to '1' (e.g.  'U'->'1', 'X'->'1' etc) the function just accepts '0'->'1' transitions as valid rising edges for the register.

If it would't be that way, every process would be synchronous, which is not intended. Processes can create combinatorical logic as well.

 

Have a nice synthesis

  Eilert

 

0 Kudos
Visitor micorulez
Visitor
5,586 Views
Registered: ‎07-31-2010

Re: Spartan 3-AN Clock & VHDL

Thank you very much eilert and sonicwave. That information means a lot to me, there are no such things in the book I'm reading (well, in fact that's about generic vhdl and not synthesizable vhdl).

 

 

I think the major problem with learning vhdl modeling is understanding that it's not a programming language (well, at least for me). I really do miss the program counter here :smileyhappy:

 

So anyways today I was trying to get the HD44780-based lcd screen on the board to do something. In the past I used to use this controller on many microcontroller based application, as a consequence I'm trying to implement something that I was doing by software, but now in the FPGA hardware.

 

By the way the code that follows needs a little introduction. delayer is a component that should work like this:

- You set the desired delay value on cycles signal

- You set the go signal high in order to let the counter start

- done signal gets high as soon as the requested amount of cycles has elapsed

- Signal done gets low 3 clk cycles after it went high

 

 

After messing around the whole day I come up with the following:

 

 

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.delayer;

entity hd44780_driver is
port( char: in std_logic_vector(7 downto 0);
write_char: in std_logic;
clear_screen: in std_logic;
clk_50mhz: in std_logic;
busy: out std_logic;
lcd_db: inout std_logic_vector(7 downto 0);
lcd_e: out std_logic;
lcd_rs: out std_logic;
lcd_rw: out std_logic );
end entity hd44780_driver;

architecture behav of hd44780_driver is

component delayer is
port( cycles: in integer;
clk: in std_logic;
go: in std_logic;
done: out std_logic );
end component delayer;

procedure send_nibble (
constant nibble: std_logic_vector(3 downto 0);
signal lcd_db: out std_logic_vector(7 downto 0);
signal lcd_e: out std_logic;
signal lcd_rs: out std_logic;
signal lcd_rw: out std_logic;
signal delayer_cycles: out integer;
signal delayer_done: in std_logic;
signal delayer_go: out std_logic ) is
variable delay_cnt: integer;
begin
lcd_e <= '1';
lcd_db(7 downto 4) <= nibble;

-- allow propagation time
delayer_cycles <= 20;
delayer_go <= '1';
wait until delayer_done = '1';
delayer_go <= '0';
wait until delayer_done = '0';

lcd_e <= '0';

-- allow hold time
delayer_cycles <= 10;
delayer_go <= '1';
wait until delayer_done = '1';
delayer_go <= '0';
wait until delayer_done = '0';

end procedure send_nibble;

procedure send_cmd (
constant cmd: integer range 0 to 16#FF#;
signal lcd_db: inout std_logic_vector(7 downto 0);
signal lcd_e: out std_logic;
signal lcd_rs: out std_logic;
signal lcd_rw: out std_logic;
signal delayer_cycles: out integer;
signal delayer_done: in std_logic;
signal delayer_go: out std_logic ) is
variable delay_cnt: integer;
begin
lcd_rs <= '1';

send_nibble(std_logic_vector(to_unsigned(cmd, 8) srl 4), lcd_db, lcd_e, lcd_rs, lcd_rw, delayer_cycles, delayer_done, delayer_go);
send_nibble(std_logic_vector(to_unsigned(cmd, 4)), lcd_db, lcd_e, lcd_rs, lcd_rw, delayer_cycles, delayer_done, delayer_go);

lcd_db(7 downto 0) <= "ZZZZZZZZ";

-- prevent IO buffers from burning out
delayer_cycles <= 5;
delayer_go <= '1';
wait until delayer_done = '1';
delayer_go <= '0';
wait until delayer_done = '0';

lcd_rs <= '0';
lcd_rw <= '1';

wait until lcd_db(7) = '0';

lcd_rw <= '0';


end procedure send_cmd;


procedure initialize(
signal lcd_db: inout std_logic_vector(7 downto 0);
signal lcd_e: out std_logic;
signal lcd_rs: out std_logic;
signal lcd_rw: out std_logic;
signal delayer_cycles: out integer;
signal delayer_done: in std_logic;
signal delayer_go: out std_logic ) is
variable delay_cnt: integer;
begin
-- 4-bit mode will be used, lcd_db<3:0>
-- signals must be driven High
lcd_db(3 downto 0) <= "1111";

-- allow the hd44780 controller
-- to start up (15 ms)
delayer_cycles <= 750000;
delayer_go <= '1';
wait until delayer_done = '1';
delayer_go <= '0';
wait until delayer_done = '0';

lcd_e <= '0';
lcd_rs <= '0';
lcd_rw <= '0';

send_nibble( "0011" , lcd_db, lcd_e, lcd_rs, lcd_rw, delayer_cycles, delayer_done, delayer_go);

-- allow the hd44780 controller
-- to perform internal functions
delayer_cycles <= 304000;
delayer_go <= '1';
wait until delayer_done = '1';
delayer_go <= '0';
wait until delayer_done = '0';

send_nibble( "0011", lcd_db, lcd_e, lcd_rs, lcd_rw, delayer_cycles, delayer_done, delayer_go);

-- allow the hd44780 controller
-- to perform internal functions
delayer_cycles <= 5550;
delayer_go <= '1';
wait until delayer_done = '1';
delayer_go <= '0';
wait until delayer_done = '0';

-- Config (init)
send_cmd( 16#28#, lcd_db, lcd_e, lcd_rs, lcd_rw, delayer_cycles, delayer_done, delayer_go);
-- Screen Off (init)
send_cmd( 16#08#, lcd_db, lcd_e, lcd_rs, lcd_rw, delayer_cycles, delayer_done, delayer_go);
-- Clear Screen (init)
send_cmd( 16#01#, lcd_db, lcd_e, lcd_rs, lcd_rw, delayer_cycles, delayer_done, delayer_go);
-- Entry Mode setup (init)
send_cmd( 16#06#, lcd_db, lcd_e, lcd_rs, lcd_rw, delayer_cycles, delayer_done, delayer_go);
-- Config for 2 lines LCD and 5x8 dots
send_cmd( 16#28#, lcd_db, lcd_e, lcd_rs, lcd_rw, delayer_cycles, delayer_done, delayer_go);
-- Screen ON, Cursor OFF, Blink OFF
send_cmd( 16#0C#, lcd_db, lcd_e, lcd_rs, lcd_rw, delayer_cycles, delayer_done, delayer_go);

end procedure initialize;

signal delayer_cycles: integer;
signal delayer_go: std_logic;
signal delayer_done: std_logic;

begin
delayer_inst1: delayer port map ( delayer_cycles,
clk_50mhz,
delayer_go,
delayer_done );

process (clk_50mhz)
variable once: bit := '0';
begin
if rising_edge(clk_50mhz)
if once = '0' then
initialize(lcd_db, lcd_e, lcd_rs, lcd_rw, delayer_cycles, delayer_done, delayer_go);
once = '1';
end if;
end if;
end process;
end architecture behav;

 

 

I did this before being aware of the advantages of the rising_edge() function, so in some places the old syntax was used.

Compiling this in the simulator worked (even if I did not simulate it, so it won't do its job for sure), but ISE won't synthesize it. It rejects the code by saing that:

 

Wait statement in a procedure is not accepted.

 

Well, fair enough.

I know the code is long and quite bad. I don't want anybody to give me a working solution, it's not what I'm looking for.

What I'm looking for are instead some comments on the style of modeling by you guys. I'll try to ask some questions:

 

- Is the way I used procedure/functions bad? I know the use of those does not reduce the amount of hardware here, but I thought they would have increased the code readability, but to me it looks like a big mess, passing that many signals...

 

- Is it bad in general to keep doing a top-bottom description of the behaviour of the device like I did (with delays, for example)? I thought that would have resulted in a state-machine, but maybe I should use other ways to describe such a thing?

 

 

 

Thank you for your time already :smileyhappy:

0 Kudos
Historian
Historian
5,571 Views
Registered: ‎02-25-2008

Re: Spartan 3-AN Clock & VHDL

 


@micorulez wrote:

Compiling this in the simulator worked (even if I did not simulate it, so it won't do its job for sure), but ISE won't synthesize it. It rejects the code by saing that:

 

Wait statement in a procedure is not accepted.

 

Well, fair enough.

I know the code is long and quite bad. I don't want anybody to give me a working solution, it's not what I'm looking for.

What I'm looking for are instead some comments on the style of modeling by you guys. I'll try to ask some questions:

 

- Is the way I used procedure/functions bad? I know the use of those does not reduce the amount of hardware here, but I thought they would have increased the code readability, but to me it looks like a big mess, passing that many signals...


 

 

 

No, procedures are not bad -- they can be very useful. But you have to understand that a procedure is "called" and depending on how the code is written, you could end up with a lot of excess code. So, until you are very conversant with HDLs, don't use them.

 

Your LCD interface is better written as a finite state machine.

 

 

 


 

- Is it bad in general to keep doing a top-bottom description of the behaviour of the device like I did (with delays, for example)? I thought that would have resulted in a state-machine, but maybe I should use other ways to describe such a thing?


 

 

I do things both ways. First, i work up a top-down description of the project, which lets me understand the whole picture and what parts are necessary to implement it. Then for actual coding, I do it bottom-up, trying to keep my entities "as small as necessary, but no smaller," and certainly with an eye towards reuse. Consider a project that has several SPI ports. You'll probably end up creating an SPI entity, and depending on your ideas about design granularity, you'll either put the shift registers in their own entities or just put them in the main SPI entity.

 

 

----------------------------Yes, I do this for a living.
0 Kudos
Teacher eilert
Teacher
5,547 Views
Registered: ‎08-14-2007

Re: Spartan 3-AN Clock & VHDL

Hi,

Bassmann already gave you some good hints on your code.

Here's one more.

 

Since you already learned how to use rising_edge, forget about using wait statements in synthesis code.

(In Testbenches it can be very usefull, indeed.)

 

For FSMs there are basic templates in the ISE Language Templates browser. Some better ones may be found in the forum.

 

Now, how do you perform a "wait until signal_x ='1' " in a state machine?

 

Lets assume you have defined a state "WaitForX":

 

 

-- nextstate <= current_state;  --Alternative way to avoid latches in a combinatorical process

case state is

   --...

   when WaitforX => If signal_x ='1' then

                                      nextstate => DoNextThing;

                                  -- else                                    -- avoid latches

                                  -- nextstate => WaitforX ;   -- if in a combinatorical process

                                    end if; -- No else needed if in a clocked process

   when DoNextThing => --...

 

Hope this helps a little too.

 

Have a nice synthesis

   Eilert

 

0 Kudos
Visitor micorulez
Visitor
5,521 Views
Registered: ‎07-31-2010

Re: Spartan 3-AN Clock & VHDL

Hi there!

 

Thank you very much for the precious information :smileywink:

 

I really didn't think designing circuits with an FPGA would have been so exciting, it's real fun!

By the way debugging withouth a logic analyzer is the worst nightmare I've ever had... really, I had difficulties to sleep :smileysad:

 

So anyway, after lots of trouble this is what I got:

 

 

 

Thank you one more time for your help :smileyhappy:

0 Kudos
Explorer
Explorer
5,498 Views
Registered: ‎11-26-2008

Re: Spartan 3-AN Clock & VHDL

Looking good ;)

 

In any case though, have a look at ChipScope for your debugging needs - it's basically a logic analyzer that you stuff into the FPGA together with your design, hook up signals of interest, load everything into your device, and you can then watch the signals on your computer using the JTAG interface.

0 Kudos
Visitor micorulez
Visitor
5,492 Views
Registered: ‎07-31-2010

Re: Spartan 3-AN Clock & VHDL

That sounds awesome! Gonna check it out, thanks for the hint :smileywink:

 

 

PS: Oh my god that's expensive, is there a free limited version or something? I see there's a trial, but I don't like getting used to things which are expected to expire :smileysad:

0 Kudos
Visitor dinesh627
Visitor
2,209 Views
Registered: ‎06-26-2017

Re: Spartan 3-AN Clock & VHDL

sir

i have written the code for simple counter. its working in Xilinx Test bench report and FPGA spartan 3an starter kit.

but when i write the same counter code in using structural programming using D-flipflop as a component. it is okay for vhdl test bench but it is not working FPGA spartan kit.

 

0 Kudos