1

I am currently working on a project in Verilog HDL with an FPGA obtained from my school (I am running Quartus II vers. 10.1 and 11.0 (I've tried both)). I am getting a very bizarre bug that I cannot figure out for the life of me.

I am developing a Morse Code program which detects dots and dashes, and then outputs the appropriate letter on a HEX display based upon this input. The HEX display works beautifully, but my UserInput module doesn't seem to do anything at all!

module UserInput(Clock, reset, in, out);
input Clock, reset, in;
output reg [1:0] out;

wire [2:0] PS;
reg [2:0] NS;

parameter NONE = 2'b00, DOT = 2'b01, DASH = 2'b11; //For Output
parameter UP = 3'b000, SHORT0 = 3'b001, SHORT1 = 3'b010, UP_DOT = 3'b011, LONG = 3'b100, UP_DASH = 3'b101;

//Active High
always@(PS or in)
    case (PS)
        UP: if (in)         NS = SHORT0;
             else               NS = UP;

        SHORT0: if (in) NS = SHORT1;
                 else           NS = UP_DOT;

        SHORT1: if (in) NS = LONG;
                 else           NS = UP_DOT;

        UP_DOT:                 NS = UP;

        LONG:   if (in)     NS = LONG;
                else            NS = UP_DASH;

        UP_DASH:            NS = UP;
    default: NS = 3'bxxx;
    endcase

always@(PS)
    case (PS)
        UP:     out = NONE;
        SHORT0: out = NONE;
        SHORT1: out = NONE;
        UP_DOT: out = DOT;
        LONG:   out = NONE;
        UP_DASH: out = DASH;
        default: out = 2'bxx;
    endcase

D_FF dff0 (PS[0], NS[0], reset, Clock);
D_FF dff1 (PS[1], NS[1], reset, Clock);
D_FF dff2 (PS[2], NS[2], reset, Clock);

endmodule

module D_FF (q, d, reset, clk);
    input d, reset, clk;
    output reg q;

    always@(posedge clk or posedge reset)
    begin
        if (reset) q = 0;
        else       q = d;
    end
endmodule

The input for the module is a KEY on the FPGA. The FSM represented by the UserInput module has the key be in the "UP" state at t=0. Then, if there is input, it will move through SHORT0 or SHORT1, and finally LONG. If it the key is released at any of these states, they go to their appropriate intermediary UP states and provide an output of "DOT" or "DASH".

However, when I connect this to my FPGA, I get nothing. From my testing, it seems that it never moves away from the "UP" state. Even my simulations give me nothing. Secondly, I've tried connecting a different UserInput module from a different project (one I know works), and still nothing. Is there something going on in the background of Verilog I am missing?

Here is an image of the simulation waveform:Simulation Waveform

DFf 0, 1, and 2 are the bits 0, 1, and 2 of PS. My simulation won't allow a showing of the NS.

10
  • 1
    When you say it's not working in simulation, are you saying you're applying the proper reset, clock, and in stimulus, and yet the DFFs never change? Can you put up the testbench code? Commented May 29, 2012 at 19:26
  • Yes, that is correct. Unfortunately, I do not know how to write testbench code. I was taught to use the Altera University Program Simulator, which provides a more graphical approach. However, when I do simulate with the Altera UP Simulator, and provide the proper reset, clock, and in stimulus, the DFFs do not change. Commented May 30, 2012 at 0:36
  • Hmm without more information I'm not sure what to say. I think that what you have there should work, provided that you haven't got the reset polarity mixed up or something. If you're debugging waves, maybe you could put up a screenshot of the waves showing relevant signals (reset, clk, NS, PS, in) at the time when it's not working? Commented May 30, 2012 at 0:54
  • I added an image of the simulation. I don't know if this helps, but I'm getting a critical warning "Timing Requirements not met." Could that be the culprit? And if so, how would I fix that? Also, thank you for taking the time to help me. I really appreciate it. Commented May 30, 2012 at 4:18
  • Are you simulating a back-annotated netlist? If timing fails then your simulation won't be useful. Commented May 30, 2012 at 4:49

1 Answer 1

2

Your code looks bad to me (which I guess you want to hear as your code doesn't work). It looks like a combination of timing problems and a design flaw.

Let's walk through your waveform view and see if we can't work out what's going on.

signal in goes high, which triggers an always block. PS is 0 so we set NS to 1. This is not in time for the rising clock edge so it's not triggered in the DFF (as you'd have suspected), never mind it'll be caught on the next clock edge.

signal in goes low, which triggers an always block, PS is 0 so we set NS to 0. This happens in time for the rising clock edge and is captured in the DFF (argh we missed the NS signal going to 1 as we wanted).

Also, someone mentioned that there's an error with your flip-flop being asserted while reset is asserted. This isn't a problem: the reset is synchronous. So on the next rising clock edge the DFF is reset to 0.

So, what's the solution (looks like homework to me, so hopefully you've fixed this already!):

It should look something like this (I haven't simulated it, so no guarantees):

Module UserInput (clk, reset, in, out);
input clk, reset, in;
output [1:0] out;

// output parameters
parameter IDLE = 2'b00;
parameter DOT = 2'b01;
parameter DASH = 2'b10;

// FSM states
parameter LOW = 3'b000;
parameter SHORT1 = 3'b001;
parameter SHORT2 = 3'b010;
parameter LONG = 3'b100;

reg [2:0] state;
wire [1:0] next_out;
wire [2:0] next_state;

always @(posedge clk)
begin
    if (reset)
    begin
        out <= IDLE;
        state <= LOW;
    end;
    else
    begin
        out <= next_out;
        state <= next_state;
    end
    end if;
end

always @(*)
begin
    case (state)
    LOW:
        next_out = IDLE;
        next_state = (in? SHORT1 : LOW);
    SHORT1:
    begin
        next_state = (in? SHORT2: LOW);
        next_out = (in? IDLE : DOT);
    end;
    SHORT2:
        next_state = (in? LONG: LOW);
        next_out = (in? IDLE : DOT);
   LONG:
        next_state = (in? LONG : LOW);
        next_out = (in? IDLE : DASH);
   default:
        // we shouldn't get here!!
        next_state = LOW;
        next_out = IDLE;
   end;
   end module;

So what's going on here: I think this should be fairly obvious. When the in signal moves from high to low then we want to output the current state (LONG as a DASH, SHORT1 and SHORT2 as a DOT), otherwise we output IDLE. If the in signal is high then we want to move the state along depending on how long it's been high for.

There's an error with this code which won't effect simulation, but which will almost certainly effect you on the FPGA: if you are getting input from an external source then you'll need to buffer it through a (series?) of flip-flops to prevent metastability problems. This can be fixed by adding a series of D flip-flops to capture the in signal and then passing this "cleaned" buffered_in to the UserInput.

ie:

module in_buffer (clk, reset, in, out);
input clk, reset, in;
output out;

reg buf1, buf2;

always @ (posedge clk)
begin
    if (reset)
    begin
        out <= 0;
        buf1 <= 0;
        buf2 <= 0;
    end
    else
        out <= buf2;
        buf2 <= buf1;
        buf1 <= in;
    end
end
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.