to make such constructions more readable i typically define something like:
'define nextstate duration <= duration - 1
so i can write
`nextstate;
That's supported only with Verilog, not VHDL.
But I wonder -- if each state has its own timer, will the synthesizer be smart enough to optimize them into one, or will you end up with one counter per state that has that `define?
don't tell me vhdl does not have something like a 'define' or macro capability. One more reason not to use that sadomasochistic horrorshow of a language ...
For delays i create macros that would load a value on a counter
`define after system_ticks[15:0] <=
`define goto if (system_ticks==0) state <=
`define goto_next state <= state +1
`go (system_ticks ==0)
...
always@(posedge clk) begin
// note that this tick counter here needs to be ABOVE the state machine so we can override the counter value
if (tick) begin
system_ticks <=system_ticks -1;
if (system_ticks ==0) system_ticks <=0;
end
end
select case state
case 1
if `go begin // unrolls to if (system_ticks==0) begin
`after 1000; // unrolls to: system_ticks[15:0] <= 1000;
`goto `some_state; // unrolls to : if (system_ticks==0) state <= `some_state;
// or `goto_next;
end
case 2
if `go begin
....
end
keep in mind that the 'after' only executes once the state has transistioned. essentially you are telling the system : do this bunch of work , go state <x> , THEN wait for this time
you can play tricks : if you omit the 'go test you can chain states that are 'timerless'. to resynchronize a process you simply go back to a state that has a 'go statement.
Let's say you have a machine that needs to fire every 1000 system ticks. That means you have 1000 ticks to execute the machine. in that case you test for 'go only at the last state of the machine. the machine will execute and then halt until the counter has zeroed.
I had multiple such 'machines' when i was working on harddisks. When the platter passes index i would fire of the main machine and load the length of 1 revolution in the counter ( actually a little bit less , so i could end up in the state that checks for the index pulse to pulse and resynchronize the machine ). Depending on track i would load another machine with the length of a sector ( again a bit smaller so i would end up in the state that is responsible for checking sector transition )
This automatically gave me 'time slots' that were locked on sectors , irrespective of drive speed or sector size. i knew up front how many time slots were available and could do things nicely in lockstep with a spinning motor. during spinup or spindown the numbers would change (speed changes ) or when hopping from inner to outer tracks the sectors per track would change. all i needed to do was alter the time between a system 'tick' the machine would always have the correct number of 'subdivisions per sector, irrespective of motor speed or number of sectors per track. if i knew i needed 10 states per sector passing i could easily program that. the 'tick' was generated by a programmable divider from a master clock that was running much faster ( basically a fractional_n synthesizer)
i could have nested processes by using mulitple of such timer blocks. every process was attached to its own timer block and all were driven by the same master tick. I could have processes wait for their own 'tick' to expire' or wait until another process synced up.