• 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

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

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

By the way , the more you write the more convinced that you really need some help grasping the basics. VHDL was designed as a simulation language but was co-opted for synthesis because of its popularity. The language doesn't care about issues of synthesis but the synthesis tool sure does. A cursory reading of the syntax is not likely to be a helpful guide. With this in mind it should be clear that you can write perfectly fine VHDL code that can't be synthesized into something that works on hardware.

Link to comment
Share on other sites

1 hour ago, zygot said:

Your process is not clocked. Think about time, delay, storage and what's going on in your process.

Why does it have to be clocked? Please just tell me. What about time, delay and storage? Honestly I have no grasp of what a "signal" is in vhdl or in the fpga (a LUT or something?) but rather than telling me how ignorant I am please enlighten me. It's weird to me that some of my code works just fine and other parts are just impossible to implement.

1 hour ago, TrapperBob said:

You are "counting" on count to have state when you write count <= count + 1 or count <= count - 1. However you have a combinatorial process defined.

Well, I don't know, maybe? Do I have to construct a register to store data?

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

@Tickstart,

You said debouncing isn't an issue, yet I must be missing your debouncing code above.  Depending on how you are handling your debouncing, the following may or may not apply:

My guess is that you are struggling with a metastability issue on those input buttons.  A metastability issue has to deal with when the button transition happens with respect to the clock.  If it happens long enough before a clock, the signal is valid.  If the transition happens too close to the clock, the bit that gets read from the port might be neither a one nor a zero, and might have different logic consequences depending upon what it is being fed into.  Because when the button press happens is completely asynchronous to the clock (go ahead and try to synchronize your finger to a 10ns boundary, I'd like to watch ;) ), sometimes there will be enough time for the bit to settle, sometimes not.  Now take this unsettled bit and try to apply logic to it.  Will it work?  Maybe.  Sometimes.

Try this: register those input buttons on a clock into a register by themselves.  After two clocks registering these into their own registers, at the rising edge of the clock, you'll have a stable value that you can then use as logic within your design.

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

I Hadn't picked up a board in a while (we are trying to get our house ready for sale, so I've been picking up paint brushes!)

So here is a quick design I knocked out to achieve your aim, with all the tricks I think need to be added. I've found my Basys3 and it works for me - it might work for you too.

The big difference is "use IEEE.NUMERIC_STD.ALL;" and, it allowing the use of "unsigned" data type, to which you can add and subtract.

Feel free to ask questions - most of the design decisions are quite arbitrary and you might have better ideas! 

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

entity up_down is
    Port ( clk      : in  STD_LOGIC;
           btn1_raw : in  STD_LOGIC;
           btn2_raw : in  STD_LOGIC;
           leds     : out STD_LOGIC_VECTOR (3 downto 0));
end up_down;

architecture Behavioral of up_down is
    -- For synchronizing into the clock domain
    signal btn1_meta       : std_logic := '0';
    signal btn2_meta       : std_logic := '0';
    signal btn1            : std_logic := '0';
    signal btn2            : std_logic := '0';
    
    -- Fro debouncing the synchronised signals 
    -- Length defines the 'hold time' for the debouncing - 2^19 cycles
    signal debounce1       : unsigned(19 downto 0) := (others => '0');
    signal debounce2       : unsigned(19 downto 0) := (others => '0');
    signal debounced1      : std_logic := '0';
    signal debounced2      : std_logic := '0';

    -- For detecting the rising edges of the debounced signals
    signal debounced1_last : std_logic := '0';
    signal debounced2_last : std_logic := '0';
    
    signal count           : unsigned(3 downto 0) := (others => '0');
begin
    leds <= std_logic_vector(count);
  --------------------------------------------
  -- Process to synchronise the button signals
  --------------------------------------------
sync_proc: process(clk)
    begin
        if rising_edge(clk) then
            btn1      <= btn1_meta;
            btn2      <= btn2_meta;
            btn1_meta <= btn1_raw;
            btn2_meta <= btn2_raw;
        end if;
    end process;

   ----------------------------------------------
   -- Process to debounce the buttons, to generate
   -- 'debouncedX' that is stable for 2^19 cycles
   -----------------------------------------------
debounce_proc: process(clk)
    begin
        if rising_edge(clk) then
            if btn1 = '0' then
                if debounce1(debounce1'high) = '1' then
                    -- Count down if the button is lifted
                    debounce1 <= debounce1 - 1;
                else 
                    -- snap down to zero once the MSB clears
                    debounce1 <= (others => '0');
                end if;
            else
                if debounce1(debounce1'high) = '0' then
                    -- Count up if the button is pressed
                    debounce1 <= debounce1 + 1;
                else 
                    -- snap down to zero once the MSB is set
                    debounce1 <= (others => '1');
                end if;
            end if;
            debounced1 <= std_logic(debounce1(debounce1'high));
            
            if btn2 = '0' then
                if debounce2(debounce2'high) = '1' then
                    -- Count down if the button is lifted
                    debounce2 <= debounce2 - 1;
                else 
                    -- snap down to zero once the MSB clears
                    debounce2 <= (others => '0');
                end if;
            else
                if debounce2(debounce2'high) = '0' then
                    -- Count up if the button is pressed
                    debounce2 <= debounce2 + 1;
                else 
                    -- snap down to zero once the MSB is set
                    debounce2 <= (others => '1');
                end if;
            end if;
            debounced2 <= std_logic(debounce1(debounce1'high));            
        end if;
    end process;
    

   ----------------------------------------------
   -- A process to detect the rising edges in the  
   -- debounced signals and then update the counter
   -----------------------------------------------
count_proc: process(clk)
    begin
        if rising_edge(clk) then
            if debounced1 = '1' and debounced1_last = '0' and
               debounced2 = '1' and debounced2_last = '0' then
               -- both buttons pressed at the same time.
                NULL;
            elsif debounced1 = '1' and debounced1_last = '0' then
                -- Count up
                count <= count + 1;
            elsif debounced2 = '1' and debounced2_last = '0' then
                -- Count down
                count <= count - 1;
             end if;
             -- Remember button states for next cycle
             debounced1_last <= debounced1;
             debounced2_last <= debounced2; 
        end if;
    end process;
end Behavioral;
Link to comment
Share on other sites

1 hour ago, D@n said:

@Tickstart,

You said debouncing isn't an issue, yet I must be missing your debouncing code above.  Depending on how you are handling your debouncing, the following may or may not apply:

My guess is that you are struggling with a metastability issue on those input buttons.  A metastability issue has to deal with when the button transition happens with respect to the clock.  If it happens long enough before a clock, the signal is valid.  If the transition happens too close to the clock, the bit that gets read from the port might be neither a one nor a zero, and might have different logic consequences depending upon what it is being fed into.  Because when the button press happens is completely asynchronous to the clock (go ahead and try to synchronize your finger to a 10ns boundary, I'd like to watch ;) ), sometimes there will be enough time for the bit to settle, sometimes not.  Now take this unsettled bit and try to apply logic to it.  Will it work?  Maybe.  Sometimes.

Try this: register those input buttons on a clock into a register by themselves.  After two clocks registering these into their own registers, at the rising edge of the clock, you'll have a stable value that you can then use as logic within your design.

Dan

Worse than metastability is just simple timing issues - a signal takes a short period of time to get along the wires in the FPGA - just using indicative numbers, maybe a nanosecond or so.

If the signal for a button is being used in the top left and bottom right of the chip the downstream logic see a skewed value on the wire. If a design is running at 100MHz (10ns cycle) there is a 1 in 10 chance of failure (a metastability error is much less likely 1 in 1 million chance)

The solution is the same though - for any asynchronous signal latch it in a flip-flop before you use it.

Link to comment
Share on other sites

Oh, here's a few comments on the O.P's code.

Most of the problems is that the adder's clock isn't an actual clock signal - it is the two buttons ORed together. To make this sort of design work you want an adder that has a "Clock Enable" ("CE") signal. That way the clock can tick every cycle, and the 'trigger' signal can drive the "Clock Enable" input.

The more subtle issue is that their is something close to a race condition - the pressing of the buttons changes the input to the adder, but the pressing of the button also triggers the adder. Which will happen first? Who knows?

An experiment in bad form could be to have trigger be "trigger <= NOT(btnU or btnD);" - that way the adder would be clocked by the falling edge of the button signal (i.e. on the downpress the input is set to either 'minus' or 'plus', and on the lift the adder is clocked. However, you still have a race condition - will add_sub be reset to 'zero' before or after the adder actually responds to the clock input?

            if btnD = '1' then
                add_sub <= minus;
            elsif btnU = '1' then
                add_sub <= plus;
            else
                add_sub <= zero; -- (sub zero lol)
            end if;

If you change that bit of code to this, as well as the change to trigger to clock on button lift:

            if btnD = '1' then
                add_sub <= minus;
            elsif btnU = '1' then
                add_sub <= plus;
            end if;

It will most likely give warnings about inferred latches, but it might work as expected.

It is still not good synchronous design though, but still might be interesting. 

 

PS. Good choice of board to learn on too :-)

Link to comment
Share on other sites

Hey guys, thanks for your responses!!

5 hours ago, hamster said:

Most of the problems is that the adder's clock isn't an actual clock signal - it is the two buttons ORed together. To make this sort of design work you want an adder that has a "Clock Enable" ("CE") signal. That way the clock can tick every cycle, and the 'trigger' signal can drive the "Clock Enable" input.

 

An adder with a constant clock but with an 'enable' makes perfect sense to me, thank you for that. I knew what I was doing was unorthodox and in bad practice, but I'm just getting started with VHDL and digital design in general so I'm sort of in the dark about what's appropriate and not. Moving from Haskell to VHDL is quite jarring ;)

That's what I will try next, if that doesn't work I'll come back to you. Not sure how I should implement the enable-functionality though, I'll probably screw up again. This is what my newly D-flipflopped full adder looks like:

entity trig_FA is
    Port ( clk, x, y, c_in : in STD_LOGIC;
           s, c_out : out STD_LOGIC);
end trig_FA;

architecture Behavioral of trig_FA is

component D_flipflop
    Port ( clk, d : in STD_LOGIC;
           q : out STD_LOGIC);
end component;

signal d_s, d_c_out : STD_LOGIC;

begin

    dff_s: D_flipflop port map(clk => clk, d => d_s, q => s);
    dff_c: D_flipflop port map(clk => clk, d => d_c_out, q => c_out);
    
    d_c_out <= (x and y) or (c_in and (x xor y));
    d_s <= x xor y xor c_in;

end Behavioral;

I guess the answer is to modify the D-flipflop to accept an enable huh.. Yep, I shall make it so!

7 hours ago, D@n said:

You said debouncing isn't an issue, yet I must be missing your debouncing code above.

Yes, the debouncing is done (hopefully) in another module (one for each button, I'm trying to object orient a bit) whose output is fed into this btn_map code I posted. The debouncing code is below:

(looking at the code now I realize I can do away with the "temp" signal but that's not an error in itself. Also, the only thing really debouncing anything is the fact that the clock fed into the module is very slow.)

entity btn_press is
    Port ( clk, btn : in STD_LOGIC; -- note that I have fed the clk-signal through a clock divider before it gets here
           pressed : out STD_LOGIC); -- not sure about what frequency exactly but definitely enough to debounce
end btn_press;

architecture Behavioral of btn_press is

signal temp : STD_LOGIC := '0';

begin

    process(clk, btn)
    begin
        if rising_edge(clk) then
            temp <= btn;
        end if;
    end process;
    
    pressed <= temp;
    
end Behavioral;

 

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

@Tickstart,

I'm missing the counter in your debouncer.  There should be a counter in there.  You mentioned that the clock was the result of a clock divider.  However, clock divider's in logic don't work--especially if you want to look for the positive edge of the clock.  You'll want to  do something instead like checking for not only the positive edge of the real clock (not a logic generated clock), but a logic signal from your logic clock divider (assuming you aren't dividing the clock via a DCM or PLL ...)

Dan

Link to comment
Share on other sites

Last night while responding to another thread I happened onto your post. It was late, I was tired, and, don't take this the wrong way, but your code gave me a headache just looking at it. i started a reply and ended up abandoning it. Though I've been doing HDL for about 20 years I don't consider myself an expert. I humbly offer some suggestions to newbies.

DON'T be cute or "unorthodox" unless you just want to play around using a simulator to see what happens ( and I totally support and encourage doing just that...) . DO keep your code as simple as possible.

Understand that most FPGA synthesis tools extract common structures from your code and implement their own optimized logic unless you turn the feature off. What a synthesis tool and simulation tool interpret your code to mean is NOT always the same so it's very possible to have code work perfectly in a simulation and not in implementation though there are no timing issues. FPGA vendors offer HDL guides for coding styles that work best with their syntheses tools. Read and use these guides. Occasionally, synthesis tools just make mistakes. Unorthodox coding is probably a good way to find bugs in tools, if that's what you're going for. All of this is to say that keeping things simple helps you in more ways than is obvious.

Hamster's comments offer a valuable point. FPGAs are not computers and HDLs are not computer software languages as far as synthesis goes. You need to be thinking about how to do things differently keeping in mind that storage and states are different in digital logic. Basically, things are either concurrent, and in no particular order, or sequential; clocked or combinatorial. All of these require thinking about timing. Combinatorial processes are prone to race conditions and clocked processes are susceptible to metastability. I still sometimes manage to get a simulator to hang by not taking into account the concept of time and signal delay properly. I tend to use either concurrent statement or clocked processes. VHDL Processes have a sensitivity list. The signals in your processes can change state based on a change of state of a signal in the sensitivity list. I rarely write processes that use signal state changes other than a clock edge, except for asynchronous resets. Hamster has offered some fine advice on resets in his wiki site. Your coding style will influence and reflect your thinking about time. I advise developing a code of basic coding styles and expanding them as your endeavours got more complex. While writing terse and arcane C code might imply a greater skill and intelligence ( or job security ) basic boring HDL is a better friend most of the time.

I rarely use variables except when writing testbenches. There are implications for mixing types in your code. Sometimes doing so is required to make your code more readable but you better understand the implications.

 

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

In VHDL there are constants and variables. Constants and variables are assigned values using the ":=" symbol. Signals area assigned values using the "<=" symbol. The difference is that ":=" is an instant assignment while the "<=" is an assignment that occurs after some event. This bring us back to the concept of things happening after time and delays. There's nothing wrong with using variables but using them indiscriminately can be a mental trap letting us forget about timing. Also, there's no need to use variables in VHDL code meant to be synthesized. There's enough to think about for my over-taxed little brain without introducing additional complexity with language features that I don't need for the task at hand.

Link to comment
Share on other sites

For everything posted to a forum like this the coding is for the most part "playing around" code. When you have a commercial product that HAS to be reliable things get extremely complicated quickly. Not only do you have to be taking into account internal FPGA signal delays but as the device substrate temperature changes, due to environmental conditions or just heating due to device operation and driving IO these delays change with temperature. On top of this is just plain "features" and behaviour  of synthesis and simulation tools that cause hidden danger. And that doesn't address the bad assumptions of what our coding in our language of choice implies relative to what it actually implies.  Over the course of my career I've read a lot of literature exposing these issues that would cause even a seasoned professional sleepless nights. I tried to find a few of these for illustration purposes from my ancient archives... but didn't find what I'm looking for yet.

Here is an observation that guides my world view:

The less you know about a topic the simpler it is... the more you know about a topic the more complex it is and the larger the realm if what's yet to be learned becomes.

Back to finding some perspective building articles....

Link to comment
Share on other sites

3 hours ago, Notarobot said:

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

 

Before I rule it out, I'll do some more comparisons with my old debounce hardware and your suggested one, since I actually built it 'n all. Right now though I've changed too much and I'm not sure what's wrong.

2 hours ago, zygot said:

Though I've been doing HDL for about 20 years I don't consider myself an expert. I humbly offer some suggestions to newbies.

 

Gee, thanks. I'm not trying to be unorthodox I'm just doing my best, I don't know how VHDL should be written, that's why I'm here. I know what variables vs signals are, I thought I used them correctly. Please specify what's wrong (even though that can be hard if you're struggling with where to even begin). I'm a simple man so keep it simple :)

Link to comment
Share on other sites

My comment wasn't meant to as a reflection on you but on me. Understand that we're all learning ( or should be ) even those with many years of experience.

One suggestion is to read code from more seasoned knowledgeable people, simulate it and try to understand why they chose to code things the way they did. 

It's my opinion that solving peoples problems for them are is usually the best way to help them along. Believe me, I do understand your frustration. Unfortunately, the second best way to learn is by figuring out your mistakes... the best way would be understanding others mistakes but take requires quite a bit of expertise, or at least experience. I think that so far you've been given some good guidance in that endeavour in this thread.

 

Link to comment
Share on other sites

So, based on what's been written so far. let me pose some questions?

Do you think that I'd use variables to solve your problem? Do you think that I'd use a clocked process?

One thing that hasn't been nailed down is these mysterious debounced button signals. It's hard to analyse and account for things that are unknown.

 

Link to comment
Share on other sites

Learning curve of HDL design is very steep especially for people without background in digital circuits. The fact that every statement outside a process is concurrent makes it very difficult to control/predict behavior. Plus it is difficult to predict how design decisions will affect compliance with the time constraints. Plus many other factors which one can learn only from making these decisions. I tend to believe that the best way to learn is on other people examples. That is one of the major values of this forum.

Some posters on this forum don’t care to explain what the issue they need to help with, but simply want complete solution. I admire D@n, Hamster and Digilent personnel to have patience for this. I am glad that Tickstart made an effort to explain his project. Thank you, zygot for raising important questions.

Have a good weekend.

Link to comment
Share on other sites

Archived

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