Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] My Clock is not Working!

Status
Not open for further replies.

Jaraqui

Newbie level 5
Joined
May 30, 2011
Messages
8
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,367
Hi,

I need to build in VHDL a clock generator.

The inputs and output of my circuit are:
  • input reset ('1' sensitive);
  • input master clock (Digilent Basys 2 board oscilator); and
  • output clock.

I present to you two versions of my vhdl code. One with shared variable and other without it.
These two versions were submitted to the same testbench file.
These three files are attached to this post.

Any help of what is wrong will be appreciated.

Regards
Jaraqui
 

Attachments

  • my_clock_with_shared.pdf
    6 KB · Views: 97
  • my_clock_without_shared.pdf
    6 KB · Views: 94
  • tb_my_clock.pdf
    4.9 KB · Views: 104

Because state is a shared variable. It will assign clk the value of state at the start of time, and there is no other event to trigger a change in the clock output. It works fine in your other version with a normal variable.

I assume you're a beginner. So the way to fix this is only ever use signals until you fully understand how variables work. And never use shared variables (you almost never need shared variables in synthesisable code, and you dont usually need them in testbenches either).

So convert all your variables to signals, and your life will be easiest and less error prone.
 
Hi Tricky,

Fisrt of all, thank you for your reply!

Yes, I suspect that I will be a beginner forever... :)

I was reading exactly about signals vs variables (PEDRONI, 2010, p. 177-198). There is a full chapter to treat the differences between them. Obviously I am making a mistake that is result of misinterpretation of the book. Let me describe for you and other people that are interested in this conversation. Your help (already is) will be very important.

If you agree, let´s talk about the codes separately.

Regarding the code with shared variables

What was my inspiration for the code with shared variable:
  • a variable receives instantaneously a value assigned to it (___, p. 181);
  • a shared variable can be assined to other signals belonging to other processes or even concurrent code, but needs to be updated only in one
    place (___, p. 179); and
  • a new value can be assigned to a signal at the end of a process cycle (___, p. 182).

Based on these three considerations, I did not understand why the testbench result didn´t present the 1 MHz clock.

Regarding the code without variables

What was my inspiration for the code without variable:
  • angry because the first case didn´t work :);
  • a variable receives instantaneously a value assigned to it (___, p. 181);
  • a new value can be assigned to a signal at the end of a process cycle (___, p. 182).

Based on these three considerations, I did not understand why the testbench result didn´t present the 1 MHz clock. Yes, this second version didn´t work too!

A Code without the 'state' variable

I present you a third version without the 'state' variable.
This code was submitted to the same testbench file presented in my previous post.
It is not working too...


It´s just an ordinary clock generator... I can´t believe... lol.


Thank you
Best Regards
Jaraqui
 

Attachments

  • my_clock_without_state_variable.pdf
    5.8 KB · Views: 88

1. Ok, you also need to learn how VHDL works as a language. A signal can only be updated when a process suspends. A process is also only run when a signal in the sensitivity list is updated. An assignment to a signal outside of a process is really just a process that is sensitive to all the signals on the RHS. In a sensitity list, it waits for a 'event to occur on one of the signals. So lets consider some code:

Code:
signal a, b : std_logic;

a <= b;

this is the equivolent of writing

process(b)
begin
  a <= b;
end process;

So now you see the problem. The shared variable cannot have a 'event, so it cannot be placed in a sensitivity list, hence it cannot update a signal outside of a process using a shared variable.

2. This code works just fine, and generates your output clock. If you want it at 1MHz, you'll have to get the specs correct. It currently generates a 50Hz clock. Ill leave you figure out why :)

3. See 2. Its a 50Hz clock.

The overall problem with using variables is placement in the code is key because of the rules you just read. Whereas with signals, you're more likely to get what you expect in terms of registers. A good guide when learning is to use variables for combinatorial logic and signals for registers. look at this code:

Code:
process(clk)
  variable a,b,c,d : std_logic;
begin
  if rising_edge(clk) then
    a := ip
    b := a;
    c := b;
    d := c;
    op <= d;
    
    --is exactly the same as writing:
    
    op <= ip;
  end if;
end process;

Now conside the same with signals:

Code:
process(clk)  
begin
  if rising_edge(clk) then
    --Order of assignemnts is irrelavent for signals
    c <= b;
    a <= ip;
    op <= d;
    b <= a;
    d <= c;
    
    --is the same as writing:
    
    op <= d;
    d := c;
    c := b;
    b := a;
    a := ip;
    
    --But the order is very important
  end if;
end process;

So, especially as a beginner, I would recommend only ever using signals. I probably use signals about 95% of the time - it makes life much easier when working out whats a register and what's not. This is not programming - its hardware DESCRIPTION.

On another note, you would definatly NOT generate a clock using logic on an FPGA. It is prone to all sorts of timing issues. Its much better to generate clock enables instead and use the system clock for everything.

- - - Updated - - -

On another side note, please stop posting code in PDF files - its very annoying. Use the code or syntax tags instead.
 
Hi Tricky,

Thank you. Codes 2 and 3 did run fine.

Here is a fix in code 2, inspired on your hint, to allow f_clk express the desired frequency to be generated (now using your suggestion about code presentation here). This fix was also used in code 3.

Code:
library ieee;
use ieee.std_logic_1164.all;

entity my_clock is
   generic( f_osc: integer := 50_000_000;
	         f_clk: integer := 1_000_000);
	port(    mclk:  in std_logic;
		       rst:  in std_logic;
				 clk: out std_logic);
end entity;

architecture arch of my_clock is
begin
   process(mclk, rst)
	   variable counter: integer range 0 to f_osc := 0;
		variable state: std_logic := '0';
		variable f_clk_int: integer := f_osc / f_clk;
	begin
	   if(rst = '1') then
		   counter := 0;
		elsif(mclk'event and mclk = '0') then
		   counter := counter + 1;
			if(counter < f_clk_int / 2) then
			   state := '0';
		   elsif(counter >= f_clk_int / 2) then
			   if(counter = f_clk_int) then
		         counter := 0;
		         state := '0';
		      else state := '1';
				end if;
		   end if;
		end if;
		clk <= state;
	end process;
end arch;

I am just practicing these concepts. When I will use clock sources, your recommendation regarding the use of logic will be considered.

Allow me talk to you (and others interested) a little bit more about shared variables, for the sake of praticing.

Forgetting my code "1" (with shared variable) for a few moments and consider the example below.

Code:
------------------------------------------------------
entity counter_with_sharedvar is
   port (clk: in bit;
         digit1, digit2: out integer range 0 to 9);
end entity;
------------------------------------------------------
architecture counter of counter_with_sharedvar is
   shared variable temp1, temp2: integer range 0 to 9;
begin
----------------------------------
   proc1: process (clk)
   begin
      if (clk'EVENT and clk='1') then
         if (temp1=9) then
            temp1 := 0;
         else
            temp1 := temp1 + 1;
         end if;
      end if;
   end process proc1;
----------------------------------
   proc2: process (clk)
   begin
      if (clk'EVENT and clk='1') then
         if (temp1=9) then
            if (temp2=9) then
               temp2 := 0;
            else
               temp2 := temp2 + 1;  
            end if;
         end if;
      end if;
   end process proc2;
----------------------------------
   digit1 <= temp1;
   digit2 <= temp2;
end architecture;

This code is a copy-paste example of a book (PEDRONI, 2010). Testing this code it isn´t running (in simulation) too!
I´ve tried with VHDL´93 and VHDL´200X.

Based on your explanations in your previous post, the cause that allow consider this code wrong is the same as my code "1"?

Best Regards
Jaraqui
 
Last edited:

that is correct, there is no event that will cause digit1 and digit2 to update. The best part about this is that if you synthesised it, it would probably work as you expected, as synthesisors will just wire it all together.
The only place where you might need to use a shared variable over a signal is when you're trying to infer a ram with write-before_read behaviour, rather than the default read-before-write.
 
Topic solved.

Thank you.
Best Regards
Jaraqui
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top