0
\$\begingroup\$

I am trying to write a verilog code for a Fibonacci sequence generator. It's output will be nth Fibonacci number where n is the output of the count. The code works for count = 2. But when the count increases, all the specified register values goes to 0. I am suspecting the error might be in the always block that contains the case statement. How can I solve the problem?

module fib(clk, reset, count, out, prev,present, temp);
// This module generates nth fibonacchi number, where n is the output of the count
    input clk, reset;
    output reg[7:0] count;
    output [7:0]out;
    output reg [7:0]prev, present, temp;
    //state register
    always @(posedge clk)
        if(reset==1) count = 1;
        else count = count + 1;

    //next state logic
    always @(count[0])
    case(count)
    8'b00000001:begin
                prev = 8'bxxxxxxxx; present = 8'bxxxxxxxx;
                end
    8'b00000010:begin
                prev = 8'b00000000; present = 8'b00000001;
                end
    default: begin
                temp = present;
                present = present + prev;
                prev = temp;
            end
    endcase

    //output logic

    assign out = present;

endmodule
\$\endgroup\$
1
  • \$\begingroup\$ Comments are not for extended discussion; this conversation has been moved to chat. \$\endgroup\$
    – Dave Tweed
    Jul 19, 2018 at 19:23

1 Answer 1

3
\$\begingroup\$

You are writing Verilog as if it is a standard programming language. HDL languages work rather different.

  1. In your count section use non-blocking assignments.

  2. In your always section you are generating latches. The whole 'always' section should be controlled by a clock as you have 'memory' elements in there: You want the values of prev, temp and present to be 'remembered'.

  3. It is common (good) practice to always use begin-end sections. In your case it works because you have a single statement (if and case).

  4. The Fibonacci sequence starts with 1,1 which is not in your code.

  5. If you use non-blocking assignments, you no longer need the 'temp' variable:

prev    <= present
present <= present + prev;

Side notes:

  1. A name like 'out' is not very descriptive. Even if you write short test snippets use descriptive names.
  2. It is bad practice to use always @( variable ) these days. It can lead to simulation synthesis mismatches. You should use always @( * ) or alway_comb.
  3. Comment as at the bottom of your example is rather superfluous:

//output logic   
assign out = present;
\$\endgroup\$
3
  • \$\begingroup\$ begin/end isn't needed if there's only one statement in a block. Stylistically I'd rather see it than check carefully whether it's needed, but I don't think this is what's causing OP's unexplained behavior. \$\endgroup\$
    – The Photon
    Jul 17, 2018 at 15:27
  • \$\begingroup\$ Thanks for your input. Finally the code has run somewhat perfectly after I initialized used posedge clk for both always block. Could you comment on why combinational assignment didn't work here? The pastebin link for the code is given: pastebin.com/jmC6aw1L \$\endgroup\$
    – user308177
    Jul 17, 2018 at 16:41
  • \$\begingroup\$ @ThePhoton : Yes I noticed, I will update. @user308177: You made some weird combinatorial loop with latches. HDL is like hardware. If you write e.g. a=b+1; b=a; you make a 'circuit' where the output goes straight back into the input. The @(posedge clk)breaks the loop with a register. \$\endgroup\$
    – Oldfart
    Jul 17, 2018 at 20:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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