More VHDL Newbie Questions


craiglindley

Recommended Posts

I'm a long time computer programmer and electrical engineer who is just now trying to understand VHDL and FPGAs. I've got some conceptual hurdles I need to get over before I attempt my first design. Probably everyone who is in this field has had these same questions at some point but I could not find the answers by searching the Internet. I'll illustrate my questions with the following VHDL code snippet:

entity ENTITY is

port (

);

end entity;

architecture rtl of ENTITY is

signal instruction : std_logic_vector( 15 downto 0 );

signal is_alu : std_logic;

begin

process1

begin

line 1;

line 2;

end process1;

is_alu <= ( instruction(15 downto 13 ) = B"011" ) ;

process2

begin

if (is_alu ) then ….

end process2;

end;

I understand that within a process block the lines of code are executed sequentially. And I think I understand that any assignments made to signals within a process block aren't actually visible until the process block has finished (goes into a wait). Is this true?

My other questions are:

1. Do the two process block run in parallel?

2. Does any code within an entity definition get executed except within a process block?

3. For example, is the is_alu signal assignment shown between the two process blocks actually only evaluated when it is referenced in process2 block?

4. Are there any interactions between the process blocks other than those the code I write cause?

5. If process blocks run totally independently and in parallel how does one guarantee ordered execution of the resultant hardware? This is where I'm definitely missing something and it is probably because of my programming background.

6. Is there some rule of thumb about the type and/or scope of the functionaliy contained in a process block?

I'm sure I'll have many more questions but getting answers to these will help alot.

Thanks in advance

Craig Lindley

Link to comment
Share on other sites

Hi Craig.

1. As written, yes - all in parallel. A process is only 'triggered' when a signal on its sensitivity list changes... So it is normal to have

process(clk)

begin

if rising_edge(clk) then

...

end

end if.

This process only runs if 'clk' changes

2. All code outside a process is concurrent.

3. ALU assignment should be something like

process(x,y,mode)

begin

if mode = "00" then

z <= x+y;

elsif mode = "01" then

z <= x AND Y; ...

end if

end process;

That way any time x,y, or mode changes the value in Z will change.

4. Not sure of the question - My answer would be "no" :-)

5. "There is no thread of execution" should be your mantra 8=). A state vector exists, clock ticks, any enabled flip-flops latch current inputs, a new state vector is born and the old one is no more.

6. No, more statements are available within a process block than outside of it (e.g. "IF" and "CASE")

Mike

Link to comment
Share on other sites

I think Mike should have pointed you to his wiki at http://hamsterworks....php/FPGA_course ;) and I recommend any beginner reads it. Also vhdlguru.blogspot.com is another site worth reading.

All processes, in fact all statments whether inside or outside a process occur simultaneously. The way you stop evertything from just happening at once on the FPGA is by synchronizing them to a clock or disabling them through conditional statements, see below.

A process must have a sensitivity list, if you do not provide one, a sensitivity list is created for you during synthesis based on the signals you use inside that process (however such implicit sensitivity lists are ill advised). Normally most simple processes have a clock on the sensitivity list though you can use any signals you want, eg

process(clk) begin

a <= b;

b <= a;

end process;

In the above example, every time the clock clk changes state, eg high-to-low or low-to-high, the signals a and b swap states. This is because the two assignment statements are executed simultaneously (in parallel) *not* sequentially as in a programming language. To try and clarify, if a and b are 8 bit vectors with a := x"12" and b := x"34", the first time clk changes state you end up with a = x"34" and b = x"12", the next time clk changes state you get a = x"12" and b = x"34" again.

In contrast, in any normal programming language a and b would end up having the same value because the two statements would be executed sequentially.

If you only wanted to execute the statements inside a process on certain conditions, you can use if statements, for example:

process(clk, enable) begin

if rising_edge(clk) then

if (enable = '1') then

a <= b;

b <= a;

end if;

c <= d;

end if;

end process;

In this example, clk and enable are on the sensitivity list. Everything inside the process happens on the rising edge of the clock and nothing happens on the falling edge. Furthermore the two assignments a and b occur on the rising edge of clk but only when the enable signal is high as well, otherwise they are not executed whereas c is always assigned a value on the rising edge of clk regardless of the state of enable.

There is no interaction between processes unless you program it in, for example if one process watches b for a certain value and if it sees it, it performes an action, then in a different process you assign values to b, then it is conceivable that the second process could trigger an action in the first process by assigning b a certain value.

One fundamental rule you need to remember is that you can not assign a value to a signal in two different processes as that will throw a multiple assignment error at synthesis. You can read the same signal in as many processes as you want but you can only assign it a value in one and only one process.

Another fundamental rule is that you cannot perform one action on the rising edge of the clock and a different action on the falling edge of the same clock in the same process. This for example would not work in VHDL:

-- this is not possible

process(clk) begin

if rising_edge(clk) then

a <= b;

elsif falling_edge(clk) then

b <= a;

end if;

end process;

-- but this is

process(clk) begin

if rising_edge(clk) then

a <= b;

end if;

end process;

process(clk) begin

if falling_edge(clk) then

b <= a;

end if;

end;

Finally, an easy way to think about statements in a process and statments outside a process, is this: statements in a process are "synchronous" or "clocked", in other words they occur synchronous to a change in one of the signals on the sensitivity list. Statements outside a process are "asynchronous" and they occur "whenever" or if you prefer, "immediately".

In your example "is_alu" is *always* evaluated, but of course it only changes the instant "instruction" changes. As soon as "instruction" takes on a new value, then "is_alu" also takes that value a instant later. This "instant later" is not in fact instantaneous, it is on the order of a few nanoseconds or even picoseconds and depends on the propagation delay of the signal from "instruction" through the gates to "is_alu" which is dependent on the speed rating of your FPGA chip. You always need to keep in mind propagation delays, even though most lay people tend to think that things just happen instantly.

Since everything in an FPGA happens in parallel, one way to ensure that certain actions occur in a defined sequence is to impement a state machine. The most basic state machine is a counter that counts up sequentially then perhaps stops at a maximum value or rolls over. Then you would have a case statement such as "when counter is 1 do i", "when counter is 2 do j", "when counter is 3 do k", where i, j, k etc are blocks of statments. In this way you are guarranteeing that when the counter counts up, i occurs before j and j occurs before k.

Another type of more complex state machine is one where the current state dictates what the next state is, possibly based on additional inputs. This state machine can jump from any state to any other state depending on calculations it performs or external stimuli. One such example of a state machine is a microprocessor. Each instruction it executes, moves it from one state to another, based on the contents of its registers and data it reads from external memory or ports.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.