Electronics > FPGA

Variable clock divider

<< < (5/5)

ataradov:
Oh, yes, I "automatically" missed negedge. This is something you should not do for sure.

kpow8050:

--- Quote from: asmi on January 15, 2022, 06:39:14 am ---It's also a bad idea to use both edges in FPGA designs, as it effectively halves allowed combinatorial delays. Don't do that.

--- End quote ---

Ahh, I see. I will make sure not to do that in future designs. Was thinking it would save an extra clock pulse. But I guess if timing is that critical I can just up the clock frequency

Bassman59:

--- Quote from: asmi on January 15, 2022, 05:34:07 am ---
--- Quote from: BrianHG on January 15, 2022, 05:02:44 am ---That is a lack of coding design quality. 

--- End quote ---
You got this backwards. Defaults are always super-evident because they are always on top of the state machine. If not using them, you will have to hunt though all states and state transitions to figure out what the value is supposed to be. And the larger and more complex state machine is, the harger it will be to understand what the code is doing what the state of each variable is supposed to be.
Lack of coding quality is repeating the same statement over and over again in all branches and states.

--- End quote ---

Asmi is exactly right here. The idea that you set a default assignment at the top of a process and then override it below (like in a state machine) is well understood and is actually (in my humble opinion) less prone to errors of the sort of "I need to set the signal in state X and then clear it in the next state ... what if I add another state in between?" (Yes, yes, yes, you are supposed to re-run your verification after making this change.) And yes, this applies to both VHDL and Verilog.
 
I like to use the term "one-shot" for this sort of thing.

What's cool is that you can implement a state-duration timer with this kind of construct. Rather than having a decrementing counter in each state, have the counter outside of the machine decoder, decrementing to zero when it stops. Assign the "duration" value to the timer in one state, and in the next state, wait for that timer to go to zero before continuing. Something like this. Here, we'll strobe enable for one clock, and then wait for some number of clocks before continuing.


--- Code: ---MyTimedStates : process (clk) is
begin
    if rising_edge(clk) then
        strobe <= '0'; -- clear previously-set one-shot strobe
       
        DurationTimer : if timer > 0
            timer <= timer - 1;
        end if DurationTimer;

        MyDecoder : case (foostate) is
            when S_FOO =>
                strobe <= '1'; -- strobe for one clock
                -- start the timer. Use a signal instead of constant and you
                -- have a run-time variable timer.
                timer  <= 100;   
                foostate <= S_BAR;

            when S_BAR =>
                -- Wait for timer to expire, then we can strobe again.
                WaitForDuration : if timer = 0 then
                    strobe <= '1';
                    timer <= 200; -- wait longer this time.
                    foostate <= S_BLETCH;
                end if WaitForDuration;
   
            when S_BLETCH =>
                WaitAgain : if timer = 0 then
                    -- we're done, go to beginning
                    foostate <= S_FOO;
                end if WaitAgain;           
        end case MyDecoder;
    end if;
end process MyTimedStates;

--- End code ---

This makes a whole lot more sense than having a decrementing counter in each state for the timing.

Navigation

[0] Message Index

[*] Previous page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod