Andrew
Andrew

Reputation: 2539

Always block being ignored

As part of a larger program, I'd like to activate the green LEDs one at a time on my DE2 board in their order (0 to 8) when I press KEY[1]. They should turn off one at a time in reverse order when I press KEY[2]. I'm pretty sure that DE2 board keys are active low. This is my code:

always@(negedge KEY[1], negedge KEY[2])
begin

    if(~KEY[1])
    begin
        LEDGValue <= LEDGValue << 1;
        LEDGValue[0] <= 1;
    end

    else if(~KEY[2]) 
        LEDGValue[0] <= LEDGValue >> 1;

end

Instead all the green LEDs light up as soon as I load the program. At this point KEY[1] and KEY[2] have no effect. Anyone see something wrong with my code?

Upvotes: 1

Views: 958

Answers (3)

Martin Thompson
Martin Thompson

Reputation: 16792

I'm not a Verilogger, but that looks like you are asking the code to trigger off edges of two different signals. This is not in my experience synthesisable, but the synthesiser may have attempting something and warned you (amongst a plethora of other warnings) that it's done something other than you really meant.


EDIT: The following doesn't apply to the board mentioned as it has debouncing hardware on board (thanks to NathanFarrington for pointing that out) but I leave it here in case it is of use to other readers:


Even if the synthesiser succeeded, edge triggering on a switch input is a dreadful idea: the switch will bounce several times when you press it, and the FPGA is easily fast enough to see all of those edges.

What you need is a process clocked from a good clock source (there's no doubt a crystal on board) which monitors both your switch signals on each clock event.

Keep a counter for each signal, increment it each time the signal is a 1, decrement it each time the signal is a 0. Clamp these counters at 0 and some maximum time which allows plenty of time for the switch to settle (a few milliseconds will probably suffice).

Once the counter has reached either end of its "travel", only then do you take some action (like shifting your LEDGValue). Remember to wait for the switch to be released afterwards (waiting for the count to go to the other 'end').

Upvotes: -1

Nathan Farrington
Nathan Farrington

Reputation: 1970

Here is an edge detector.

module edge_detector (
    input wire clk,
    input wire in,
    output wire negedge_out
);

reg in_reg= 1'b0;

wire in_next = in;

assign negedge_out = ({in_reg,in) == 2'b10);

always @(posedge clk) in_reg <= in_next;

endmodule

Here is how you use an edge detector.

reg [8:0] LEDGValue = 0, LEDGValue_next;

wire key1_edge;
wire key2_edge;

edge_detector
key1_edge_detector_inst (
    .clk(clk),
    .in(KEY[1]),
    .negedge_out(key1_edge)
);

edge_detector
key2_edge_detector_inst (
    .clk(clk),
    .in(KEY[2]),
    .negedge_out(key2_edge)
);

always @* begin : combinational_logic
    LEDGValue_next = LEDGValue;
    if (key1_edge)
        LEDGValue_next = {LEDGValue[7:0], 1'b1};
    else if (key2_edge)
        LEDGValue_next = {1'b0, LEDGValue[8:1]};
end

always @(posedge clk) begin : sequential_logic
    LEDGValue <= LEDGValue_next;
end

The key is that key1_edge and key2_edge signals are asserted only for a single clock cycle.

Upvotes: 2

xucheng
xucheng

Reputation: 275

Should it be

 always@(negedge KEY[1] OR negedge KEY[2])

Upvotes: -1

Related Questions