Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
17241 Discussions

VHDL Variables: Is it combinational code inside a clocked process?

Altera_Forum
Honored Contributor II
11,797 Views

Hello all 

 

Since the VHDL variables topic strikes as a little bit odd even to VHDL designers who have some experience I would like to ask about VHDL variables in order to clarify a few things. 

 

If we have the usual case of register A feeding register B through some combinational logic (registers in same clock domain) then, until now,when I needed to make some complicated combinational code to represent the combinational code between the two registers, I used to do it in another non-clocked process having as inputs the outputs of register stage A and the outputs of the combinational code feeding the input of register stage B. Then inside the clocked process of stage B assign the values of the input. 

 

I was wondering, in order to make the code more readable and maintanable, is it possible to use variables to implement the complicated combinational code inside the clocked process so that I do not have to use another non-clocked process? 

 

Since I havent found somewhere a clear answer about the use of variables, I wanted to ask, is that the purpose of existence of VHDL variables? Do variables exist in order simplify the writing of combinational code inside a clocked process? 

 

Note: If I used signals inside the clocked process to help me store intermediate results,that would lead to register inference which is not intended if the designer wants to implement pure combionational code inside the clocked process.
0 Kudos
25 Replies
Altera_Forum
Honored Contributor II
1,452 Views

 

--- Quote Start ---  

Yes you are right. I tried it too. 

 

In general my problem is to be able to create one solid process per logic entity with complex combinational logic that could also be exported out of the process as asynchronous signals to be used for other processes. In order to achieve that I suppose I have to use variables that get assigned outside the clocked if (but also read but not assigned inside the clocked if) and when I need to export them I can assign the variables-to-be-exported to signals but outside the clocked if. 

 

Another question is that maybe inside the clocked process I need to make a variable assignment. Is it possible to split the clocked if in two (so have two if(rising edge)) inside the same process and in between make asynchronous variable assignments? 

 

process(clk) variable t1 : std_logic; variable t2 : std_logic; begin t1 := A and B; if rising_edge(clk) then Yb <= t1; end if; Y <= t1 XOR Yb; t2 := A or B; if rising_edge(clk) then Yc <= t2 OR Y; end if; end process;  

 

Is this mixture possible? 

--- Quote End ---  

 

Yes, but the two 'if rising_edge' constructs will be mapped to the same clock. 

In fact you can write it also as:process(clk,A,B,Yb) variable t1 : std_logic; variable t2 : std_logic; begin t1 := A and B; Y <= t1 XOR Yb; t2 := A or B; if rising_edge(clk) then Yb <= t1; Yc <= t2 OR Y; end if; end process; 

Note that I added Yb to the sensitivity list (because Y depends on it)
0 Kudos
Altera_Forum
Honored Contributor II
1,452 Views

 

--- Quote Start ---  

 

 

Another question is that maybe inside the clocked process I need to make a variable assignment. Is it possible to split the clocked if in two (so have two if(rising edge)) inside the same process and in between make asynchronous variable assignments? 

 

process(clk) variable t1 : std_logic; variable t2 : std_logic; begin t1 := A and B; if rising_edge(clk) then Yb <= t1; end if; Y <= t1 XOR Yb; t2 := A or B; if rising_edge(clk) then Yc <= t2 OR Y; end if; end process;  

 

Is this mixture possible? 

--- Quote End ---  

 

 

according to JosyB any coding style accepted by tools should be ok and I agree. 

Your code may work for what you want but then one will ask why not use signal instead of variable t1 since it is outside clock edge and hence combinatorial (always).
0 Kudos
Altera_Forum
Honored Contributor II
1,452 Views

Since I started this thread I would like to wrap up. 

 

Until now, when I wanted to make a logic entity which includes complex combinational process between two register stages - plus having the flexibility to export some of the combinational logic to other processes - I had to create many combinational processes inside an entity which use the same signals together with the clocked processes. This created the following problems: 

 

- Difficult readability of the file due to the existence of many processes making it difficult to easily see how they interconnect. 

- Signal declaration flooding. Many signals that were used to interconnect combinational code with its respective clocked processes were unnecessarily declared on the top of the file rather than inside the process when they were only there used. 

- More writing effort due to writing repeated code (naming processes, using the same keywords, etc) 

- Unmodularity of the code. If i wanted to change a small detail in the code I should change it in more places than if the logic entity was inside one process. 

 

So I created an example that successfully uses variables (both combinational and registered, depends on where you assign it and where you read it) in only one process, representing a "complex" logic function with many register stages and combinational code and also having the flexibility to export any stage of the combinational code as asynchronous and not registered (if chosen could be also exported as registered). 

 

So in order to implement the following function: 

 

https://www.alteraforum.com/forum/attachment.php?attachmentid=9057  

 

I needed to implement the following code: 

 

library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity exportcombvariable is port(clock : in STD_LOGIC; A, B, C, D : in STD_LOGIC; Y, Y1,Y2,Y3,Y4: out STD_LOGIC ); end exportcombvariable; architecture rtl of exportcombvariable is begin process(clock,A,B,C) variable t1 : STD_LOGIC; variable t2 : STD_LOGIC; variable t3 : STD_LOGIC; variable t4 : STD_LOGIC; variable r_Y1 : STD_LOGIC; variable r_Y2 : STD_LOGIC; variable r_Y3 : STD_LOGIC; variable r_Y4 : STD_LOGIC; begin t1 := A AND B; if(rising_edge(clock)) then r_Y1 := t1; end if; if(rising_edge(clock)) then r_Y3 := D; end if; t2 := t1 AND r_Y1 AND C; if(rising_edge(clock)) then r_Y2 := t2; end if; t3 := t2 XOR r_Y2; t4 := t3 AND r_Y3; if(rising_edge(clock)) then r_Y4 := t4; end if; --Export section Y1 <= t1; Y2 <= t2; Y3 <= t3; Y4 <= t4; Y <= r_Y4; end process; end rtl;  

 

which produced the following RTL structure: 

 

https://www.alteraforum.com/forum/attachment.php?attachmentid=9058  

 

Which shows that all the internal to the process signals (whether registered or combinational) are declared as variables inside the process and depending on where they are assigned or/and read they infer registers or not. Also there is the flexibility to export whichever part of the diagram whether coombinational or not at the export section. In that section one uses declared (at the top of the file) signals that can be used by other processes. 

 

In this way the entirety of the logic stays inside one process making it easier to read and understand (one could also use only one clocked if(risingedge) block instead of many that I used, but I did that to show the logic continuity of the actions inside the process), variable naming scope also stays inside the process so one could reuse the process and export the same parts of the logic with different signal names,so that makes it modular, and last but not least it is much easier to modify, add or remove logic from the process without having to rewrite a lot of code (keywords or unique) and waste valuable time. 

 

Finally I grasped a big part of the meaning and use of variables in VHDL and I saw not only how useful they are but also how invaluable they can prove to the designer if he is making reusable modular code. 

 

Thanks a lot to kaz, josyb,FvM, and aprado for the contributions.
0 Kudos
Altera_Forum
Honored Contributor II
1,452 Views

Is there any way to force an error if a 'variable' ends up being a register? 

Otherwise the only way to tell seems to be to inspect the RTL viwer.
0 Kudos
Altera_Forum
Honored Contributor II
1,452 Views

 

--- Quote Start ---  

Is there any way to force an error if a 'variable' ends up being a register? 

--- Quote End ---  

 

Luckily not, I'd say :) 

The question, IMHO, indicates you have to study the 'nature of variables' a bit deeper.
0 Kudos
Reply