Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Debouncer & FIFO in VHDL

Status
Not open for further replies.

Morell

Member level 1
Joined
Dec 1, 2015
Messages
35
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
614
Hi,

I wrote these Components.
I simulated both of them and they worked correctly but
in implementation(Spartan-3 50MHz), they sometimes work and sometimes don't.

1- Debouncer:

There are two counters : Clock_Divider_Counter (Works with 50MHz) and
Debounce_Counter (Works with 1KHz)

If Bounced_Start (Input) is '1' for about 100 mili seconds then
Decounced_Start (Output) will become '1' only for one clock pulse (1/50MHz).





Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
entity Debouncer is
    Port (Clock : in STD_LOGIC;
            Reset : in STD_LOGIC:='0';
            
            Bounced_Start : in STD_LOGIC:='0';
            Debounced_Start : out STD_LOGIC:='0');
end Debouncer;
 
architecture Behavioral of Debouncer is
 
Constant Clock_Divider_Counter_Top : integer := 50000;  -- 50000
Constant Debounce_Counter_Top : integer := 100; -- 100
 
Signal Bounced_Start_Reg : std_logic := '0';
Signal Debounced_Start_Reg : std_logic := '0';
Signal Clock_Divider_Counter : integer range 0 to Clock_Divider_Counter_Top :=0;
Signal Debounce_Counter : integer range 0 to Debounce_Counter_Top := 0;
 
 
begin
 
Debounced_Start <= Debounced_Start_Reg;
 
Process (Clock)
Begin
    if rising_edge (Clock) then
        if RESET = '1' then 
            -- reset all assigned signals
            Bounced_Start_Reg <= '0';
            Debounced_Start_Reg <= '0';
            Clock_Divider_Counter <= 0;
            Debounce_Counter <= 0;
            
        else 
            
            -- Default assignments
            Bounced_Start_Reg <= Bounced_Start;
------------------------------------------------------------------------------------
 
            if Bounced_Start = '1' then 
                Clock_Divider_Counter <= Clock_Divider_Counter + 1;
            else 
                Clock_Divider_Counter <= 0;
            end if;
 
------------------------------------------------------------------------------------
            
            if (Clock_Divider_Counter = Clock_Divider_Counter_Top) then 
                Clock_Divider_Counter <= 0;
                if (Bounced_Start_Reg = '1') then 
                    Debounce_Counter <= Debounce_Counter + 1;
                else 
                    Debounce_Counter <= 0;
                end if;
            end if;
            
------------------------------------------------------------------------------------
            
            if  Debounce_Counter = Debounce_Counter_Top then 
                Debounced_Start_Reg <= '1';
                Debounce_Counter <= 0;
            else 
                Debounced_Start_Reg <= '0';
            end if;
            
------------------------------------------------------------------------------------            
        end if;
    end if;
End Process;
end Behavioral;




2- FIFO :

Input (Data_in) is 1 to 4 bytes.
Output (Data_out) is 1 byte.
Data_out is Data_in_Reg(i).


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
entity FIFO is
 
    Generic  (FIFO_Length : integer range 1 to 4 :=1;
             Byte : integer := 8);
                 
    Port      (Clock : in STD_LOGIC;
             Reset : in STD_LOGIC:='0';
                
                 Write_in : in STD_LOGIC:='0';
                
             FIFO_Ready : out STD_LOGIC:='0';
                
             i : in integer range 0 to FIFO_Length-1:=0;
                
             Data_in : in STD_LOGIC_VECTOR((FIFO_Length * Byte)-1 downto 0);
             Data_out : out STD_LOGIC_VECTOR(Byte-1 downto 0));
 
end FIFO;
 
architecture Behavioral of FIFO is
 
type FIFO_Type is array (0 to FIFO_Length - 1) of std_logic_vector(7 downto 0) ;
signal Data_in_Reg : FIFO_Type := (others => x"00");
 
signal Data_out_Reg : std_logic_vector(Byte-1 downto 0):=(Others => '0');
 
signal Write_in_Reg : std_logic:='0';
signal FIFO_Ready_Reg : std_logic:='0';
 
signal Index : integer range 0 to (FIFO_Length-1):=0;  
signal j : integer range 0 to (FIFO_Length-1):=0;  
 
 
type State is (Idle,Writing,Reading);
signal Current : State := Idle;
 
begin
 
-- Combinatorial Parts
    FIFO_Ready <= FIFO_Ready_Reg;
    
    Data_out <= Data_out_Reg;
 
Process(Clock)
begin
    if rising_edge(Clock) then 
        if reset = '1' then
            -- Reset all assigned signals
            Index <= 0;
            
            Write_in_Reg <= '0';
            
            Current <= Idle;
            
            J <= 0;
            
            Data_in_Reg <= (Others => X"00");
            
            Data_out_Reg <= (Others => '0');
            
            FIFO_Ready_Reg <='0';
            
        else
            -- Default assignments
            Index <= i;
            Write_in_Reg <= Write_in;
            
            
            Case Current is 
--Idle------------------------------------------------
                
                When Idle => 
                    FIFO_Ready_Reg <= '0';
                    if Write_in_Reg = '1' then
                        Current <= Writing; 
                    else
                        Current <= Idle;
                    end if;
                    
--Writing------------------------------------------------
                
                When Writing => 
                    if (j /= FIFO_Length-1) then 
                        Data_in_Reg(j) <= Data_in( (Byte * (j+1))-1 downto Byte * j );
                        j <= j + 1;
                    else
                        Data_in_Reg(j) <= Data_in( (Byte * (j+1))-1 downto Byte * j );
                        Current <= Reading;
                    end if;
                    
--Reading------------------------------------------------
                
                When Reading => 
                    FIFO_Ready_Reg <= '1';
                    Data_out_Reg <= Data_in_Reg(Index);
                    if (Index = 0) then 
                        Current <= Idle;
                    end if;
                    
---------------------------------------------------------
    
            End Case;
            
        end if;
    end if;
end Process;
 
end Behavioral;

 

debounce counter is assigned in two different if statements. This is logically fine, but may lead to errors. It is something that should be rare enough to justify an explanation.

You reset the debounce counter when it is equal to counter top. It seems possible to hold the button for a second and generate 10 pulses.
 
  • Like
Reactions: Morell

    Morell

    Points: 2
    Helpful Answer Positive Rating
Yes this is possible.

What should I do?

This is exactly what my teacher said.
I have no idea what to do.
 

Re: Debouncer &amp; FIFO in VHDL

I would code all three if statements like so:
Code:
  if (Bounced_Start = '1' AND Clock_Divider_Counter /= Clock_Divider_Counter_Top) then 
    Clock_Divider_Counter <= Clock_Divider_Counter + 1;
  else 
    Clock_Divider_Counter <= 0;
  end if;

--------------------------------------------------------------------------
  
  if (Clock_Divider_Counter = Clock_Divider_Counter_Top) then 
    if (Bounced_Start_Reg = '1' AND Debounce_Counter /= Debounce_Counter_Top) then 
      Debounce_Counter <= Debounce_Counter + 1;
    else 
      Debounce_Counter <= 0;
    end if;
  end if;
  
--------------------------------------------------------------------------
  
  if (Debounce_Counter = Debounce_Counter_Top) then 
    Debounced_Start_Reg <= '1';
  else 
    Debounced_Start_Reg <= '0';
  end if;

Note that none of the if statements assign outputs that are common across multiple if statements.

I think you need to review flow control (if) statements. You seem to have difficulty translating from what the decisions are and how to write an if statement that reflects those decisions.

Also, my guess would be you didn't draw a schematic/block diagram of how the debounce circuit should look like and work before starting your code.

Debounce...
1. detect a leading edge of a signal (should also use a 2 or 3 stage synchronizer before doing this)
2. start timeout counter (10 ms is typically used for mechanical switches)
3. clear timeout counter if is signal is not detected (bounce chatter!)
4. timeout detected (10 ms of detected signal)
5. generate debounced signal (you won't use this as your pulse)
6. generate your single period output pulse by detecting the leading edge of your debounced signal.
7. clear the counter (done already in 3) and the debounced signal only when the input signal is removed.

- - - Updated - - -

Edit:

I don't understand your FIFO code. If you start writing it writes forever until the FIFO is full. If you have a single clock wide write pulse it will fill the FIFO up. That is NOT a typical FIFO (it's more of a FIMFO, First In, Many First Outs).

What is the specification of this sort of "FIFO"ish thing?

Once again there is an apparent lack of "design" being done prior to coding.
 
  • Like
Reactions: Morell

    Morell

    Points: 2
    Helpful Answer Positive Rating
Re: Debouncer &amp; FIFO in VHDL

@Ads-ee Thank you very much

I didn't quite understand the "Debouncer" part but I will think about it.

About the FIFO.
That is not really a FIFO. :-D

FIFO has to work as I Discribe:

1- The top module in which FIFO is used, sends 1 to 4 (FIFO_Length) bytes to the FIFO.
2- Then FIFO dynamically, creates a place coresponding to the size of FIFO_Length.
for example : if FIFO_Length is 3 then FIFO Creates a place with the size of three bytes.(Data_in_Reg).
and Data_in_Reg(0), Data_in_Reg(1) and Data_in_Reg(2) are FIFO's Three Places(Bytes).
3- Now FIFO should sends those three bytes from High to Low (first Data_in_Reg(2) then Data_in_Reg(1) then Data_in_Reg(0))

So basically it is not a FIFO, it just Divides a string of bits(8,16,24 and 32 bits) into 8-bits, and sends them from high to low.

So do you think my "FIFO" does that?
or there are some mistakes?

thank yoyu very much
 

You have the FIFO_Length defined in the generic as 1, you can't change that on-the-fly. That is a compile time constant if the width needs to be 1 to 4 bytes you have to supply an interface that supports 4 bytes as that is the maximum width.

It still looks to me like some sort of FIFO, but still has the issue of repeatedly writing the same value multiple times. It's not logically done as a width conversion FIFO.

FIFOs typically have a write strobe (for each word written), a full flag, so writing source knows there's no room left in the FIFO, an empty flag to let the reader know there is data available in the FIFO, a read strobe to get data out of the FIFO, along with the input data and the output data. Your "FIFO" doesn't have any of these, so there's no way to actually control it.
 
  • Like
Reactions: Morell

    Morell

    Points: 2
    Helpful Answer Positive Rating
For the debouncer, you should have the debounce count have an upper limit of one higher than it is now. It increments until it reaches this N+1 limit. The output pulse occurs when the counter reaches N. Now the output pulses are not duplicated.
 
  • Like
Reactions: Morell

    Morell

    Points: 2
    Helpful Answer Positive Rating
Transmitter & Debouncer in VHDL

Hi,

I designed 3 modules with your help,
All of them worked on the board.
But there was a small problem in testing the code on the board (Spartan-3 50Mhz).

1- These are the codes :

- Top module


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
entity Transmitter_Test is
 
Generic       (
                FIFO_Length : integer range 1 to 4 := 3;
                Byte : integer := 8;
                Bit_Time : integer :=5460
                );
 
    Port    (
                Clock : in std_logic;
                Reset : in std_logic:='0';
                
                Start : in std_logic:='0';
                
                TxD : out std_logic:='1';
                TxD_Valid : out std_logic:='0'
                );
 
end Transmitter_Test;
 
architecture Behavioral of Transmitter_Test is
 
--======================================================================
 
Component Transmitter
    
    Generic (
                FIFO_Length : integer range 1 to 4 := 3;
                Byte : integer := 8;
                Bit_Time : integer :=5460
                );
 
    Port    (
               Clock : in STD_LOGIC;
                Reset : in STD_LOGIC:='0';
                
                Data : in STD_LOGIC_VECTOR(31 downto 0):=(Others => '0');
                Send : in STD_LOGIC:='0';
                
                TxD : out STD_LOGIC:='1';
                TxD_Valid : out STD_LOGIC:='0'
                );
 
end Component;
--======================================================================
Component Debouncer 
    Port (Clock : in STD_LOGIC;
            Reset : in STD_LOGIC:='0';
            
            Bounced_Start : in STD_LOGIC:='0';
            Debounced_Start : out STD_LOGIC:='0');
end Component;
 
--======================================================================
--Transmitter's signals
                
Signal TxD_Reg,TxD_Wire: std_logic:='1';
 
Signal TxD_Valid_Reg,TxD_Valid_Wire : std_logic:='0';
 
Signal Data : std_logic_vector(31 downto 0):=X"330f00FF";
 
--======================================================================
--Debouncer's Signals
 
Signal Bounced_Start_Reg : std_logic:='0';
 
Signal Debounced_Start_Reg , Debounced_Start_Wire : std_logic:='0';
 
--======================================================================
 
begin
Unit_Debouncer   : Debouncer   Port Map (Clock,Reset, Bounced_Start_Reg , Debounced_Start_Wire);
Unit_Transmitter : Transmitter Port Map (Clock,Reset, Data , Debounced_Start_Reg , TxD_Wire , TxD_Valid_Wire);
 
TxD <= TxD_Reg;
TxD_Valid <= TxD_Valid_Reg;
 
Process(Clock)
begin
    if rising_edge(Clock) then 
        if reset = '1' then 
            --Reset
            Bounced_Start_Reg <= '0';
            Debounced_Start_Reg <= '0';
            
            TxD_Reg <= '0';
            TxD_Valid_Reg <= '1';
            
        else
            --Default
            Bounced_Start_Reg <=Start;
            Debounced_Start_Reg <= Debounced_Start_Wire;
            
            TxD_Reg <= TxD_Wire;
            TxD_Valid_Reg <= TxD_Valid_Wire;
            
        end if;
    end if;
End Process;
end Behavioral;



- Debouncer (the first component)


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
entity Debouncer is
    Port (Clock : in STD_LOGIC;
            Reset : in STD_LOGIC:='0';
            
            Bounced_Start : in STD_LOGIC:='0';
            Debounced_Start : out STD_LOGIC:='0');
end Debouncer;
 
architecture Behavioral of Debouncer is
 
Constant Clock_Divider_Counter_Top : integer := 50000;
Constant Debounce_Counter_Top : integer := 1000;
 
Signal Bounced_Start_Reg : std_logic := '0';
Signal Debounced_Start_Reg : std_logic := '0';
Signal Clock_Divider_Counter : integer range 0 to Clock_Divider_Counter_Top :=0;
Signal Debounce_Counter : integer range 0 to Debounce_Counter_Top := 0;
 
 
begin
 
Debounced_Start <= Debounced_Start_Reg;
 
Process (Clock)
Begin
    if rising_edge (Clock) then
        if RESET = '1' then 
            -- reset all assigned signals
            Bounced_Start_Reg <= '0';
            Debounced_Start_Reg <= '0';
            Clock_Divider_Counter <= 0;
            Debounce_Counter <= 0;
            
        else 
            
            -- Default assignments
            Bounced_Start_Reg <= Bounced_Start;
------------------------------------------------------------------------------------
 
            if Bounced_Start = '1' then 
                Clock_Divider_Counter <= Clock_Divider_Counter + 1;
            else 
                Clock_Divider_Counter <= 0;
            end if;
 
------------------------------------------------------------------------------------
            
            if (Clock_Divider_Counter = Clock_Divider_Counter_Top) then 
                Clock_Divider_Counter <= 0;
                if (Bounced_Start_Reg = '1') then 
                    Debounce_Counter <= Debounce_Counter + 1;
                else 
                    Debounce_Counter <= 0;
                end if;
            end if;
            
------------------------------------------------------------------------------------
            
            if  Debounce_Counter = Debounce_Counter_Top then 
                Debounced_Start_Reg <= '1';
                Debounce_Counter <= 0;
            else 
                Debounced_Start_Reg <= '0';
            end if;
            
------------------------------------------------------------------------------------            
        end if;
    end if;
End Process;
end Behavioral;



- Transmitter (the second module)


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
entity Transmitter is
    
    Generic (
                FIFO_Length : integer range 1 to 4 := 3;
                Byte : integer := 8;
                Bit_Time : integer :=5460               );
 
    Port    (
               Clock : in STD_LOGIC;
                Reset : in STD_LOGIC:='0';
                
                Data : in STD_LOGIC_VECTOR(31 downto 0):=(Others => '0');
                Send : in STD_LOGIC:='0';
                
                TxD : out STD_LOGIC:='1';
                TxD_Valid : out STD_LOGIC:='0'
                );
 
end Transmitter;
 
architecture Behavioral of Transmitter is
 
 
Type States is (Idle , Store_in_Queue , Set_Data , Transmit , Continue_Stop );
Signal Current : States := Idle;
 
Signal Send_Reg : std_logic:='0';
Signal Data_Reg : std_logic_vector(31 downto 0):=(Others => '0');
 
type Queue is array (0 to 3) of std_logic_vector(7 downto 0);
signal Data_Queue : Queue := (others => x"00");
Signal i : integer range 0 to FIFO_length-1 := FIFO_Length-1;
Signal TxD_Buffer : std_logic_vector((Byte-1) downto 0):=(Others =>'0');
 
Signal Time_Counter : integer range 0 to Bit_time - 1:=0; 
Signal Bit_Counter : integer range 0 to Byte+1 :=0;
 
Constant Stop_bit : std_logic :='1';
Constant Start_bit : std_logic :='0';
 
Signal TxD_Reg : std_logic :='1';
Signal TxD_Valid_Reg : std_logic:='0';
 
begin
 
TxD <= TxD_Reg;
TxD_Valid <= TxD_Valid_Reg;
 
Process (Clock)
Begin 
    if rising_edge(Clock) then 
        if reset = '1' then
            --  reset all assigned signals
            Send_Reg <= '0';
            Data_Reg <= (Others => '0');
            
            TxD_Reg <= '1';
            TxD_Valid_Reg <= '0';
            
            Current <= Idle;
            
            Time_Counter <=0;
            Bit_Counter <=0;
            
            i <= FIFO_Length - 1;
            
            
        else    
            -- default assignments
            Send_Reg <= Send;
            Data_Reg <= Data;
            
            Case Current is 
-----------------------------------------------------------------------         
 
                When Idle => 
                    if Send_Reg = '1' then 
                        Current <= Store_in_Queue;
                    else 
                        Current <= Idle;
                    end if;
                    
-----------------------------------------------------------------------
 
                When Store_in_Queue =>
                    Data_Queue (0) <= Data_Reg(7  downto  0);
                    Data_Queue (1) <= Data_Reg(15 downto  8);
                    Data_Queue (2) <= Data_Reg(23 downto 16);
                    Data_Queue (3) <= Data_Reg(31 downto 24);
                    
                    Current <= Set_Data;
                
-----------------------------------------------------------------------                 
                
                When Set_Data =>
                    TxD_Buffer <= Data_Queue(i);
                    Bit_Counter <= 0;
                    Current <= Transmit;
                    
-----------------------------------------------------------------------
 
                When Transmit =>
                    
                    if (Time_Counter /= Bit_Time-1) then
                        Time_Counter <= Time_Counter + 1 ;
                    else
                        Time_Counter <= 0;
                        if (Bit_Counter /= Byte+1) then 
                            if (Bit_Counter = 0 ) then
                                Bit_Counter <= Bit_Counter + 1;
                                TxD_Reg <= Start_Bit;
                                TxD_Valid_Reg <= '1';
                            else
                                Bit_Counter <= Bit_Counter + 1;
                                TxD_Reg <= TxD_Buffer(Bit_Counter-1);
                                TxD_Valid_Reg <= '1';
                            end if; 
                        else
                            Current <= Continue_Stop;
                            TxD_Reg <= Stop_Bit;
                            TxD_Valid_Reg <= '0';
                        end if;
                    end if;
 
-----------------------------------------------------------------------
                
                When Continue_Stop => 
                    if i = 0 then 
                        Current <= Idle;
                    else
                        i <= i - 1;
                        Current <= Set_data;
                    end if;
                
-----------------------------------------------------------------------
 
            End Case;
        end if;
    end if;
end Process;
 
end Behavioral;




When FIFO_Length is 1,2 or 4 everything is fine and perfect.
But When FIFO_Length is 3 and whe push the start button on the board
the computer recieves 2 bytes instead of 3 every time!!!!!!

As an example : I want to send the three right bytes of Data which is X"0F 00 FF".

These three bytes are put in the 3 lower bytes of Data_Queue.
(Data_Queue(0)=FF Data_Queue(1)=00 Data_Queue(2)=0F )

After that the transmitter would send each of those three bytes from Data_Queue(2) to Data_Queue(0) one by one.

But in the computer I receive this:

1) 00001111 (0F)
2) 00000000 (00)

and after I push the start button once more (for the second time)

3) 11111111 (FF)
4) 00001111 (0F)

Like that it only can send 2 bytes each time!!!!!!! :-o

This only happens when FIFO_Length is 3.

If you have any suggestions please let me know
thank you
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top