1
\$\begingroup\$

I have a lattic X03LF starter board with 6900C FGPA. There are eight LED available on this board and a push button.

The goal of my code is to design a 8 bit counter that increments whenever a button is pressed. Also there is another button available that is used for resetting the device.

Since the led work on active low signal, i have the counting start from 0xFFh, 0xFEh, 0xFCh...

Below is the design module for the counter,

module led_counter_starter_kit(
output reg [7:0] led_out,
input sw_n,
input reset_n,
input clk,
output [7:0] cur_st,
output [7:0] nex_st
);

reg [7:0] current_state;
reg [7:0] next_state;

parameter S0 = 8'hFF;
parameter S1 = 8'hFE;
parameter S2 = 8'hFC;
parameter S3 = 8'hF8;
parameter S4 = 8'hF0;
parameter S5 = 8'hE0;
parameter S6 = 8'hC0;
parameter S7 = 8'h80;

always @(posedge clk)   begin
    if (~reset_n)
        current_state <= S0;
    else
        current_state <= next_state;
end // always @(posedge clk)

always @(posedge clk) begin
    case (current_state)
        S0: begin 
            if (~sw_n) begin 
            next_state <= S1;
            led_out <= S0;
            end
            else begin
                next_state <= S0;
                led_out <= S0;
            end
            end

        S1: begin 
            if (~sw_n) begin 
            next_state <= S2;
            led_out <= S1;
            end
            else begin
                next_state <= S1;
                led_out <= S1;
            end
            end

        S2: begin 
            if (~sw_n) begin 
            next_state <= S3;
            led_out <= S2;
            end
            else begin
                next_state <= S2;
                led_out <= S2;
            end
            end

        S3: begin 
            if (~sw_n) begin 
            next_state <= S4;
            led_out <= S3;
            end
            else begin
                next_state <= S3;
                led_out <= S3;
            end
            end

        S4: begin 
            if (~sw_n) begin 
            next_state <= S5;
            led_out <= S4;
            end
            else begin
                next_state <= S4;
                led_out <= S4;
            end
            end

        S5: begin 
            if (~sw_n) begin 
            next_state <= S6;
            led_out <= S5;
            end
            else begin
                next_state <= S5;
                led_out <= S5;
            end
            end

        S6: begin 
            if (~sw_n) begin 
            next_state <= S7;
            led_out <= S6;
            end
            else begin
                next_state <= S6;
                led_out <= S6;
            end
            end

        S7: begin 
            if (~sw_n) begin 
            next_state <= S0;
            led_out <= S7;
            end
            else begin
                next_state <= S7;
                led_out <= S7;
            end
            end

        default: next_state <= S0;

        endcase // current_state
    end




/*always @(posedge clk) begin
    if (~reset_n)
        led_out <= S0;
    else begin
        case (current_state)
            S0: led_out <= S1;
            S1: led_out <= S2;
            S2: led_out <= S3;
            S3: led_out <= S4;
            S4: led_out <= S5;
            S5: led_out <= S6;
            S6: led_out <= S7;
            S7: led_out <= S0;
        endcase // case(current_state)
    end 

end // always @(posedge  clk)*/

assign cur_st = current_state;
assign nex_st = next_state;


endmodule // led_counter_starter_kit

and the test bench for this design is below:

`timescale 1s / 1s
`include "led_counter_starter_kit.v"

module starter_kit_counter;
    reg clk;
    reg sw_n;
    reg reset_n;
    wire [7:0] led_out;
    wire [7:0] cur_st;
    wire [7:0] nex_st;

    initial begin
        clk = 1'b0;
    forever begin
        #1 clk = ~ clk;
        end
    end

led_counter_starter_kit Test (.led_out(led_out), 
                              .sw_n(sw_n), 
                              .reset_n(reset_n), 
                              .clk(clk),
                              .cur_st(cur_st),
                              .nex_st(nex_st)
                              );

    initial     begin

    @(posedge clk)      reset_n = 1'b0; sw_n = 1'b1;
    @(posedge clk)      reset_n = 1'b1; sw_n = 1'b0;
    @(posedge clk) ;
    @(posedge clk)      sw_n = 1'b0;
    @(posedge clk) ;
    @(posedge clk) ;
    @(negedge clk)      sw_n = 1'b1;
    @(posedge clk) ;
    @(posedge clk) ;
    @(posedge clk) ;    sw_n = 1'b0;    
    @(posedge clk) ;
    @(posedge clk) ;
    @(posedge clk) ;    sw_n = 1'b1;
    @(posedge clk) ;
    @(posedge clk) ;
    @(posedge clk) $finish;


    end

endmodule

The problem i am running is that the counter is increments after every two cycle of clock period instead after first period.

Here is the snapshot from Model Sim, enter image description here

update: 12/20/2018

enter image description here

Edited code:

always @(sw_n, current_state) begin
    case (current_state)
        S0: begin 
            if (~sw_n) begin 
            next_state <= S1;
            led_out <= S0;
            end
            else begin
                next_state <= S0;
                led_out <= S0;
            end
            end
\$\endgroup\$
2
  • \$\begingroup\$ always @(sw_n, current_state) is technically correct, but a better solution would be to use auto-sensitivity always @*. That way if the reference signals every change, you don't have to remember to add/remove it from the sensitivity. Separately, it is recommended use blocking assignment (=) for combiantional logic. Non-blocking assignment (<=) should be used with assigning synchronous logic. \$\endgroup\$
    – Greg
    Commented Dec 20, 2018 at 20:43
  • \$\begingroup\$ Hi Greg, there is this confusion always in verilog when to use non-blocking versus blocking assignment. \$\endgroup\$
    – JYasir
    Commented Dec 20, 2018 at 23:24

1 Answer 1

0
\$\begingroup\$

The problem i am running is that the counter is increments after every two cycle of clock period instead after first period.

You designed it to do that. Say you keep sw_n is kept low, and you just transitioned to state S1. Now on the next cycle, next_state will be updated to S2. And on the cycle after that current_state will update to S2.

If you want to be able to increment every cycle, you can calculate next_state in combinational logic rather than synchronous logic. This could still involve an always block if you use the usual template for coding a multiplexer.

\$\endgroup\$
3
  • \$\begingroup\$ Thanks for an excellent pointer, actually i only want the next_state to be calculated when i press the switch. I just ran a quick simulation on model sim and it worked as i need it to be. Dumping the code on stater kit and checking how it actually works on the hardware. \$\endgroup\$
    – JYasir
    Commented Dec 20, 2018 at 3:52
  • \$\begingroup\$ Your answer is good, where can i post my edited code and modelsim snapshot? \$\endgroup\$
    – JYasir
    Commented Dec 20, 2018 at 4:56
  • \$\begingroup\$ Feel free to crop your wave screenshot :) \$\endgroup\$
    – CapnJJ
    Commented Dec 20, 2018 at 14:30

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.