1
\$\begingroup\$

So I am trying to make a basic FSM in verilog to turn on 3 different LEDs. I've looked at examples and other people's work, but I can't understand why mine wont work. Maybe someone can help me spot a bug in my code I can't see.

module blink( input rst, output reg [2:0] leds, output LED);

OSCH #("2.08") osc_int (                    //"2.03" specifies the operating frequency, 2.03 MHz. Other clock frequencies can be found in the MachX02's documentation
        .STDBY(1'b0),                           //Specifies active state
        .OSC(clk),                              //Outputs clock signal to 'clk' net
        .SEDSTDBY());       
wire clk_slow;              //this will be the slower clock wire

reg [21:0] cnt;                     //these two lines use the fast clock to increment a 21 bit register
always @(posedge clk) cnt <= cnt+1;

assign clk_slow = cnt[21];      //this is high whenever the 21st bit of the fast clock register is true, thus slowing the clock to about 1 Hz
assign LED = clk_slow ;         //status LED so I know my clock is working


reg [1:0] state;            
reg [1:0] state_n;

    parameter S0 = 2'b00;           //state paramenters
    parameter S1 = 2'b01;
    parameter S2 = 2'b10;

always @ (posedge clk_slow or posedge rst)  //state changer
begin
    if(!rst)
        state <= S0;
    else
        state <= state_n;

end

always @ (*)        //changes next state
begin
    case(state)
        S0: state_n = S1;
        S1: state_n = S2;
        S2: state_n = S0;
        default state_n = S0;
    endcase
end

always @ (*)        //decides what leds to light based on state
begin
    if (state == S0)
        leds = 3'b001;
    else if(state == S1)
        leds = 3'b010;
    else if(state == S2)
        leds = 3'b100;
end


endmodule

I'm not quite sure why it isn't working. The status LED I have hooked up is blinking at 1 Hz, which is correct. My other 3 LEDs seem to be stuck in State 0... or something. When I hit the reset button, it sometimes changes my LEDs to state 1, but I think that has to do with clock overlap. Any help is appreciated.

I am using a Lattice Diamond FPGA to program this. I am using the onboard clock to generate the initial clock, and I am using on board LEDs. My reset button is external and active low.

\$\endgroup\$
  • \$\begingroup\$ If the reset is active low you need negedge rst. \$\endgroup\$ – copper.hat May 11 '15 at 4:30
3
\$\begingroup\$
always @ (posedge clk_slow or posedge rst)  //state changer
begin
    if(!rst)
        state <= S0;
    else
        state <= state_n;

end

If you want an asyncronous active-low reset, this always block should be sensitive to negedge rst instead of posedge rst.

If you want an active-high reset, then the condition in your if statement should be rst instead of !rst.

Edit

Other minor issues I see in the code (that shouldn't make your system nonfunctional):

  • Your comment says cnt is a 21-bit register, but the actual code makes it a 22-bit register. This should just make the LEDs blink half as fast as you expected.

  • There is no reset logic for cnt. This will make the code difficult to simulate (because cnt will be stuck in the 'x' state).

\$\endgroup\$
  • \$\begingroup\$ Ah, yes thank you! However, my problem persists even after I have changed that. :( \$\endgroup\$ – Gigaxalus May 11 '15 at 3:32
  • \$\begingroup\$ Hmm ok thanks. I'll try to implement that and see if that helps me find the problem. \$\endgroup\$ – Gigaxalus May 11 '15 at 4:39
0
\$\begingroup\$

Best practice is not to use clk_slow as your state machine clock. Use clk for your state machine and make clk_slow a sort of flag.

always @ (posedge clk or posedge rst)
begin
    if(!rst)
        state <= S0;
    else if (clk_slow)
        state <= state_n;
end

(I don't usually work in Verilog so please verify the syntax)

\$\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.