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

Need advice about coding style

Altera_Forum
Honored Contributor II
3,550 Views

Hello I'm Alex and I am novice for VHDL coding. if my english awful pls forgive me. 

I trying to understand VHDL PROCESS statement. I try with 1bit full adder with carry save function in Quartus2 v15. 

I write down code:LIBRARY IEEE; USE IEEE.std_logic_1164.ALL; -- truth-table of full-adder -- with three inputs: ci{carry_in}, a{first in} and b{second in} -- and two ouputs: s{sum} and co{carry_out} -- ci a b | s co -- ----------------- -- 0 0 0 | 0 0 -- 0 0 1 | 1 0 -- 0 1 0 | 1 0 -- 0 1 1 | 0 1 -- 1 0 0 | 1 0 -- 1 0 1 | 0 1 -- 1 1 0 | 0 1 -- 1 1 1 | 1 1 ENTITY full_add_1bit IS PORT ( ci : IN STD_LOGIC; a : IN STD_LOGIC; b : IN STD_LOGIC; s : OUT STD_LOGIC; co : OUT STD_LOGIC ); END full_add_1bit; ARCHITECTURE b OF full_add_1bit IS BEGIN p0 : PROCESS(ci, a, b) VARIABLE aab, aob, axb, sxc : STD_LOGIC; BEGIN aab := a AND b; axb := a XOR b; sxc := axb XOR ci; s <= sxc; IF ci = '0' THEN co <= aab; ELSIF ci = '1' THEN aob := axb XOR aab; -- the same as (a OR b) co <= aob; END IF; END PROCESS p0; END b; 

but during compilation i recieves message  

 

--- Quote Start ---  

Warning (10631): VHDL Process Statement warning at full_add_1bit.vhd(30): inferring latch(es) for signal or variable "co", which holds its previous value in one or more paths through the process 

--- Quote End ---  

 

I follow the simple logic - let's compute new values then do all signal assignments and the question is 

question1 : does pressure on variables so need?! 

I rewrite architecture to new one, let's compiler do all work: 

ARCHITECTURE b1 OF full_add_1bit IS BEGIN p0 : PROCESS(ci, a, b) VARIABLE result_i : INTEGER; VARIABLE result_v : STD_LOGIC_VECTOR (0 TO 1); BEGIN result_i := CONV_INTEGER(a)+CONV_INTEGER(b)+CONV_INTEGER(ci); result_v := CONV_STD_LOGIC_VECTOR (result_i, 2); co <= result_v(0); s <= result_v(1); END PROCESS p0; END b1; 

Finally i make schematic for this with 2mux1 blocks as for fun... in the attachments.  

never use schematic for establishing any equation - you waste your time

But result is the same with that scheme. 

question 2: how to find the way to good coding style?
0 Kudos
31 Replies
Altera_Forum
Honored Contributor II
924 Views

I have two examples of code for two registers writing from one bus. Which example is more suitable? 

the first implementation 

reg_n : process(r, clk, wrn) variable t : unsigned(n'range); begin if r = '1' then t := to_unsigned(0, t'length); elsif rising_edge(clk) then if wrn = '1' then t := resize(d, t'length); end if; end if; n <= t; end process reg_n; reg_k : process(r, clk, wrk, wrn) variable t : unsigned(k'range); begin if r = '1' then t := to_unsigned(0, t'length); elsif rising_edge(clk) then if wrk = '1' and wrn = '0' then t := resize(d, t'length); end if; end if; k <= t; end process reg_k; 

and the second implementaion 

reg_n : process(r, wrn, wrk) variable t : unsigned(n'range); begin if r = '1' then t := to_unsigned(0, t'length); elsif rising_edge(wrn) then if wrk = '0' then t := resize(d, t'length); end if; end if; n <= t; end process reg_n; reg_k : process(r, wrk, wrn) variable t : unsigned(k'range); begin if r = '1' then t := to_unsigned(0, t'length); elsif rising_edge(wrk) then if wrn = '0' then t := resize(d, t'length); end if; end if; k <= t; end process reg_k;
0 Kudos
Altera_Forum
Honored Contributor II
924 Views

Neither. Why bother using variables at all. You could just sign directly to k or n? Also the codes are not functionally equivalent so you cannot compare them. 

 

Also, assigning signals outside the clocked part or the code is not a recommended style.
0 Kudos
Altera_Forum
Honored Contributor II
924 Views

okay . the second is very bad . You should await that signals comes like clocks - nonsense.  

what for the first style, your should capture Enable signal before clock transtion or signal should be stable for clock-period. or must i put multiplexor on data-in? 

 

Why I bother vaiables? I follow examples that books and web provide. <- it is common convention :) 

It seems that i 've alraedy asked similar question. I don't remember where...
0 Kudos
Altera_Forum
Honored Contributor II
924 Views

If the examples you are looking at look anything like your code above, I highly suggest you ditch those as very poor examples. There is hardly ever a situation where a variable is required in synthesisable logic. Variables can have issues of you use them wrong that you don't get with signals. Variables are best avoided. 

 

I can't comment on the code about whether you need mixing our anything. I have no idea on the specs of the design. But you should try and register all outputs.
0 Kudos
Altera_Forum
Honored Contributor II
924 Views

The sensitivity list for a clocked process should only contain the clock and the reset signals. If you add the wrn and wrk signals to the list, you will create a design that will behave differently in a simulator and on a real FPGA. Quartus will ignore your sensitivity list and just synthesize as if it was (r, clk) so if you want to simulate it correctly in Modelsim you should write it as is in your code.

0 Kudos
Altera_Forum
Honored Contributor II
924 Views

 

--- Quote Start ---  

The sensitivity list for a clocked process should only contain the clock and the reset signals. If you add the wrn and wrk signals to the list, you will create a design that will behave differently in a simulator and on a real FPGA. Quartus will ignore your sensitivity list and just synthesize as if it was (r, clk) so if you want to simulate it correctly in Modelsim you should write it as is in your code. 

--- Quote End ---  

 

 

If it is a synchronous process, and you add all the signals in the file, it will still behave like a synchronous process, and will still synthesise to a synchronous process, and the synthed design and the simulation will match. 

All adding all the extra signals does is cause the simulator to trigger the process when any of the signals changes. But because stuff doesnt actually happen unless there is a rising edge of the clock, nothing actually changes inside the process. 

 

So all you do is add extra work for the simulator to do to action the process when nothing actually happens inside the process.
0 Kudos
Altera_Forum
Honored Contributor II
924 Views

 

--- Quote Start ---  

The sensitivity list for a clocked process should only contain the clock and the reset signals. If you add the wrn and wrk signals to the list, you will create a design that will behave differently in a simulator and on a real FPGA. Quartus will ignore your sensitivity list and just synthesize as if it was (r, clk) so if you want to simulate it correctly in Modelsim you should write it as is in your code. 

--- Quote End ---  

 

I have tried to remove one and with standard option set the quartus reports me that i should include them in process-sensitivity list xD 

and if you want trully asyncronus modeling -> let's enter the process, stop it through breakpoint in statements for clock transition, then manually change signal 'r' value to one that send command reset to your schematic. and wait when the reset occur . will we have glitch?
0 Kudos
Altera_Forum
Honored Contributor II
924 Views

How about such cutting for sensitivity list when describing FSM? I know that is very badexample with impure function instead of process but ... quartus eats it up. 

library ieee; use ieee.std_logic_1164.all; entity fsm is port( clk, enable_SM, start, pk_eq_k, pn_eq_n : IN std_logic; pk0, pkp1, pn0, pnp1 : OUT std_logic ); end fsm; architecture v1 of fsm is type state_type is (s1, s2, s3, s4); impure function next_state(st : state_type) return state_type is begin case st is when s1 => if start= '1' then return s2; else return s1; end if; when s2 => return s3; when s3 => if pk_eq_k = '0' then return s3; else return s4; end if; when s4 => if pn_eq_n = '0' then return s4; else return s2; end if; end case; end next_state; signal st : state_type; begin process(enable_SM, clk) begin if enable_SM = '0' then st <= s1; elsif rising_edge(clk) then st <= next_state(st); end if; end process; pk0 <= '1' when (st = s1 or (st = s4 and pk_eq_k = '1')) else '0'; pkp1 <= '1' when st = s3 else '0'; pn0 <= '1' when st = s2 else '0'; pnp1 <= '1' when st = s4 else '0'; end v1; 

 

The code above ... struck me so / really assignment to signal operators imply implicit processes . so i change a little bit behaviour to fsm 

architecture v2 of fsm is type state_type is (s1, s2, s3, s4); signal st : state_type; procedure state_transition is begin case st is when s1 => if start= '1' then pk0 <= '1'; st <= s2; else pk0 <= '0'; st <= s1; end if; pkp1 <= '0'; pn0 <= '0'; pnp1 <= '0'; when s2 => pn0 <= '1'; pkp1 <= '1'; pk0 <= '0'; pnp1 <= '0'; st <= s3; when s3 => if pk_eq_k = '0' then pk0 <= '0'; pkp1 <= '1'; pnp1 <= '0'; st <= s3; else pk0 <= '1'; pkp1 <= '0'; pnp1 <= '1'; st <= s4; end if; pn0 <= '0'; when s4 => if pn_eq_n = '0' then pnp1 <= '1'; st <= s4; else pnp1 <= '0'; st <= s2; end if; pkp1 <= '0'; pn0 <= '0'; pk0 <= '0'; end case; end state_transition; begin process(enable_SM_n, clk) begin if enable_SM_n = '1' then st <= s1; pn0 <= '0'; pkp1 <= '0'; pk0 <= '0'; pnp1 <= '0'; elsif rising_edge(clk) then state_transition; end if; end process; end v2; 

but all is fine until you you catch multiple assignments. 

 

by the way ... (why my rang became as written? is it joke?)
0 Kudos
Altera_Forum
Honored Contributor II
924 Views

I dont understand the questions, both processes and code examples imply synchronous code. But the first example as asynchronous outputs while the 2nd is all registered outputs...

0 Kudos
Altera_Forum
Honored Contributor II
924 Views

Tricky , you shed the light for me. seriously. 

the both state machines are Melay machine. I know a lot of about state machines from theory. 

it is better to follow style with two separate processes for describing fsm. so model and synthesis will be similar. 

be aware : you can get unexpected clock-enable pins instead of asynchronus reset with styles as above.
0 Kudos
Altera_Forum
Honored Contributor II
924 Views

yes - you get that because you didnt reset all output in the async reset branch. 

 

The prefered style for state machines now is a single clocked process. This avoids any latch creation and can be easier to track. The two process style is a throwback to very old synthesis engines that required separated logic and register processes. And so many textbooks taught this style. Now there is no restriction there is no need to separate logic and registers.
0 Kudos
Reply