Jump to content
  • 0

Something simple is apparently impossible. Incr/decr number.


Tickstart

Question

Hi, I'm just beginning with FPGA's, I bought a Basys 3 this past tuesday.

I'm trying to increment a 4-bit value with the on-board Up-button and decrease it with the Down-button. What is a straight forward way of doing this?? I've tried to get this to work for the last two days. The buttons are debounced, so that's not an issue.

I've tried keeping the value in a signal vector and depending on which button is pressed, add a one or add a two's complement -1. The adding is done with a 4 bit adder I built, which works.

 

I'm sort of new to VHDL and digital design so any useful tips or hints or general advice are very much appreciated.

Instead of getting 1, 2, 3, 4, 5, 6 etc when pressing the Up button, I get a very weird pattern.. See attached photo (the arrows were meant to show that the pattern repeated itself after a number of presses).

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--use IEEE.STD_LOGIC_UNSIGNED.ALL;
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity btn_map is
    Port ( btnD, btnU : in STD_LOGIC;							--btnU/D stands for up/down
           key : out STD_LOGIC_VECTOR (3 downto 0));
end btn_map;

architecture Behavioral of btn_map is

component trig_4b_Adder is
    Port ( clk : in STD_LOGIC;			--I modified the adder with some D-flops to not create a combinatorial loop (hence the clk)
           c, y : in STD_LOGIC_VECTOR (3 downto 0);				--c/y are the two 4-bit inputs to the adder
           s : out STD_LOGIC_VECTOR (3 downto 0));				--s = result
end component;

signal val, add_sub, new_key : STD_LOGIC_VECTOR (3 downto 0) := (others => '0');
signal trigger : STD_LOGIC := '0';		-- clock for the adder, "keypressed"

begin

    Adder: trig_4b_Adder port map(clk => trigger, c => val, y => add_sub, s => new_key); -- add_sub is either the +1, -1 or 0
    
    process(btnD, btnU)
        variable minus : STD_LOGIC_VECTOR (3 downto 0) := "1111";
        variable plus : STD_LOGIC_VECTOR (3 downto 0) := "0001";
        variable zero : STD_LOGIC_VECTOR (3 downto 0) := "0000";
        begin
            if btnD = '1' then
                add_sub <= minus;
            elsif btnU = '1' then
                add_sub <= plus;
            else
                add_sub <= zero; -- (sub zero lol)
            end if;
        end process;
                               
    trigger <= btnU or btnD;		-- start the adder
    val <= new_key;	-- I want to save the result from the adder till next clock cycle	-- these two lines of code feel bad for some reason,
    key <= new_key; -- key is the output from this module					-- like my design is inherently flawed somehow..
    
end Behavioral;

 

IMG_20170422_040209832.jpg

Link to comment
Share on other sites

Recommended Posts

Here's where being able to use a simulator might help.

Your process is not clocked. Think about time, delay, storage and what's going on in your process. Simulate it and see what the simulator thinks of your code. I've already given you a broad hint in mentioning that I use concurrent statements and clocked processes ( OK in my state machines I use two processes, one clocked and one not...) I try and keep my concurrent statements and processes  separate though sometimes this makes the code hard to read so I don't. I keep track of processes and signals associated with each clock domain using comments and keeping them together in the code.

For the record it's entirely possible to have an whole design be combinatorial and not use a clock. I've had this as a work requirement for special purposes. Anyone doing that had better know what their doing and be very experienced if the design has any complexity at all; not for the inexperienced.

You can shut me up for good by not posting your simulation experience or question related to getting a simulation working as your next post....

 

Link to comment
Share on other sites

On 4/25/2017 at 8:35 PM, zygot said:

Take a few deep breaths and forget about everything in the past... think of this as an easier way to re-boot your HDL journey.

Yes, I saw it as an oppurtunity to validate my progress and perhaps improve on things I did worse first time round.

I've been quite busy this week so not much time over for programming. Anyway, my up-/down counter still doesn't work.

On 4/22/2017 at 3:50 PM, Notarobot said:

Hi, here is a good explanation and code for the debouncer.

 

Thanks again for the debouncing theory, the picture in the link really helped, and made it fun to implement instead of just copying someone else's code. I modified it to act in a "key released"-fashion.

 

Anyway, back to the matter at hand: What's wrong with my code?

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.all;

entity add_sub is
    Port ( inc, dec : in STD_LOGIC;
           c : out STD_LOGIC_VECTOR (3 downto 0));
end add_sub;

architecture Behavioral of add_sub is

signal count : STD_LOGIC_VECTOR (3 downto 0) := (others => '0');

begin

    process(inc, dec)
    begin
        if inc = '1' then
            count <= count + 1;
        elsif dec = '1' then
            count <= count - 1;
        else
            NULL;
        end if;   
    end process;
    
    c <= count;

end Behavioral;

The number shown on the display jumps all over the place, from A to 9, then F, 8, E, E, F, 6, 9 whatever. 

Link to comment
Share on other sites

@Tickstart,

Can I try to answer your question, "Why does it need to be clocked?"

Your count signal is 4-bits wide.  When you wish to increment this, there's an "equation" or "logic" that needs to take place for all 4 bits.  This function depends upon inc, dec, and the previous counter--so it is roughly a six bit equation.  The problem you have without clocking is that some of those bits will be ready before others.  Sure, they all require one LUT, but routine between them will be different.  The earlier bits will then get used in the equation for the later bits and thus the inputs will not be stable until all of the outputs are determined. 

So ... what results will you expect from a function whose inputs are changing while the function is being evaluated?

Dan

Link to comment
Share on other sites

2 hours ago, D@n said:

So ... what results will you expect from a function whose inputs are changing while the function is being evaluated?

 

Well yeah, that makes sense. But I have some modules which are not clocked (combinatorial..?) nested into the other ones, how do you know when to clock and so on? A regular AND-expression is not clocked for instance but I never hear people complain about that.. Not exactly sure how to keep track of when to clock or not, surely there must be some key insight I'm missing.

Link to comment
Share on other sites

@Tickstart,

The difference between what you proposed above and what you've seen in the past is sometimes called a "logic loop".  In your proposal above, you have logic depending upon itself with no clock.  (This is bad)  In the logic  you've seen before, everything could eventually be traced back to clocked logic somewhere.  The distance between the final piece of logic and the clock that started it off determines the minimum clock period (maximum clock rate) for your board.

Dan

Link to comment
Share on other sites

Dear @Tickstart

I am afraid you are getting confused with multiple points of view. Let me add one more.

FPGAs are used as event driven machines. They produce output based on combination of inputs and these outputs change when there is change on input(s). It can be completely asynchronous machine if you don't need time stimulus. Then there is no need for clock. If your design have regular repetitive event then a clock is your help. Clocks a needed also for generating of signals, communication, and implementing delays.  In VHDL many processes have clock in a list of stimuli but it depends on its purpose. It is necessary for synchronization only.

Events in many control systems are random and the beauty of FPGA that they can respond almost immediately as oppose to clocked processor based controller. The latest industrial PLCs are constructed on FPGAs to achieve fast and deterministic response.

Good luck!

P.S. It should be mentioned that VHDL has operators for simulation only. They are not synthesizable, for example "wait". Clock driven counter is used instead for the implementation.

Link to comment
Share on other sites

Some pointers to absolute beginners in FPGA development.

1. FPGA development using VHDL or Verilog isn't the same as software development.  Using an HDL to express logic in an FPGA is Computer Aided Digital Design. The place to start is understanding the basic concepts of digital design. Take a course in digital design. Read a book about digital design. Using an HDL for logic synthesis is more complicated than using a computer language like C... there are a lot more things that have to be taken into consideration.

2. Once you've grasped the concepts of digital design you're ready to learn Verilog or VHDL in the context of logic synthesis. In the beginning you don't have to understand how a synthesis tool interprets your HDL code and ends up with a configuration file that programs an FPGA. You DO have to understand all of the elements of the HDL that's in your code in the context of digital logic.

3. Once you've grasped the basics of digital design and using an HDL to do digital design you are ready to understand the code for an entity or module written by someone who does. Then you're ready to understand the HDL in a testbench meant to verify that code. The you can learn how to use a simulator to verify the HDL.

4. Once you gotten to this point you are ready to write code for your first module. The very next step is to write a testbench for that module, simulate it and see what's going on. Verification is part of the HDL design process. Trying to do one without the other is just silly.

5. I you ask for help and someone gives it to you then you are obliged to at least try and follow their instructions. If their instructions aren't helping then you should find help from someone else. Simply ignoring instructions is an insult to you and anyone trying to help you. It is arrogant to think that you can use a language that you know that you don't understand and continue to try and get useful results by writing code. The verification step is helpful in finding errors in syntax, timing and design concept. It isn't a cure for trying to use a language that you don't understand.

I post this more explicit rehash of what I've already said in this thread because I suspect that @Tickstart isn't a real person but a computer simulation... perhaps Yahoo trying to get into IBM's Watson space. A lot of things would start making sense to me if this is true.

 

Link to comment
Share on other sites

 

@Tickstart

Now that the commentators have handed you Dbounce.vhd and a testbench and thrown you back into the drink waving goodbye and saying"Have a nice swim!" How's it working out?

In DBounce.vhd:

Did you notice that the input signal nreset is expected to be synchronized to signal clk? If you use this module did you make sure that your nreset works with this code?

Did you notice that BD_OUT is declared as type buffer? Type buffer is actually new to me and  created some homework to do.  I typically have internal copies of signals declared as type out on the entity port and use a concurrent statement to assign the port signal to the internal signal. Of course I only do this when I want to read the state of that port signal when using type OUT. Just curious, were you familiar with type buffer? Did you try and synthesize DBouncd.vhd?

Personally, I find that the construction of DBounce.vhd is a bit odd. But that doesn't matter as it is presented as an example for de-bouncing a push-button, or anything else involving moving contacts.

Did you notice the sensitivity lists for the processes? Wonder why some have more than clk?

What did you think about ( in the context of the previous question ):

   process(clk, button_in)
    begin        
        if(rising_edge(clk)) then
            if(nreset = '0') then
                DFF1 <= '0';
                DFF2 <= '0';
            else
                DFF1 <= button_in;
                DFF2 <= DFF1;
            end if;
        end if;
    end process;

Did you simulate DBounce using the testbench?

Did you wonder if your simulator warns about potential metastability? Try aligning the button_in signal exactly in time with the clk by making this change in the testbench clocking process:

      clk <= '1', '0' after clock_period / 2;

Do you understand the concepts of setup and old time? Did your simulator? ( I'm assuming that you figured out how to sun the simulator in Vivado or ModelSim, change the source, re-compile, and restart a simulation as well as display the signals of interest.

What I like about the testbench is that it does  show you a way to have your simulator terminate when your testbench is over. Did you catch how that works. There are other ways to do the same thing. All of my simulations end in FAILURE but that's the way that I like it. This method just doesn't give you  a message that it did.

Did you wonder about the timing of the button_in assertions? Do the numbers make any difference?

Did you try running synthesis and then a post_synthesis timing simulation? ( this isn't the best example for timing simulations...)

Were any of these questions of interest to you?

I ask these questions out of curiosity and as a bit of feedback.

Link to comment
Share on other sites

OK This is my last post on this thread, I promise! I wanted to say this and forgot ( not withstanding D@n's previous comments )

On tools:
I have a large garden behind my house. Near the garden is a shed and in the shed are a variety of tools that for all appearances are pretty simple devices; like a hoe, a shovel, a rake. Of, course using any of them effectively involves quite a bit more complexity than one might suppose. I'm referring a sight twist of the wrist for a particular effect, a slight alteration of angle of attack, etc. Now, if my aim is to dig a 2 foot hole for a post and I blindly pull out the closest tool in the shed and start flailing at the ground with it, and the tool happens to be a rake you might imagine that I'll spend many hours of frustrating work and never accomplish my goal. Why would anyone do such a thing with something as complicated as a computer-aided design language? But at some point we all do usually because we think that we're saving time or someone is pushing us to get results without taking the time to use our brains.

On testbenches:
One of the rarest gifts one can obtain is insight. You can't have valuable insight without a really solid foundation of knowledge; but knowledge alone doesn't often produce insight (I fully expect push-back with this statement). A simulator is a tool that can offer insight with surprising frequency if used correctly. It can also lie to you and tell you how wonderful you and your design are if used incorrectly. The same concept applies to all computer-aided design and lab tools.

On Personal behaviours:
We all know Newton's observation that "a body in motion tends to stay in motion". And we know that there are forces that work against that body having inertia; such as resistance.
There is an analogy to personal work ethic that has slightly different physics. If you go about your work in a sloppy, unstructured, mindless and lazy manner today, you will tend to gather momentum in a very unfortunate direction of sloppier, lazier, and less productive tomorrow. On the other hand it takes a lot of effort to maintain a course in the other direction as there are numerous forces working against you

I realise that D@n and I arrive a t different conclusions but I don't see a real competition here.

I'm done... really this time.

Link to comment
Share on other sites

12 minutes ago, zygot said:

OK, I'll try an wrap this up and go on to other things.

Sigh, and here I thought this thread had already been wrapped up.  :)

12 minutes ago, zygot said:

My advice:

So, I advise you to put off, if you can, getting your project to work until you are comfortable using your tool of choice. ...  That's the best advice I have to offer.

Ouch!  Not my advice.  My advice: This is a perfect learner's project, I love it!  --keep going!  After a couple such projects, you will then be "comfortable using your tool of choice."

Also, I caught your comment above about having worked in the field for 20+ years and that you use test benches.  Ignoring all of the rest of the stuff you had to say about the importance of test benches, this one piece was enough to highlight for me that you found them valuable and that your recommendation had some weight behind it.  That simple statement above my have been the "best advice" you've offered.

12 minutes ago, zygot said:

- Do read and try to understand well written code, and try to figure out why it is well written code, from experienced people even if the goal of their task is not very interesting. ...  This advice works for just about any endeavour.  

On that note, thank you, @hamster!  I learned a lot from the several debouncing examples you posted above.  Thank you, for walking through several versions of how to do the same thing and discussing the problems with each.  Again, I learned a lot.

Dan

 

Link to comment
Share on other sites

OK, I'll try an wrap this up and go on to other things.

You'll notice that my "help" has not been in the form of providing code examples, answering your questions directly or providing exactly what it is that you are looking for. Others have done that so you are being pretty well serviced in that regard. What I'd like to do is try and expand your perspective. Intelligence, educational degrees, and even to an extent experience are all nice things to have when trying achieve success in any endeavour. In my experience, attitude, having a structure to your thinking and problem solving efforts, being willing to continually challenge your assumptions and work product are far more important in determining what kind of experiences you'll have in life. This is true whether you are a student waiting to enter professional life or even a seasoned old hand just playing around with a new FPGA board. Believe me I understand the desire for immediate (OK immediate is a relative term ) gratification in seeing your project perform. You'll sustain your interest in FPGA or any other other endeavour far longer by forcing other goals into you thinking.

My advice:

- Your brain is telling you something when it complains that the tool ( in this case VHDL ) that you're using is confusing and flawed ( this is my interpretation of your comment ). The truth is that no tool is perfect for all tasks, or perfect for any for that matter ) but when multitudes of people use the same tool and achieve success the problem is not likely the tool. Your brain is telling you that perhaps you need to learn how to use your tools. So, I advise you to put off, if you can, getting your project to work until you are comfortable using your tool of choice. This will make your eyes roll... in VHDL integers aren't infinite... in fact the largest integer is a signed 32-bit value. Ouch! But the explicit advice here is to learn to listen to your brain and figure out what it is trying to tell you. That's the best advice I have to offer.

- Do read and try to understand well written code, and try to figure out why it is well written code, from experienced people even if the goal of their task is not very interesting. In life the shortest distance between two points is rarely a straight line. Somewhere in the documentation for OCTAVE the authors mention a quote from a book of my youth "How to build a Telescope". I'm paraphrasing here but the quote goes like this: " It takes less time to build a 5" mirror and an 8" mirror than it does to build an 8" mirror". As you probably don't have the book I'll explain. The reference is to the skill involved in hand grinding and polishing a glass bank into a shape suitable for use as an optical mirror that could be used in building a telescope. If you read the book you'll realize that what's involved in ending up with a usable 8" mirror is far more challenging than for a 5" mirror.You'll waste far less time and glass honing your skills and training your brain, hands and eyes trying to achieve what you really want by preparing yourself with a succession of less demanding objectives. This advice works for just about any endeavour.  

 

 

Link to comment
Share on other sites

Again, the following comments are not an argument with Hamster's statements about really long simulation times or "commercial quality" code verses "messin' around" quality code but I offer a slightly different perspective.

I write testbenches for my  "messin' around" quality code as often as for my "commercial quality" code. You can always figure out a way to shorten overly long simulation times when doing RTL level simulation. Timing simulations are a discussion for another thread. Really, there can be many types of verification exercises that concentrate on different aspects of the design code. Indeed, if you see writing verification code as an exercise in forcing yourself to think about where the possible issues might be this becomes a welcome and challenging habit. Actually writing good verification code can be more tricky and require more creativity than the actual design code. I don't create designs for hardware that I don't have and so testbenches are rarely the endpoint.... though occasionally I try out an idea just for experimentation purposes, expecting to use the idea later in a real project.

One thing that hardware can't tell you is if there are subtle issues with your design. Sure seeing a seven-segment display module change characters as expected might look like everything is just fine but really now... what's the fastest event that you can detect visually? Do you always believe what your see? Even if you own a really good oscilloscope and other test equipment there are things that you are likely to miss that a simulation can reveal. Simulations are not the be-all or end-all of good design practice but I believe that it's easy to get sloppy if you don't hold yourself to a certain standard.. even when just playing around for fun. Now I admit that not all of my testbenches are exhaustive exercises ( you can spend you life just testing stuff if you allow it to happen ) as I usually have a larger goal in mind. But I don't want to start bad habits and work by hope an assumptions that I got my design code correct. 

By the way your testbench can write out thousands of signal values to a text file for analysis in OCTAVE or MatLAB.

I used to be astonished, fixing other peoples software code how WRONG code implementations and even sometimes how wrong the basic concept can be but still look kinda correct.. mostly... most of the time. 4-5 people will have messed with it, patched it, massaged it and never understood what was going on all the time making imaginary fixes. You end up peeling back layers of changes until you eventually either get to the initial problem or just end up replacing it ( when allowed by the $$$ people...) Scary!

Anyway, if you are just starting out and learning an HDL language I heartily recommend that you get comfortable with verifying your "other" code... you know that one that you want to see working on you new Basys3 board. You may not guarantee that your design is bullet-proof developing a habit of using testbenches but I guarantee that if you start writing lots of design code that goes straight to hardware you will be fooling yourself that it's "working".

A debugged program is one for which you have not yet found the conditions that make it fail. -- Jerry Ogdin

 

Lastly, I don't get paid by "Council for Testbenches" or anyone else or see myself as an evangelist for the cause...

Link to comment
Share on other sites

@hamster,

Using this occasion I wanted to thank you for you contributions. I've found a lot to learn from your site as well as from posts on this forum.

The debouncer code I posted is not mine. It is very similar to yours and I chose it because it has pretty clear description.

Also in my practice I use testbenches whenever I can. In cases when FPGA controls the equipment trial and error approach would be very costly. When the testbench is too complicated we used to built a physical test setup. Exhaustive testing is the major prerequisite of success in commercial environment.

Link to comment
Share on other sites

5 hours ago, Notarobot said:

Having spare time on hands and following the last post I took a liberty to create a testbench using published materials. The VHDL code was taken from  here and the template for the testbench was created using this online tool here

The testbench is for the debouncer only and it's very simplistic but sufficient as a starting point. It is easy to copy internal signals to the entity port and get insights into its internal behaviour.

Thanks!

TB_Debouncer.vhd

DBounce.vhd

@Notarobot's  code is much the same as mine in function. But style is a different. 

I wonder why it isn't just a single process like this:

process(clk)
    begin
        if(rising_edge(clk)) then
            if nreset = '0' then
 	        if DFF1 /= DFF2 then
                    q_reg <= (others => '0');   -- reset counter
                elsif q_reg(N-1) = '0' then 
	            q_reg <= q_reg + 1; 
                else
                    DB_out <= DFF2;
                end if;
                DFF1 <= button_in;
                DFF2 <= DFF1; 
            else
                q_reg <= (others => '0');
                DFF1 <= '0';
                DFF2 <= '0';
	    end if;
        end if;
    end process;
Link to comment
Share on other sites

Oh, and with regards to test benches. Somethings are hard to prove with test benches, and easy to prove in real life. Especially things that involve timescales needed for human interaction.

Take the seven-segment display module. A 'full' test bench for that would be hard (test each digit for each value - 64 test patterns, each requiring at least enough time to update all output signals, 300 million cycles simulation cycles, and each blink test would need at least 64 million cycles for the counter to roll over - so half a billion simulation cycles.

Then it would need to inspect the simulation output, to check that the correct LEDs were on at the correct time.

Far easier to connect the digits to the switches on the dev board, the buttons to the blink inputs, download the design and manually verify it - a physical/manual test-bench :-) 

So I write VHDL testbenches when I know I will need to debug or otherwise inspect behavior of the internals.

For a button debouncer my personal view is that a test bench is a bit over the top, and it is hard to have the correct assumptions of how bad a really bad switch is -  and all my projects are for my own enjoyment, so I don't have to design to commercial standards of proof.

 

 

Link to comment
Share on other sites

@Tickstart

Here's my equivalent of the 7-seg code you posted, just for comparison - it is just a hack, so the blink rate and update rates were just convenient, rather than to any hidden spec!

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity seven_seg is
    Port ( clk : in STD_LOGIC;
           segments   : out STD_LOGIC_VECTOR (6 downto 0);
           seg_select : out STD_LOGIC_VECTOR (3 downto 0);
           digit0     : in STD_LOGIC_VECTOR (3 downto 0);
           blink0     : in STD_LOGIC;
           digit1     : in STD_LOGIC_VECTOR (3 downto 0);
           blink1     : in STD_LOGIC;
           digit2     : in STD_LOGIC_VECTOR (3 downto 0);
           blink2     : in STD_LOGIC;
           digit3     : in STD_LOGIC_VECTOR (3 downto 0);
           blink3     : in STD_LOGIC);
end seven_seg;

architecture Behavioral of seven_seg is
    signal digit_count : unsigned(25 downto 0);
    signal to_decode : std_logic_vector(3 downto 0);
begin
                                    -- GFEDCBA
   with to_decode select segments <= "1000000" when "0000", -- Zero
                                      "1111001" when "0001", -- One
                                      "0100100" when "0010", -- Two
                                      "0110000" when "0011", -- Three
                                      "0011001" when "0100", -- Four
                                      "0010010" when "0101", -- Five
                                      "0000010" when "0110", -- Six
                                      "1111000" when "0111", -- Seven
                                      "0000000" when "1000", -- Eight
                                      "0011000" when "1001", -- Nine
                                      "0001000" when "1010", -- A
                                      "0000011" when "1011", -- B
                                      "1000110" when "1100", -- C
                                      "0100001" when "1101", -- D
                                      "0000110" when "1110", -- E
                                      "0001110" when others; -- F
                                 
process(clk)
    begin
        if rising_edge(clk) then
            seg_select <= "1111"; -- active low!
            case digit_count(digit_count'high-6 downto digit_count'high-7) is
                when "00" =>
                    seg_select(0) <= blink0 AND digit_count(digit_count'high);
                    to_decode  <= digit0;                    
                when "01" =>
                    seg_select(1) <= blink1 AND digit_count(digit_count'high);
                    to_decode  <= digit1;                    
                when "10" =>
                    seg_select(2) <= blink2 AND digit_count(digit_count'high);
                    to_decode  <= digit2;                    
                when others =>
                    seg_select(3) <= blink3 AND digit_count(digit_count'high);
                    to_decode  <= digit3;                    
            end case;
            digit_count <= digit_count + 1;
        end if;
    end process;
end Behavioral;
Link to comment
Share on other sites

Having spare time on hands and following the last post I took a liberty to create a testbench using published materials. The VHDL code was taken from  here and the template for the testbench was created using this online tool here

The testbench is for the debouncer only and it's very simplistic but sufficient as a starting point. It is easy to copy internal signals to the entity port and get insights into its internal behaviour.

Thanks!

TB_Debouncer.vhd

DBounce.vhd

Link to comment
Share on other sites

Pardon me for back-tracking but I just re-read this thread a bit more carefully. The truth is that I just trust Hamster's opinion and didn't bother to read all of his code carefully to understand what he was trying to say.

He writes earlier:"The take-away wisdom being "always synchronise your async inputs" and "try really hard to never have more than one clock"

I'm not arguing with Hamster as I understand what he is trying to say but this sentence just irks me a bit so I feel the need to comment. As far as synchronising signals goes I think that it would be better to say that for all clocked processes signals that change due to any event, combinatorial logic or a different clock than the one in your process sensitivity list has to be conditioned (including synchronized) to the clock in your process. This is to avoid the effects of metastability in the process outputs. Metastability is unavoidable but you can, and MUST, minimize it's effects in the downstream logic states.  As to having more than one clock; this is often unavoidable. I've worked on systems with 10's of clock domains all of them being necessary. You DO have to synchronize any signal that changes due to a clock in a different clock domain to the clock listed in your process sensitivity list. There are a few standard ways to to do this some pretty good and some not so much for all situations. What I'd say is that even though the HDL languages allow you to decide that ANY signal can be used as a clock this is not good practice. Even good clock signals that are the outputs of expensive clock modules have jitter, drift, noise and other encumbrances that don't do your design efforts any good. Using a signal that is derived from combinatorial logic, though often a temptation, is a really bad idea for reasons that I won't go into at this time. FPGA devices have special clocking lines, clocking IO pins, and resources for a reason. The synthesis and routing tool logic expects signals labelled as clocks to behave as high quality clocks will have a lot of problems with badly behaved "clocks". Now I'm sure that there's someone who might read my "clarification" of Hamster's point and have as much problem with my comments as I had with Hamster's but I don;t think that this is the thread for detail on that level.

Since Hamster feels that giving you a code example is in your best interest ( I don't but nor do I take issue with doing so ) perhaps he would be generous enough to supply you with a nice testbench. Even if you have perfectly good code to work with you should know how to test it in simulation. Testbenches are your friend, not your enemy.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...