1

Sorry if anything in here seems obvious but I am starting out in this new FPGA thing and I really enjoy it so far but this is driving me crazy. Here is the Verilog code for a block that should in principle do the following to an 8 bit register:

00000001

00000010

00000100

.....

01000000

10000000

01000000

00100000

module bit_bouncer(clock, enable, bouncer_out);
//INPUTS PORTS
input clock;
input enable;
//OUTPUTS PORTS
output bouncer_out;
//INPUT DATA TYPE
wire clock;
wire enable;
//OUTPUT DATA TYPE
reg [7:0] bouncer_out = 8'b00000001;
//Register to store data
reg direction = 0;

//CODE STARTS HERE
always @ (posedge clock) begin
    if(enable) begin
        bouncer_out = direction ? (bouncer_out >> 1) : (bouncer_out << 1);
        direction <= (bouncer_out == 8'b00000001 || bouncer_out == 8'b10000000) ? ~direction : direction;
    end
end

endmodule

This works perfectly in simulation but fails on the FPGA (DE10-Nano board, if interested). I should also point out that this gets driven by a clock passed trough a PLL on the FPGA that is then passed trough a divideByN block. Here is the code for the divideByN block:

module clk_divn #(
parameter WIDTH = 20,
parameter N = 1000000)

(clk,reset, clk_out);

input clk;
input reset;
output clk_out;

reg [WIDTH-1:0] pos_count = {WIDTH{1'b0}};
reg [WIDTH-1:0] neg_count = {WIDTH{1'b0}};
wire [WIDTH-1:0] r_nxt = {WIDTH{1'b0}};

 always @(posedge clk)
 if (reset)
 pos_count <=0;
 else if (pos_count ==N-1) pos_count <= 0;
 else pos_count<= pos_count +1;

 always @(negedge clk)
 if (reset)
 neg_count <=0;
 else  if (neg_count ==N-1) neg_count <= 0;
 else neg_count<= neg_count +1; 

assign clk_out = ((pos_count > (N>>1)) | (neg_count > (N>>1))); 
endmodule

The divideByN has also been tested in simulation and works fine. I actually made a simulation in which the divideByN is connected to the "bouncer_block" if I can call it like that and it also works.

Everything simulates but nothing works in real life....but isn't it always like that :P

I hope someone can help me figure this out because I really want to learn more about FPGA and use them in future projects.

If you read all this you are awesome and I wish you an amazing day :)

  • You need to explain with more details what "failes" means. We can't see your FPGA board. – dave_59 Apr 19 '20 at 06:04
  • The 8 LEDs which I hooked the output to just light up one at a time in an unpredictable manner (it jumps around very fast and stops on an LED and the jumps again fast to another LED lighting the LED in it's path very briefly) – Zacharie McCormick Apr 19 '20 at 06:31
  • 1
    You are using what we called a *'derived clock'*. A clock which is generated by another clock plus logic. There was a question about that yesterday [here](https://electronics.stackexchange.com/questions/494006). Have a look at the comments there. If at all possible use one master clock throughout your design. (Until you get to multiple clock domains and clock domain crossing in a few years time) – Oldfart Apr 19 '20 at 06:51
  • I have done as you said and used a direct clock from the FPGA and I passed it only trough the divideByN and not the PLL. Now the only thing I get is one LED that remains lit forever and nothing happens (no button press affect it either, in caes you may be thinking that my logic is reversed for my enables). Here is my schematic to show you my actual setup which still does not work (Still using the same code as before but i tweeked the divideByN to 50 000 000 to try and get a 1Hz signal from the input clock): https://imgur.com/tegPQLg – Zacharie McCormick Apr 19 '20 at 13:11
  • I alos edited the width of the divideByN to 26 to account for the N of 50 000 000 (not 5 000 000...silly me...).But it still doesn't work. Now the LED jumps around as before but seems to be affected by the width of the divideByN even though the buffer is big enough for the N used. – Zacharie McCormick Apr 19 '20 at 13:36
  • Can you add a reset to your `bit_bouncer` module and reset the `bouncer_out` and `direction` registers instead of relying on the initial assignment? Maybe something weird is happening during powerup and you don't have a reset condition to restore it to normalcy. Can you also check the timing reports and confirm the design has all positive slacks? – Charles Clayton Apr 19 '20 at 16:58
  • I will try the reset thing, just give me a couple of hours and I'll get back with more info :) – Zacharie McCormick Apr 19 '20 at 20:13

2 Answers2

0

Your bit bouncer is not operating synchronously to the system clock and neither does it have a reset condition, which is a recipe for trouble.

A better approach is to use a clock strobe and test for it on edges of the main system clock. Also, all inputs from tactile buttons should be synchronised to the system clock and debounced. Something like this:

Schematic

enter image description here

RTL

enter image description here

BitBouncer

module BitBouncer
(
    input wire clock,
    input wire reset,
    input wire enable,
    input wire clock_strobe,
    output reg[7:0] bouncer_out
);

    // Register to store data
    reg direction = 0;

    // CODE STARTS HERE
    always @(posedge clock)
    begin
        if (reset)
        begin
            bouncer_out = 1;
            direction = 0;
        end
        else if (enable && clock_strobe)
        begin
            bouncer_out = direction ? (bouncer_out >> 1) : (bouncer_out << 1);
            direction <= (bouncer_out == 8'b00000001 || bouncer_out == 8'b10000000) ? ~direction : direction;
        end
    end

endmodule

ClockStrobe

module ClockStrobe
#(
    parameter MAX_COUNT = 50000000
)
(
    input wire clock,
    input wire reset, 
    output reg clock_strobe
);

    reg [$clog2(MAX_COUNT) - 1: 0] counter;

    always @(posedge clock)
    begin
        if (reset)
        begin
            counter <= 0;
        end
        else
        begin
            counter <= counter + 1;
            if (counter == MAX_COUNT)
            begin
                clock_strobe <= 1;
                counter <= 0;
            end
            else
            begin
                clock_strobe <= 0;
            end
        end
    end

endmodule

Sync

module Sync
(
    input wire clock,
    input wire in,
    output reg out
);

    reg [2:0] sync_buffer;

    initial
    begin
        out = 0;
        sync_buffer = 3'd0;
    end

    always @*
    begin
        out <= sync_buffer[2];
    end

    always @(posedge clock)
    begin
        sync_buffer[0] <= in;
        sync_buffer[2:1] <= sync_buffer[1:0];
    end

endmodule

Debounce

module Debounce
#(
    parameter MAX_COUNT = 2500000
)
(
    input wire clock,
    input wire in,
    output reg out
);

    reg previous_in;

    reg [$clog2(MAX_COUNT) - 1:0] counter;

    initial begin
        previous_in = 0;
        counter = 0;
        out = 0;
    end

    always @(posedge clock)
    begin
        counter <= counter + 1;
        if (counter == MAX_COUNT)
        begin
            out <= previous_in;
            counter <= 0;
        end
        else if (in != previous_in)
        begin
            counter <= 0;
        end
        previous_in <= in;
    end

endmodule
tim
  • 482
  • 3
  • 12
  • You literally posted this as I was writing my answer to this post XD Let me read it now :P – Zacharie McCormick Apr 19 '20 at 20:37
  • Ok so if I'm getting this correctly you are debouncing my switch but I forgot to mention that they are already debounced on the hardware (sorry about that). But could you please explain the functionning of a clock strobe and it's puprose (if you have the time of course). And thx for that clog2 function, I have been wanting to remove those pesky WIDTH parameter for since yesterday :P – Zacharie McCormick Apr 19 '20 at 20:44
  • Regarding debouncing, my dev board manual *claims* that they are debounced, but in my experience my dev board buttons have taken such a hammering, I do the extra debouncing just to be sure. – tim Apr 19 '20 at 21:18
  • Regarding the clock strobe, it generates a pulse width of one clock cycle every MAX_COUNT. Then the BitBouncer tests the value of the strobe on every positive edge of the system clock. This keeps the logic synchronised to the system clock, therefore only one clock domain. By trying to synchronise to a clock divider, it lags by a multitude of propagation delays, therefore highly unlikely to be lined up with the system clock edges and becomes another clock domain of bad quality. – tim Apr 19 '20 at 21:26
  • I'll take note of that :P Do you have the same board? – Zacharie McCormick Apr 19 '20 at 21:27
  • I'm using the DE2-115 at the moment. Your bit bouncer works well on it even with my dodgy KEY0. – tim Apr 19 '20 at 21:30
  • I kinda understand so I'll jsut let the idea sink in for a while :P But thanks for the information, I'll use that in the future because as I understand it, you should avoid having too many unnecessary clock domain because each one uses a precious clock line inside the FPGA. Just confirm this fact and I'll be on my way :) Also, I will mark your answer as the final answer but you skimmed over the divideByN block which was the real culprit here in the end. – Zacharie McCormick Apr 19 '20 at 21:33
  • Nice to know someone is enjoying my crappy design XD – Zacharie McCormick Apr 19 '20 at 21:33
  • Thx to everyone who helped me figure this out. I will most definitly be posting more question on this forum which seems to have an equallly awesome community :) – Zacharie McCormick Apr 19 '20 at 21:37
  • Thanks for marking it as the answer. Would just like to highlight that synchronising of asynchronous inputs is vital to avoid flip-flop metastability issues when the input changes very close to or at the system clock edge. At least a two-stage buffer should be used. A single stage buffer is not reliable enough. – tim Apr 19 '20 at 22:19
  • I finally understood the clock strobe! Thx for this HAHA moment I now have another great tool in my pocket to use for future projects :) For anyone wondering, you use a clock strobe to avoid creating a new clock signal in your design that would be put onto a clock line inside the FPGA. Doing this, you now have the same behavior but you are using less precious ressources :) And for anyone looking at the above schematic and being dumbstruck as I was trying to understand it, simply consider the clock strobe block as the divideByN block I had in my design (it should become clearer). – Zacharie McCormick Apr 20 '20 at 02:45
0

I have tried to add a reset with no success but I have made my own divideByN and kept the reset Charles suggested and now it's working flawlessly. I think the code for the divideByN I took online might be unable to synthesize properly. Here is my new code for the divideByN:

module my_div_n #(parameter N = 1_000_000, parameter WIDTH = 20) (clock_in, 

clock_out);
input wire clock_in;
output reg clock_out;
reg[WIDTH-2:0] counter; //WIDTH-2 because the last bit is taken care of by the fact that we flip the output (it acts as the last bit)

always @ (posedge clock_in) begin
    counter <= counter + 19'b1;
    if(counter == N>>1) begin
        counter <= 0;
        clock_out <= !clock_out;
    end
end

endmodule

And the code for my bit_bouncer:

module bit_bouncer(clock, enable, reset, bouncer_out);
//INPUTS PORTS
input clock;
input enable;
input reset;
//OUTPUTS PORTS
output [7:0] bouncer_out;
//INPUT DATA TYPE
wire clock;
wire enable;
wire reset;
//OUTPUT DATA TYPE
reg [7:0] bouncer_out;
//Register to store data
reg direction;

//CODE STARTS HERE
always @ (posedge clock) begin
    if(reset) begin
        bouncer_out <= 8'b00000001;
        direction <= 0;
    end
    else if(enable) begin
        bouncer_out = direction ? (bouncer_out >> 1) : (bouncer_out << 1);
        direction <= (bouncer_out == 8'b00000001 || bouncer_out == 8'b10000000) ? ~direction : direction;
    end
end

endmodule

Here how everything is wired:

The circuit block diagram

I would still like to know the purpose of the clock strobe because you make it seem as if I should probably know this if I want to understand my circuit better and all about synchronicity.