Using assign statements is not a magic method to reduce latency. You could make the exact same thing with an always block.
Code Verilog - [expand] |
1
2
3
4
5
6
7
8
9
10
11
12
| wire in_a;
wire in_b;
wire output_of_the_day;
wire yet_another_output;
// unregistered AND gate
assign output_of_the_day = a & b;
// the exact same boring unregistered AND gate
always @(*) begin
yet_another_output = a & b;
end |
If you no coding habit yet, I suggest you go with the
always flavor. Why? Because while in verilog-1995/2001 there is no real advantage that I can tell, in systemverilog there is. And in verilog country things are slowly but surely moving in the direction of systemverilog. So you would be future proofing your code habits.
Code Verilog - [expand] |
1
2
3
4
5
| wire output_sv_style; // More properly you'd use a "logic" and not a "wire", but lets keep it simple.
// the exact same boring unregistered AND gate
always_comb begin
output_sv_style = a & b;
end |
Case in point, I am used to using
assign statements for simple combinational logic. And now when doing some systemverilog I find I still have that habit, and have to stamp it out (grrr). And then replace it with a proper
always_comb. So if your neural paths are still fresh and in mint condition, might as well cement the correct pathway while you still have the chance. ;-)
As for assigns and reduced latency... An assign results in combinational logic. That is a blob of logic, where the output is NOT put into a clocked register. That lack of register may reduce latency, but it also may reduce functionality and increase pain. What I mean is, you have to use combinational logic for a specific reason, not just "because less latency is good". If that reasoning worked we'd all be making designs without any clocks whatsoever. Somehow that never quite works. And as I said, nothing magic about an assign statement, you can make the exact same thing with an
always @(*) in old verilog or with an
always_comb in systemverilog.