Search code examples
verilog

Delay counter not incrementing? FSM


I was writing a code for DAC register and there is delay required. However, in the delay state, the DAC_counter_2 is not incrementing, and delay is not being achieved. I have copied the code to different project and tried to check. The problem still exists. Any help would be great.

module dac_card
(   output reg DAC_SCLK,
    output reg SYNC,
    output reg SDIN,
    input MHZ_50_CLK,
    input RST,
    output reg [7:0] DAC_counter_1,
    output reg [7:0] DAC_counter_2
    );
    
    reg [7:0] pst_state, nxt_state;
    
    reg [23:0] DAC_reg;
    
    always @(posedge MHZ_50_CLK)
    begin
        if (RST)
        begin
            DAC_reg <= 24'hEEEEEE;
            SYNC <= 1'b1;
            DAC_SCLK <= 1'b0;
            SDIN <=1'b0;
            DAC_counter_1 <= 8'd0;
            DAC_counter_2 <= 8'd0;
            pst_state <= 8'd0;
        end
        else
        begin
            pst_state <= nxt_state;
            DAC_counter_1 <= DAC_counter_1 + 1'b1;
        end
    end
    
    always @(pst_state or DAC_counter_2)
    begin
        case (pst_state)
            8'd0            :   begin
                                    if (DAC_counter_2 == 8'd24)
                                    begin
                                        DAC_counter_2 = 8'd0;
                                        SYNC = 1'b1;
                                        SDIN = 1'b0;
                                        nxt_state = 8'd2;
                                    end
                                    else
                                    begin
                                        SYNC = 1'b0;
                                        DAC_SCLK = 1'b1;
                                        DAC_counter_2 = DAC_counter_2 + 1'b1;
                                        SDIN = DAC_reg [23];                         //Writing DAC register
                                        DAC_reg = DAC_reg << 1;
                                        nxt_state = 8'd1;
                                    end
                                end
            8'd1            :   begin
                                    DAC_SCLK = 1'b0;
                                    nxt_state = 8'd0;
                                end
            8'd2            :   begin
                                    if (DAC_counter_2 == 8'd10)                      //Minimum delay for SYNC to be low for write mode
                                    begin
                                        SYNC = 1'b1;
                                        DAC_counter_2 = 8'd0;
                                        nxt_state = 8'd3;
                                    end
                                    else
                                    begin
                                        SYNC = 1'b0;
                                        //Not incrementing
                                        DAC_counter_2 = DAC_counter_2 + 1'b1;
                                    end                                   
                                end
            8'd3            :   begin
                                    nxt_state = 8'd0;
                                end
            default         :   begin
                                    nxt_state = 8'd0;
                                end
        endcase
    end
endmodule

Here is the test bench

module test_bench
();
//Analog Card DAC wires and registers
    reg MHZ_50_CLK;
    reg RST;
    wire DAC_SCLK;
    wire SYNC;
    wire SDIN;
    wire [7:0] DAC_counter_1;
    wire [7:0] DAC_counter_2;
    
    //Instatntiate DAC
    dac_card dc (.DAC_SCLK(DAC_SCLK),
                 .SYNC(SYNC),
                 .SDIN(SDIN),
                 .MHZ_50_CLK(MHZ_50_CLK),
                 .RST(RST),
                 .DAC_counter_1(DAC_counter_1),
                 .DAC_counter_2(DAC_counter_2)
                 );
    initial
    begin
        MHZ_50_CLK = 1'b0;
        #10 RST = 1'b1; 
        #20 RST = 1'b0;
    end
    
    always
    begin
        #10 MHZ_50_CLK <= ~MHZ_50_CLK;
    end
endmodule

Here is the waveform. After 24 counts of DAC_counter_2, delay for 8'd10 is not achieved.

enter image description here


Solution

  • You need to make an assignment to nxt_state in all branches of your case statement. This also avoids inferring unintended latches. For example, refer to the line // MISSING nxt_state = below:

            8'd2            :   begin
                                    if (DAC_counter_2 == 8'd10)                      //Minimum delay for SYNC to be low for write mode
                                    begin
                                        SYNC = 1'b1;
                                        DAC_counter_2 = 8'd0;
                                        nxt_state = 8'd3;
                                    end
                                    else
                                    begin
                                        SYNC = 1'b0;
                                        //Not incrementing
                                        DAC_counter_2 = DAC_counter_2 + 1'b1;
                                        //  MISSING nxt_state =
                                    end                                   
                                end
    

    As your waves show, once you enter state 2, you remain in state 2. Since DAC_counter_2 is not 10 in state 2, you always execute the else clause, which does not change nxt_state.


    There are a couple other issues which may also be causing problems.

    Good coding practices recommend making assignments to a reg from a single always block. DAC_counter_2 is assigned in 2 different blocks.

    Also, the same signal should not appear on both the LHS and RHS of an assignment in a combinational always block since it creates a feedback loop. For example, DAC_counter_2 = DAC_counter_2 + 1 should probably be in a sequential always block like DAC_counter_1.