Always look at the code as a specification for simulation purposes not for HW synthesis. Neither Verilog nor VHDL were designed for synthesis, but were designed for modeling of the behavior of HW. There is a big conceptual gap between these HW modeling languages and what the synthesizers require for a specification. You can close the gap by quickly learning the parts of the language to which synthesizers respond, but that may be somewhat disadvantageous with regard to testing and simulating your designs. If there is one overarching recommendation I can make it is to never implement a design and test it in the FPGA. Always write a testbench even it is nothing more than a clock driver.
EEyE wrote:
#1, it is a sequential circuit by the use of 'always @ (posedge clk)'
The list of signals specified as arguments of @() are simply instructions to the simulator of what input signals are to be monitored during each simultation cycle. A general failure of experience and non-experienced HDL designers is to leave out some of the input signals used by the equations within the always block (process). Synthesis is only concerned about which signal may be used as the clock for any sequential logic in the always block (process). Simulation, OTH, is concerned with speed, and most HDL simulators are event driven. As such they attempt to evaluate equations only when thier input signals change. This is the reason that the arguments of @() are known as the sensitivity list of the always block (process).
In the referenced always block, the @(posedge Clk) identifies to the simulator that the input signal Clk is the only signal that needs tbe monitored for changes, and then only for rising edges. This means that the simulator only evaluates the equation within the block on this event. Since the intent is to specify a sequential circuit, including any of the other input signals in the sensitivity list would not produce the same results because the equations would be changing state whenever one or more transitions occurred.
When viewed in this manner, it becomes clear how the synthesizer interprets the sensitivity list of such an always block. It recognizes that the block is sensitive only to the rising edge of Clk, but it doesn't find Clk included in any of the equations within the block. From this it infers that the equations within the block are sequential logic, so it infers the required FFs. If additional signals had been specified within the sensitivity list and none of them were included in the equations, then the synthesizer would be very confused because that would have implied a sequential circuit with FFs using multiple clocks. If a second signal is specified such as @(posedge Clk or posedge Rst), and the Rst signal is included in the equations of the block, then the synthesizer interprets the Rst signal as an asynchronous SET/CLR signal a la 7474. If a signal such as Rst is used with the always block, but is not included in the sensitivity list, then it is assummed to be a synchronous SET/CLR signal. (The recommended practice in Altera and Xilinx FPGAs is to implement local synchronous resets.)
EEyE wrote:
#2, it uses blocking arguments as opposed to non-blocking, by the use of '<=' which can change a circuit greatly
Blocking and non-blocking assignment concepts are not sythesizable. They are concepts for controlling the simulators. From a synthesis perspective, blocking statements are used within always blocks and their assignments are made to Verilog reg variables. That's why I said in an earlier post that
reg variables are not FFs. They are only FFs if the sensitivity list identifies a posedge/negedge signal as a clock, otherwise they are simply the combinatorial signals to which the blocking assignment <= is made within the block. From a synthesis perspective, the non-blocking assignments are used with
assign statements, and those only synthesize to combinatorial logic.
Conceptually, the blocking assignments within a synthesizable always block functions like a sample and hold in front of an ADC. On the transition of any of the signals in the sensitivity list, the simulator samples and holds the value of all the signals at that instant and then evaluates all of the equations. Notice that I did not mention the synthesizer in this explanation. The logic equations derived by synthesizer are operating in the HW continously without regard to signal transitions and other whatnots.
EEyE wrote:
#3, you use delays which are not synthesizable, i.e.'#1'.
There is a lot of disagreement on my team about my use of this construct. It is true that it is not synthesizable, but it is simulated. The issue that it resolves is a simulation issue. Some simulators, notably ISE (but I've the same problem with ModelSimXE), fail to correctly resolve simultaneous transitions on inputs and outputs. This issue has caused me untold hours of debugging perfectly valid synthesizable code. The solution is to provide the simulator a little help and specify that the output of the assignment will be delayed from the evaluation by some small amount. I have chosen to use #1 (after 1 ns - in VHDL) to avoid this issue. I religiously apply these delays on all assignments for sequential circuits. It is just two simple keystrokes and a space, and it saves an enormous amount of time when debugging.
EEyE wrote:
#4, you use a reset which adds a layer of logic, although it is desirable for simulation.
Relying on the initialization feature of the FPGA is flirtiing with disaster. The fact that the external logic will almost always beat an FPGA in coming out of reset means that some of the external signals may be nice and stable, but others may not because they are adversely affected by the FPGA not being fully operational. There are lots of things I do to avoid this situation, but the best is to have a reset input that is held off until the DONE pin is high. I also change the initialization order in the configuration panel so that DONE is asserted high only after all internal initialization is completed. Finally, the conceptual disconnect represented by an HDL-based design and a schematic-based design means that simulation is absolutely required. As I said above, you should commit yourself to simulating each and every module. This can save you countless hours, and can be as simple as just setting up the clock and releasing reset after a minimum amount of time. (For ISim it is 100ns.)
EEyE wrote:
#5, the case statement infers a multiplexer?
Yes, but it can also infer a ROM.
EEyE wrote:
Question: Why is there no test for Reset on the case statement, like it is tested in the other FF's?
The always @(*) block in which the partial sums are computed does not declare a clock. Without a clock, the block specifies combinatorial logic, and Rst is not required as a gating function in the logic.
EEyE wrote:
#6, you use '2**' exclusivley to shift right?, instead of '<<'?
No. Exponentiation is used to calculate the width of the vectors. I changed the parameterization in the other modules to use N as the bit width directly. It is more natural.
I have found that >> and << don't synthesize reliably in ISE. So I generally write the left and right shifts explicitly.