3
\$\begingroup\$

I have written a verilog code and RTL simulation is working fine. After this I synthesized the design using XST tool in Xilinx ISE 13.2. The post-synthesis simulation is showing some unexpected results. I don't know what went wrong as there were no warnings during simulation. What should I do now? Is there any way to debug post synthesis level netlist? How can I know what my synthesis tool (XST) is doing with my design? I have included part of my source code. It is for control FSM of my design.

always @ (posedge clock)
begin
case (state)   // s0, s1, s2, s3, s_reset are parameters
s_reset:    
        begin
            if(start_proc)
                state <= s0;
            else
                state <= s_reset;
        end
s0: begin
            pixel_value <= dataOut_bigimage;
            pixel_ref <= dataOut_smallimage;
            j <= j+1;
            if(j==1'b1)
            i <= i+1;
            if ({i,j} == 2'b11)
                if(base_col == 3'b101)
                begin
                    base_row_prev <= base_row;
                    base_col_prev <= base_col;
                    base_col <= 3'b000;
                    base_row <= base_row+1;
                end
                else
                begin
                    base_col <= base_col+1;
                    base_col_prev <= base_col;
                    base_row_prev <= base_row;
                end

            state <= s1;
        end

s1: begin
            if (pixel_value <= pixel_ref)
                accumulator <= accumulator+1;
            else
                accumulator <= accumulator;
            if({i,j} == 2'b00)
                state <= s2;
            else state <= s0;
        end

s2: begin
            if (accumulator > 2'b01)
                begin
                    matchcount <= matchcount+1;
                    rowmatch[matchcount] <= base_row_prev;
                    colmatch[matchcount] <= base_col_prev;
                end
            accumulator <= 2'b00;
            if (base_row == 2'b11)
                state <= s3;
            else 
                state <= s0;
        end

s3: begin
            task_done <= 1'b1;
            state <= s3;
        end

Every thing inside the always block is of reg data type and is properly initialized in a separate initial block

Thanks in advance

\$\endgroup\$
  • \$\begingroup\$ What's your definition of a 'random result'? \$\endgroup\$ – Tim Mar 29 '13 at 18:45
  • \$\begingroup\$ @Tim, it's not same as the one I got in behavioral simulation. My problem is I can monitor only top level ports of my design after synthesis. So all I can tell is, my design is not working after synthesis :( \$\endgroup\$ – Akash Singh Mar 29 '13 at 18:51
  • \$\begingroup\$ I'm not aware of any 'standard way' to debug a post synthesis netlist other than to put on your engineer hat and start trying to work backward through the design to see where it's going wrong. Don't know about the specifics of your tool, but perhaps theres a way you can add keep nets to key signals in your design and see if they are behaving properly. You say that you can only see the top level ports, is there a reason why you cannot run the simulation against your synthesis netlist and dump the full waveform? \$\endgroup\$ – Tim Mar 29 '13 at 18:55
  • \$\begingroup\$ Also I don't know if this is a 50 gate or 500,000 gate synthesis, but if your project is small perhaps you can add the source and someone can look for obvious problems like latches or possibly x-prop issues. \$\endgroup\$ – Tim Mar 29 '13 at 18:55
  • \$\begingroup\$ @Tim, the netlist is in terms of FPGA primitives. So I cannot understand its meaning. Moreover, I don't think there are issues likes latches because XST shows warnings for such problems. I am adding the source here. Let's see if someone can help. \$\endgroup\$ – Akash Singh Mar 29 '13 at 19:05
2
\$\begingroup\$

Add (and use) a reset signal.

Xilinx FPGAs have a global set/reset (GSR) signal that puts all registers in the their default state or as specified in the register declaration (this is documented in the XST User's Guide at the beginning of chapter 5). AFAIK, the @initial block is ignored.

However, things are chaotic when the FPGA starts up, because:

  • The GSR is asynchronous.
  • PLLs are not locked
  • Not all PLLs lock at the same time
  • There are race conditions everywhere

So the initial Flip-Flop values after the GSR are not enough.

Create a module that generates a reset signal for each clock domain. You can create it by by AND'ing relevant asynchronous reset signals, such as an external reset pin, PLL/DCM locked signals, and using it with a synchronizer, as follows:

Reset Circuit

(Source: How do I reset my FPGA?)

\$\endgroup\$
1
\$\begingroup\$

Here's one bit of your code that might trip up someone new to Verilog:

        j <= j+1;
        if(j==1'b1)
           i <= i+1;
        if ({i,j} == 2'b11)
           ...

In this code, the j used for the comparison (if(j==1'b1)) is the old value of j, not the newly incremented value. But I suspect you already knew this, and at any rate if this was your problem, you would have seen it in the behavioral simulation (unless you were using blocking assignment like j = j+1 when you did the behavioral simulation).

Another odd thing about your code is that once you get to state 3, you're stuck. You didn't provide any mechanism to return to the reset state or to state 0, which is an unusual design, but also doesn't sound like the problem you're asking about.

\$\endgroup\$
  • \$\begingroup\$ Actually, it is the old value of j that I am intending to compare in if statement. So, that's not a problem. Also, my design enters state 3 when my task is complete. So it is supposed to be stuck there \$\endgroup\$ – Akash Singh Mar 30 '13 at 5:26
1
\$\begingroup\$

Apparently, there is a tool-specific feature allowing initial blocks to be synthesized in your case. I wasn't aware of that when I wrote this. I wonder why they would add that feature, because it would just encourage bad coding style. A Power-on-reset mega-function would make more sense. So take this answer as general advice.

Every thing inside the always block is of reg data type and is properly initialized in a separate initial block

Initial blocks are usually not synthesizable. Although some tools may correctly implement the initial block, it is not advisable to rely on this behavior for portability reasons. For example, if you switch tools, it may break your design. You should not use them in blocks you intend to synthesize in general, as the pre-synthesis and post-synthesis behavior might not match.

Your block has no reset signal, and usually this means there is no initialization in hardware. To fix this problem, add a reset signal and a reset condition to your code. Then, place the contents of the initial block into the new reset condition block.

\$\endgroup\$
  • 2
    \$\begingroup\$ While I agree with your advice about synthesizing initial blocks, I've found that they can be used with Xilinx tools and FPGAs. Xilinx FPGAs go through an internal reset and programming sequence, and it's possible to initialize registers as part of that process. \$\endgroup\$ – Joe Hass Jul 12 '13 at 11:03
  • \$\begingroup\$ @Joe Where did you find that initial blocks are used during synthesis? From what I understand, only the value specified in their declaration is used. \$\endgroup\$ – apalopohapa Oct 2 '13 at 20:49
  • \$\begingroup\$ @JoeHass, using reset is still the preferred route, because relying on tool-specific behavior like that causes portability problems. \$\endgroup\$ – travisbartley Oct 3 '13 at 8:23
  • \$\begingroup\$ @apalopohapa I couldn't cite a reference for you, but I teach digital design using Xilinx tools and some students use initial blocks in synthesized code, despite my warnings not to do it. To my suprise, it worked. I think it is because the Xilinx chips inherently generate a global power-up reset. \$\endgroup\$ – Joe Hass Oct 3 '13 at 10:56
  • \$\begingroup\$ @trav1s As I said originally, I agree with your advice. However, saying that they are unsynthesizable is not strictly correct. \$\endgroup\$ – Joe Hass Oct 3 '13 at 10:57
0
\$\begingroup\$

I would advise you to have a combinational block and move all the control logic there and only keep the data transfer logic in the sequential block. I haven't run your code, but I feel that in the case of the state being s0, your two if conditions (if j==1'b1) and (if {i,j} == 2'b11) might be colliding with each other. In a normal behavioral simulation, the tool simulates the design without no delays. However, after synthesis, the delays get added to the design and may cause the "random result" problem that you are seeing.

\$\endgroup\$
  • \$\begingroup\$ Might agree with your assessment to split up the logic a little more cleanly, but I can't think of any problem that could be caused by the two if statements that you pointed out. They wouldn't be 'colliding' in any way that I can see. \$\endgroup\$ – Tim Mar 29 '13 at 21:10
  • \$\begingroup\$ I have included many registers in the top level block just by defining reg's and assigning them values in the always block shown in the code. Is that the problem?? Should I define these reg's in separate modules and then instantiate them in the top level block? \$\endgroup\$ – Akash Singh Mar 30 '13 at 5:30
  • \$\begingroup\$ I agree with this advice. Your coding style is very dangerous. Separate the combinational logic into its own procedural block with blocking assignments. The clocked procedure should do nothing more than state <= nextstate; \$\endgroup\$ – Joe Hass Mar 30 '13 at 19:36
  • \$\begingroup\$ @JoeHass This procedural block is mainly sequential. I am assigning values to reg data types depending upon some input signal. Splitting it would mean defining some register modules with Load Enable inputs and controlling these Load Enable signals from this block. But then won't it be like designing from schematics. \$\endgroup\$ – Akash Singh Apr 1 '13 at 10:06
  • \$\begingroup\$ @Tim, my bad. I missed out on the fact that OP is incrementing j nonetheless. \$\endgroup\$ – Spartan_Xtreme Apr 8 '13 at 21:07
0
\$\begingroup\$

I did not find any mention about initial blocks being the proper way of initializing registers value in XTS User's Guide.

On the other hand, I found the following statement on page 109: "Since initial blocks are ignored during synthesis, only always blocks are discussed".

Well, it seems that your synthesis tool does not support registers' initialization in initial blocks. You have two options:

  1. Define a proper reset signal and use it to initialize your design (see other answers for more elaborate explanations)
  2. Use the supported syntax for initialization with internal reset (page 104): reg [3:0] arb_priority = 4'b1011;

In general, I strongly advice you not to use initial statements for initializations of values (except for initialization of SRAM contents and initialization of testbench signals).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.