Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
8 years ago

Latches in frequecny divider using fsm implementation

I am new to verilog and HDL.

I want to implement a N-frequency divider,

which count clock ticks (pos and neg) and start the counting mechanism from the first rising edge of the input clk.

In addition the clk divider has to support synchronous rst_n.

I am using Altera Quartus and the following code

https://pastebin.com/mkw686h4


module clk_divider_fsm
(
    in_clk,
    rst_n,
    out_clk
);
 
input in_clk, rst_n;
output out_clk;
 
parameter prescaler = 10;
parameter BIT_DEPTH = `CLOG2(prescaler);
parameter S0 = 2'b00, S1 = 2'b01, S2 = 2'b10;
parameter CNT_RESET = {BIT_DEPTH{1'b0}};
//parameter CNT_FIRST = {BIT_DEPTH-1{1'b0}, 1'b1};
reg  ps, ns;
reg out_change;
reg out;
reg  cnt;
 
initial
begin
    ps = S0;
    ns = S0;
    cnt = CNT_RESET;
    out_change = 1'b0;
    out = 1'b0;
end
 
always @ (in_clk)
begin
    if(!rst_n)
        ps = S0;
    else
        ps =  ns;
//  begin
//      if(ns != ps)
//          ps =  ns;
//  end
end
 
always @ (in_clk)
begin
    case(ps)
        S0: begin
            if(in_clk === 1'b1)
            begin
                out_change <= 1'b1;
                ns <= S1;
                cnt <= CNT_RESET + 1'b1;
            end
            else
            begin
                out_change <= 1'b0;
                cnt <= CNT_RESET;
                ns <= S0;
            end
        end
        S1: begin
            if(in_clk === 1'b0)
            begin
                if(cnt == prescaler)
                begin
                    cnt <= CNT_RESET + 1'b1;
                    out_change <= 1'b1;
                    ns <= S2;
                end
                else
                begin
                    cnt <= cnt + 1'b1;
                    out_change <= 1'b0;
                    ns <= S2;
                end
            end
            else
            begin
                out_change = 1'b0;
                ns = S1;
                cnt <= cnt;
            end
        end
        
        S2: begin
            if(in_clk == 1'b1)
            begin
                if(cnt == prescaler)
                begin
                    cnt <= CNT_RESET + 1'b1;
                    out_change <= 1'b1;
                    ns <= S1;
                end
                else
                begin
                    cnt <= cnt + 1'b1;
                    out_change <= 1'b0;
                    ns <= S1;
                end
            end
            else
            begin
                out_change = 1'b0;
                ns = S2;
                cnt <= cnt;
            end
        end
        default: begin
            out_change <= 1'b0;
            cnt <= CNT_RESET;
            ns <= S0;
        end
    endcase
    
    if(!rst_n)
    begin
        ns <= S0;
        cnt <= CNT_RESET;
    end
end
 
always @ (posedge out_change or negedge rst_n)
begin
    if(!rst_n)
        out <= 1'b0;
    else
        out <= ~out;
end
 
 
assign out_clk = (prescaler == 1) ? (in_clk & rst_n) : out;
 
endmodule

After synthesis I get warnings about latches used for cnt register.

What am I doing wrong?

Can you guide me with good practice tips to avoid such cases in the future or more elegant ways to implement those kind of RTL?

thanks

19 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Tricky, thank you for your reply.

    I have seen some code examples where the signals in sensitivity list are written without any edge statements.

    Such code can be synthesized ?

    Why quartus doesn't raise any error if such implementation is not compatible with FPGAs?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Hi Tricky, thank you for your reply.

    I have seen some code examples where the signals in sensitivity list are written without any edge statements.

    Such code can be synthesized ?

    Why quartus doesn't raise any error if such implementation is not compatible with FPGAs?

    --- Quote End ---

    Thats because those blocks will describe assignments for the variables in ALL paths through the block (ie. assigned in all ifs and else), so no latches are created.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    OK, but as you said previously

    FPGAs doesn't support both falling and rising edges of signal.

    is that means every verilog module targeted for FPGA can't have sensitivity list without stating the edge of the signal?

    Thanks
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    OK, but as you said previously

    FPGAs doesn't support both falling and rising edges of signal.

    is that means every verilog module targeted for FPGA can't have sensitivity list without stating the edge of the signal?

    Thanks

    --- Quote End ---

    Your code is not clocked, it is level sensitive, hence the latches.

    If you wanted to be sentive to the edges, you would write:

    
    always @(posedge clk or negedge clk)
    begin
      if (clk = '1') //rising edge action
      else if (clk = '0') // falling edge action
    end
    

    This would create a double edge sensitive flop, which is not possible in FPGA. The following code is just level sensitive to the compiler, but not simulation as quartus will ignore the signals in the sensitivity list, and just use what is in the always block, so will not produce a flop:

    
    always @(clk)
    begin
      if (clk = '1' )  // stuff to do while clock is '1'
      else if (clk = '0') // stuff do while clock is '0'
    end
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Tricky,

    Thank you for your reply.

    If I get it right,

    always @(clk)

    begin

    ...

    end

    or always @(*)

    are supported for compilation only but not for simulation and programming into FPGAs.

    Am I correct?

    Thanks
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Hi Tricky,

    Thank you for your reply.

    If I get it right,

    always @(clk)

    begin

    ...

    end

    or always @(*)

    are supported for compilation only but not for simulation and programming into FPGAs.

    Am I correct?

    Thanks

    --- Quote End ---

    Incorrect.

    They are a legitimate way of coding verilog, for creating logic or latches, which are both suitable for FPGAs.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Tricky,

    writing

    always@(clk)

    means it will execute the process for each changing in clk signal, in other words sesitivity for both rising or falling edges. However as you said FPGAs doesn't support dual edge flip flops. What am I missing?

    Sorry, I really don't get it when dual edge sensing is valid and when it's not. And why I don't get any synthesis errors if the HDL code is not suitable for the target device?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    FPGAs do not support dual edge flip flops. Plus Synthesis tools (but not simulators) ignore the sensitivity list of the always block. Hence, if you write:

    always @(clk)

    The synthesis tool ignores it, and treats it as

    always @(*)

    This is because synth tools have to infer logic from your code, and have to follow specific templates to generate specific logic.

    See https://www.altera.com/en_us/pdfs/literature/hb/qts/qts-qps-handbook.pdf , section 2-12 for recommended HDL coding styles.

    The problem with writing

    always @(clk)

    Is that in simulation it will behave like a dual edge flop, but as synthesis treats it as always @(*), the simulation behaviour and real hardware behaviour will not match. This is why you get warnings about latch generation when you may have a perfectly good simultion.