Have you ever wondered on when would you want to use an `assign` statement or when would you want to write the combinational logic using an `always_comb` block? Well, generally you can do either but if you have seen my solutions part of the Hands-on RTL Design course then you'd know that I like to use `assign` (by combining it with `genvar` loop) a lot more and very specifically use the `always_comb` block.
One of the reasons for it is because I really like to be quite specific on the logic I want the RTL to synthesise to. I find the combination of `assign` with `genvar` loop does it really well. As an example consider this implementation of a simple count ones logic:
Count Ones using assign
Now, implementing the same using `always_comb` block, the logic would look something like this:
Count Ones using always_comb
The one using the assign statement is slightly easier to comprehend since you know that the output of the previous adder is being used to drive the current one and so on and so forth. You can do the exact same thing in `always_comb` block as well but it would then defeat the entire purpose of the `always_comb` block being procedural in nature.
So, when should we use always_comb block?
I like to describe it for things which are really hard to write using an assign & genvar loop. Like an one-hot mux with multiple bits of data as shown:
Multi-bit One Hot Mux
The one-hot mux with `always_comb` would simply be the following:
One Hot Mux using always_comb
The above logic clearly drives the `one_hot_out` for each iteration of the loop with the current iteration being ORed with the output of the previous iteration. This works since the select is `one-hot` and thus would only match with only one entry.
Can you think of implementing the one-hot mux using assign and genvar blocks? Would love to see you give it a try!
Oh, and before I forget — I’m also making steady progress on the Hands-on Testbench Design course. I’m excited to see how this one turns out!