Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Beginner questions re FSM

Status
Not open for further replies.

Aussie Susan

Advanced Member level 5
Advanced Member level 5
Joined
Jan 5, 2015
Messages
1,612
Helped
415
Reputation
830
Reaction score
474
Trophy points
1,363
Activity points
19,113
I am very new to FPGA programming and I'm trying to learn using Verilog. (40+ years of procedural programming from Cobol, Pascal, Fortran, all variants of C etc are probably getting in the way!). I have a Digilent Basys3 board and have installed Vivado 2022.1 on a Linux box as my environment.

I've managed to get a 'debounce' module working and using that to toggle a LED - that is the level I'm at!

I've been looking at several code examples of a UART transmitter and they all use a FSM - fair enough as I'm familiar with those from way back in my Electrical Engineering student days. What I don't understand is why they all seem to create 2 'always' blocks, both sensitive to the 'posedge' of the same clock. One seems to handle the state transitions and the other handles the inputs and outputs.

I hope this is not a 'flame war' question but why use 2 FSMs running in parallel? It would seem to me that it is be more 'readable' to have a single FSM that does all the work within each state.

What are the benefits and problems with each style?

Susan
 

I'm a VHDL guy, but I think what I'm about to say still holds.

I think textbooks love to use the two-process state machines. I don't know why. And they also love to talk about Mealy machines, and Moore machines and Mealy-Moore machines.

In all my years of writing (functional, bug-free) FSMs I have NEVER used the two-process approach. It just doesn't make any sense to me. And, apparently, it doesnt' make sense to you either. Brava! And I have never thought, "I'm going to use a Mealy machine here instead of a Moore machine."

And I think it's also good that you realize that FPGAs are not software. Forget about all that software stuff; think hardware!

Let the flaming begin!
 
+1 for Barry's reply!

And since I do not use the two-process state machines I will not try to answer how it works.

In some other forum or may here, really a long time ago, I had read that the early synthesis tools (pre 2005) were not able to correctly interpret your design if a FSM was not two-process state machine based. Do not know how of it is true.

I am not a 20 yr old developer! :)
 

What I don't understand is why they all seem to create 2 'always' blocks, both sensitive to the 'posedge' of the same clock. One seems to handle the state transitions and the other handles the inputs and outputs.
You are right. Two clock edge sensitive blocks can be combined to one without changing the functionality. Having two clocked always block is a special case, not the usual text book approach.

The common two block FSM template found in text books uses one combinational and one clocked always block (respectively VHDL process). As many other contributors discussing the topic in the past, I'm preferring a single process FSM style without separated combinational logic.
 

Thank you for the replies (and no 'flames'!).

I'll stick with what (to me at least) seems the most straight forward way. I have plenty of other issues to sort out with my understanding of coding FPGAs to get on with.

Susan
 

I usually code my FSMs with just the states and the state transition code in one always block. I put everything else into other always blocks including outputs generated by the FSM.

I find it's easier for me to see the overall structure of the FSM if the FSM state transition code is in a concise block without a bunch of other signals being assigned in every state. I've seen state assignment errors that were not caught that would cause issues as the default would change based on which state a state was entered from.

I've also seen FSMs where every signal is assigned in every state and state transition. This makes it hard to even see the overall FSM structure as the FSM code is perhaps 200+ lines of code (because there are 10-20 assignments in every state).

My issue is most if not all of the code I've had to maintain (which follow the 2nd and 3rd paragraphs), never have any documentation, have no FSM diagrams, have no comments in the code, and do not have any (or inconsistent) formatting of the code to make it readable. Therefore anything that makes it easier to see what the code does without as much effort put into analyzing it makes me happy. Perhaps my brain is wired differently than other people.

What I don't do is split my FSM into a two process FSM where the state register is separated from the combinational state transition code. Yes this made a lot of sense when Synopsys back in the early days wouldn't synthesize a single process FSM very well. Synthesis tools have advanced since then and the netlist produced by a two process or a single process FSM are usually identical.
 

You are right. Two clock edge sensitive blocks can be combined to one without changing the functionality. Having two clocked always block is a special case, not the usual text book approach.

The common two block FSM template found in text books uses one combinational and one clocked always block (respectively VHDL process). As many other contributors discussing the topic in the past, I'm preferring a single process FSM style without separated combinational logic.
Let me chime in as I have been writing FSMs for decades and actually worked as an instructor for Cadence courses on Verilog and SystemVerilog...

Most textbooks talk about Mealy and Moore. I have never seen this concept come up in real world, it really makes no difference at all. So let's scrap that.

There is a lot of software mentality that pops up in this discussion. People often talk about writing elegant code, concise code, people argue about verbosity, etc. This discussion never made sense to me (w.r.t. hardware). For one, you are not writing procedural code, you are describing a hardware behavior that will be inferred/synthesized. So I will happily trade elegance for clarity.

About the number of always blocks, this is something that has confused students for decades. I have always emphasized to students that no style produces better logic: one always, two always, three always... The logic will be the same. So what are we discussing in the end?

What are we discussing in the end is coding styles and "quality" of code. To this day, I still prefer the two-always style that separates combinational from sequential. This is a relatively personal choice, doctrine if you will. I like this style because I can easily visualize how many flip-flops will be generated from my code. It also has the benefit that you would never mix and match blocking and non-blocking assignments in the same always block. (I have encountered very few designers that actually know what they are doing when they mix the two). For my students, I tend to set a hard constraint on the assignments: this lab must be solved using one always block. Or two always blocks. In any case, you are not allowed to mix and match assignment operators.

This is how I look at this discussion. It's opinion-based rather than fact-based.
 
A two cents from an outsider on this (compiling all insights):
From the synchronous design perspective, seems like a preference to code gathering structures belonging to the same clock domain at the same always bloc rather than splitting them based on their role on the circuit.
 

Several processes/always blocks only produce the same result as a single one as long as the assignments of each signal/variable are confined to a single block. I stopped splitting blocks when I in one case discovered that I wanted to change one signal in more than one block. Maybe it was a debug signal, I don't remember.

So I don't see a good reason to split the blocks unless you are trying to write a reusable sub-block.

I am a VHDL person. Isn't it true that Verilog code can have dependencies on the execution order?
The execution order isn't known if the code is splitted into several always blocks?
 

Several processes/always blocks only produce the same result as a single one as long as the assignments of each signal/variable are confined to a single block.
ASIC synthesis does not permit assignments to the same variable in different always blocks. This is a no no.
 

That was my point! You limit yourself if you split the code into several processes/always blocks.
I strongly disagree. You cannot have assignments in different always blocks because of multi drivers (that would create shorts in real hardware). This is very different than discussing coding styles.
 

I strongly disagree. You cannot have assignments in different always blocks because of multi drivers (that would create shorts in real hardware). This is very different than discussing coding styles.
My advice is just don't design any state machine.
 

I personally use *a lot* of parallel always blocks.

In my case, I tend to separate combinational logic using "wire/assign/?:" and sequential logic using "reg/always @(posedge clk)/non-blocking assignment(<=)". I avoid as much as I can to use things as "always@(*)/blocking assignments(=)" to generate combinational circuits, because I feel it is more likely to generate latches.

Specially when there is some pipelining involved, I tend to use one always per pipeline in order to maintain some readability, and insert the combinational logic between the pipelines.

Other situation where two always are really needed is when you want to generate a parallel hardware (generate), then you have to use one always inside the generate - for the code you want in parallel - and one always outside the generate, for the circuit you don´t want to duplicate.

A third situation that might be useful to have multiple always: sometimes you want to test if adding a pipeline is effective or not regarding timing. Making one or more "always @(posedge clk)" make it easy to remove the pipeline just by chaning it to "always @(*)" (you need to adjust the blocking/non-blocking assignments, but still not so painful to change).
 

I strongly disagree. You cannot have assignments in different always blocks because of multi drivers (that would create shorts in real hardware). This is very different than discussing coding styles.
I am not sure what you disagree about. Of course we can't synthesize assignments to the same signal in different always blocks. My point is that there is no such limitation if I use a single process/always block.

Assume two state machines in the same clock domain. For some reason, I want a debug/status signal to be set by a specific condition in state machine 1, and it should be reset by a specific condition in state machine 2.
If both state machines are coded in the same process/always block this is not a problem. I can just put the assignments where I want them.
If the state machines are coded in separate processes/always blocks, some workaround involving additional code and signals must be used.

So the coding style has an effect on what you can do.
 
I am not sure what you disagree about. Of course we can't synthesize assignments to the same signal in different always blocks. My point is that there is no such limitation if I use a single process/always block.

Assume two state machines in the same clock domain. For some reason, I want a debug/status signal to be set by a specific condition in state machine 1, and it should be reset by a specific condition in state machine 2.
If both state machines are coded in the same process/always block this is not a problem. I can just put the assignments where I want them.
If the state machines are coded in separate processes/always blocks, some workaround involving additional code and signals must be used.

So the coding style has an effect on what you can do.
Exactly.
 

I am not sure what you disagree about. Of course we can't synthesize assignments to the same signal in different always blocks. My point is that there is no such limitation if I use a single process/always block.

Assume two state machines in the same clock domain. For some reason, I want a debug/status signal to be set by a specific condition in state machine 1, and it should be reset by a specific condition in state machine 2.
If both state machines are coded in the same process/always block this is not a problem. I can just put the assignments where I want them.
If the state machines are coded in separate processes/always blocks, some workaround involving additional code and signals must be used.

So the coding style has an effect on what you can do.

Some comments here:

- For a debug/status signal, you could use a third always block containing the register you want to set/reset, with signals of state machine 1 and 2;
- In fact, I find such limitation (of not allowing two different assignments in different always blocks) a good thing and I use it in my favor. If I have two always blocks, they should represent two different entities (two different components, or two different pipelines for example) which should not receive assignments for the same register in a different block anyway. By this way, I assure the signals relevant for one block are reunited into a single block, and not distributed into a big always block containing a lot of different functionalities.
 

Back in the 79/80's when we created our own RTOS with 6805's and glue logic, we never thought about Mealy-Moore or FSM because ASIC and Programmable Logic didn't exist. The RTOS had to control DS1 1.544 Mbps bidirectionally over 24 channels with prioritized messages for fire/burglar alarms/ meter reading/ telephone/payTV/ opinion polling. The combinational glue logic just had to be sync'd to avoid race conditions unless. they were interrupts.
 

I am not sure what you disagree about. Of course we can't synthesize assignments to the same signal in different always blocks. My point is that there is no such limitation if I use a single process/always block.

Assume two state machines in the same clock domain. For some reason, I want a debug/status signal to be set by a specific condition in state machine 1, and it should be reset by a specific condition in state machine 2.
If both state machines are coded in the same process/always block this is not a problem. I can just put the assignments where I want them.
If the state machines are coded in separate processes/always blocks, some workaround involving additional code and signals must be used.

So the coding style has an effect on what you can do.
Yes, and I have been very clear from the beginning that this discussion should be about code "quality" and preferences.

When you started the topic of multi drivers, the discussion went in a different direction. Your use of the word limitation is very strange. You picked a bad example, IMO, even if I agree with you.
 

Back in the 79/80's when we created our own RTOS with 6805's and glue logic, we never thought about Mealy-Moore or FSM because ASIC and Programmable Logic didn't exist. The RTOS had to control DS1 1.544 Mbps bidirectionally over 24 channels with prioritized messages for fire/burglar alarms/ meter reading/ telephone/payTV/ opinion polling. The combinational glue logic just had to be sync'd to avoid race conditions unless. they were interrupts.
Well, that had absolutely nothing to do with the discussion at hand. Tell us more about an unrelated project you worked on 40 years ago. 😄
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top