# Inequality outside of process (in when statement?) (VHDL)

I am rewriting a VGA controller in (I hope) a better way; I have a 'blank' signal which means that the current pixel is outside of the visible area, and I have the gut feeling it would be better to branch that signal outside of the "pixel processing" process (race conditions?).

I am trying to translate something like this:

-- Horizontal procedure:
h_proc : process(pix_clk)
begin
if(rising_edge(pix_clk)) then
-- counts the pixel clocks
h_cnt <= h_cnt + 1;
-- updates the blank signal (whether in visible area or not)
if(h_cnt <= HRES and v_cnt <= VRES) then
blank <= false;
-- generates synchronisation signals
else
blank <= true;
if(h_cnt > HRES+HFP and h_cnt < HRES+HFP+HSP) then
h_sync <= '0';
else
h_sync <= '1';
end if;
end if;
end if;
end process;


Into this:

blank <= false when h_cnt <= HRES and v_cnt <= VRES, else false;
-- And while I'm at it
h_sync <= '0' when h_cnt > HRES+HFP and h_cnt < HRES+HFP+HSP, else '1';


But I end up with a syntax error. Isn't there any way of branching test on inequalities such as greater than / less than outside of processes?

Modified code Inside the architecture:

-- blank is true outside of the visible area (where synchronisation pulses are sent and black is needed)
blank <= false when h_cnt <= HRES and v_cnt <= VRES else true;

-- Address of the pixel (block of memory containing the color of the pixel)
when blank = false else (others => '0');

-- Colors returned correspond to the aimed pixel, but black if out of the visible area
R <= buffer_data(RDEPTH+GDEPTH+BDEPTH-1 downto GDEPTH+BDEPTH) when blank = false else (others => '0');
G <= buffer_data(GDEPTH+BDEPTH-1 downto BDEPTH) when blank = false else (others => '0');
B <= buffer_data(BDEPTH-1 downto 0) when blank = false else (others => '0');

-- Synchronisation pulses
h_sync <= '0' when h_cnt > HRES+HFP and h_cnt < HRES+HFP+HSP else '1';
v_sync <= '0' when v_cnt > VRES+VFP and v_cnt < VRES+VFP+VSP else '1';

-- Counter update procedure:
h_proc : process(pix_clk)
begin
if(rising_edge(pix_clk)) then
-- counts the pixel clocks, update the line counts and reset the counters when appropriate
if(h_cnt = HRES+HFP+HSP+HBP) then
h_cnt <= 0;
if(v_cnt = VRES+VFP+VSP+VBP) then
v_cnt <= 0;
else
v_cnt <= v_cnt + 1;
end if;
else
h_cnt <= h_cnt + 1;
end if;
end if;
end process;


Your approach is perfectly legal. The commas are not, however. Getting rid of them should solve your problem, unless there are other issues that are not clear from the code you posted.

Note that there are side-effects to moving your code out of a clocked process, though - the value of blank will change 1 clock earlier, and your timing performance will be worse. Make sure your design can sustain these changes.

Be aware also that the logic for h_sync is not equivalent (though this may actually be an improvement) - in the clocked process, h_sync is not assigned a value in every branch of the if-block, and it appears that it could get stuck at '0' for certain values of HFP, etc. In the concurrent assignment, its value is always explicitly assigned.

### brief tutorial on sequential signal assignment

The canonical way of thinking about VHDL processes is that signals are not updated until the process suspends (which, for a clocked process, is at the end of the process). It may be helpful to realize that clocked processes are meant to represent physical registers and actual signal propagation. Either way, if you are assigning multiple interdependent signals in clocked processes, the value can only "advance" one signal at a time on each clock edge.

So consider the following code:

(A)

process (clk)
if rising_edge(clk) then
foo <= foo + 1; -- if value is becoming N this clock cycle...
if foo = N then -- value is still N-1 here - signal has not updated yet
bar <= '1';
else
bar <= '0';
end if;
end if;
end process;


(B)

process (clk)
if rising_edge(clk) then
foo <= foo + 1; -- if value is becoming N this clock cycle...
end if;
end process;

bar <= '1' when foo = N else '0'; -- assigned concurrently, so value is already N here


In (A), foo is not updated until the end of the process. On the clock cycle when foo becomes N, it hasn't been updated when the "if" check is done, so the value of bar will not change. bar will change 1 clock later, since on that iteration of the process, foo will have been updated to equal N.

In (B), bar is not assigned in a clocked process, and therefore will be updated as soon as foo changes (after some logic delays in the real world, of course).

Does that help?

• Thanks for the quick answer. I was misled by the fact that the "with XXXX select XXXX when XXXX, XXXX when others" had a comma and syntax errors are so explicit... I uploaded the modified code. You spotted h_sync right, however in that particular code due to the front porch just before the pulse the waveform should have been correct (normally). – Mister Mystère Apr 21 '14 at 18:58
• HOWEVER, I am puzzled about that way being worse for 'blank': I thought signals were changed at the end of the process, so still after one clock cycle? Because I understood that in a process 'foo <= foo + 1; if(foo = N) then ... end if;' would trigger the if an iteration after what's expected!? – Mister Mystère Apr 21 '14 at 19:01
• I assumed h_sync probably wouldn't actually be in issue, but I thought I would mention it just in case. The change to timing performance and sequencing is the more significant one. – fru1tbat Apr 21 '14 at 19:04
• I'm not saying it's better - there are several factors to consider. Above you said "signals [are] changed at the end of the process" - this is correct. Here you say it's "executed sequentially". These two statements are in conflict. See my attempted brief tutorial above for more information, and let me know what you're having trouble with. – fru1tbat Apr 21 '14 at 19:53
• That's one way to say it, yes. I usually think of it as the signal assignment being "deferred" until the end of the process, as this makes visualizing actual hardware easier for me. Keep in mind that this is only true for signals, though; variables are updated immediately. – fru1tbat Apr 22 '14 at 15:10