Simple Fade Counter as a tool for get students skills - Page 1
Forum section: electronics / general

author: mrisco
author_rank: Regular Contributor
timestamp: November 13, 2019, 03:46:31 pm
content: This is a simple Fade Counter, how many LE do you need to reproduce it? Please publish your results, post your video and how many resources did you use. This simple project allows the teacher to know the skills of the FPGA students, some of them will try to solve from a programmer perspective, others from structural but the best of the VHDL world is thinking behavioral.The specifications are:- Asynchronous active low reset,- 10MHz clock input,- 8 bits outputs fade counter.- Count at 0.5Hz approx.- The Leds no fade to black, the fade to the next count.Attached are the results for implementation without optimizations on MAX10 FPGA

author: hamster_nz
author_rank: Super Contributor
timestamp: November 14, 2019, 06:11:09 am
content: 29 or 30 flipflops, and about the same number of LUTs (depending on how they pack on the chosen architecture) would be my first guess.Will code later tonight if you want...Is that a sync or async reset? Just that async resets will require a few more FFs

author: hamster_nz
author_rank: Super Contributor
timestamp: November 14, 2019, 08:01:11 am
content: Having done this little project, I don't think that it is that good an assessment of skill or thinking.You can design things to be efficient or to be flexible or to use minimal resources or many other aims.There are quite a few subtleties that are at play:- Is it 0.5hz or "about" 0.5Hz - is a 10Mhz clock divided by 4194304 (2^22) 'about' 0.5Hz Hz? Will you be timing how long it takes to roll over, and it need to meet a given time range?- What range of PWM frequencies for the LEDs are acceptable?- I would not expect a newbie to get the reset anything close to right. Heck I don't think my one is, and I think I know what I am doing!- Count of 'LUTs and FFs' isn't a measure of goodness. Give the students a reasonable budget to hit, then assess the qualities of their design.- The most efficient way (in terms of LUTs and FFs) is to use them for multiple uses - is that FF the state of the counter, or is it the state of an LED? In my case it is both.- Do the LED outputs need to be registered, or can they be glitchy?Anyhow, here is my Utilization numbers - it is running on a Artix 7 (Basys3), with a 100MHz clock, so I could remove a couple of FFs if I had used a 10MHz clock. I also think I did a good reset, which used three of the FFs:Code:+-------------------------+------+-------+-----------+-------+| Site Type | Used | Fixed | Available | Util% |+-------------------------+------+-------+-----------+-------+| Slice LUTs* | 24 | 0 | 20800 | 0.12 || LUT as Logic | 24 | 0 | 20800 | 0.12 || LUT as Memory | 0 | 0 | 9600 | 0.00 || Slice Registers | 37 | 0 | 41600 | 0.09 || Register as Flip Flop | 37 | 0 | 41600 | 0.09 || Register as Latch | 0 | 0 | 41600 | 0.00 || F7 Muxes | 0 | 0 | 16300 | 0.00 || F8 Muxes | 0 | 0 | 8150 | 0.00 |+-------------------------+------+-------+-----------+-------+So with a naive reset and at 10MHz , I think it could be as low as 32 FFs.Oh... forgot to mention, the process that does all the work is about 20 lines of code, the whole project is 41.Not going to post code or video as this seems to be a homework project from a person with a post count of 1.

author: Someone
author_rank: Super Contributor
timestamp: November 14, 2019, 08:22:08 am
content: Specifications by youtube video, new style efficiency.

author: RoGeorge
author_rank: Super Contributor
timestamp: November 14, 2019, 08:37:27 am
content: In case one is in a location with restricted youtube, that's a 12 seconds video showing a LED binary counter, were the LEDs turn on and off by slowly fading in and out their light intensity, instead of suddenly turning on and off.

author: mrisco
author_rank: Regular Contributor
timestamp: November 14, 2019, 10:32:33 pm
content: No code is necessary. It is not real homework. But for recognizing your achievement a video will be great. Please note that is not a simple PWM, the LEDs are not going to fade to black, they fade to the next count, 256 fade steps will be acceptable but not mandatory, only a nice effect as the original video is requested.I did propose this simple task as introductory to know how the students arrive at an intermediate level of VHDL course. Some try to complete the task using a programmer point of view, this approach is not wrong but consume a lot of extra resources. The students with basic electronics engineering formation try to use a structural solution, joining elementary sequential and combinational blocks following some functions and time diagrams. But the most simple and effective solution is when they use the VHDL potential to effectively describe the behavioral of the system. The amount of used resources gives to me an idea of the method used to get the results without see the code, of course, that is not a measure of the quality of the code but is a valid comparison number.This example allows me to show how important is, to left for a moment the programmer and electronics ways thinking to take advantage of the powerfulness of the language.We use SBA (VHDL) to code this example and make it portable across multiple FPGA vendors. I will share the code in the future.Regards.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 14, 2019, 11:23:30 pm
content: Quote from: mrisco on November 14, 2019, 10:32:33 pmWell, since you ask...And since you assure me that it isn't homework (remember that this is set up for a 100MHz clock):Code:library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.NUMERIC_STD.ALL;entity fade_counter isPort ( clk : in STD_LOGIC;nReset : in STD_LOGIC;led : out STD_LOGIC_VECTOR (7 downto 0));end fade_counter;architecture Behavioral of fade_counter issignal counter : unsigned(20 downto 0) := (others => '0');signal counter2 : unsigned(12 downto 0) := (others => '0');signal sync_reset : std_logic_vector(2 downto 0) := (others => '0');begin-- Does the divisionLED <= std_logic_vector(counter(counter'high downto counter'high-7));process(clk, nReset)beginif nReset = '0' thensync_reset <= (others => '1');elsif rising_edge(clk) thensync_reset <= sync_reset(sync_reset'high-1 downto 0) & '0';end if;end process;process(clk)beginif rising_edge(clk) thenif sync_reset(2) = '1' thencounter <= (others => '0');counter2 <= (others => '0');elseif counter2(counter2'high) = '1' thencounter <= counter - 4095;counter2 <= (others => '0');elsecounter <= counter + 1;counter2 <= counter2 + 1;end if;end if;end if;end process;end Behavioral;

author: aandrew
author_rank: Frequent Contributor
timestamp: November 15, 2019, 02:30:38 am
content: wow, that is a slick implementation, hamster_nz! I was hung up thinking of how to get the LEDs to fade to the next value but you've really elegantly solved that!

author: mrisco
author_rank: Regular Contributor
timestamp: November 15, 2019, 04:05:35 am
content: Excellent, I like your solution so much. To match the original video, it only takes a more smooth/long fade.

author: SiliconWizard
author_rank: Super Contributor
timestamp: November 16, 2019, 05:19:51 pm
content: @hamster_nz: Looks to be counting faster than 0.5Hz though? (It looks more like 1Hz, or even a bit faster, to my stupid eyes.) Very compact though.I realize it's just a simple student project, but I think the goal should maybe be stated more precisely. Beyond "thinking behavioral" (which may itself have different interpretations but let's not nitpick), the "number of logic elements" measure seems to imply you're favoring "compactness" over anything else: the "else" being (non-exhaustively): readability, maintainability, genericity (is a one-shot cute trick OK or does it have to be easily reusable/modifiable?), etc.As I personally favor genericity (/reusability) for most of the things I design, I thought if I was going to do this, it would be "fun/more interesting" to write this as a generic fading LED display component and include it in a top-level file doing the counting and writing to the display component. My component has generics for pretty much everthing: the number of LEDs, the main clock frequency, the fading period (time), the number of fading steps, and the PWM frequency! The input data is registered as well and it handles fading from any previous data to the new data you're writing to it. Of course, the result takes more LUTs and registers than hamster's solution, but it's fully reusable and it's dead easy to change any parameter. The component (entity) is 130 lines of VHDL, header description and comments included. I'm not posting it as it clearly goes well beyond what you asked IMO, but I thought talking about reusability could be an interesting point.I'd post a video (tested it on a Lattice MachXO2 dev board), but as shocking as it sounds, I don't have a Youtube channel. I'll see later what I can do to post it.Edit: there you go:https://streamable.com/1y841(It seems slow but it is indeed counting @0.5Hz, I checked with a scope - at least the fading effect is easy to see.)

author: mrisco
author_rank: Regular Contributor
timestamp: November 17, 2019, 04:16:07 am
content: @SiliconWizardPerfect video, the fade effect is clearly visible. Thank you. I think that reusability and genericity when we write code is important. A compromise between compactness and readability, maintainability must be always a goal.Regards.

author: Someone
author_rank: Super Contributor
timestamp: November 17, 2019, 04:30:20 am
content: Quote from: hamster_nz on November 14, 2019, 08:01:11 amHaving a single quantifiable measure is a good thing for students, they don't have to worry about balance and can take the idea as far as they like. Trick is to have it well enough constrained so they don't get a trivial result like 0/0 FF/LUTs by using PLLs, Block RAMs, and DSP blocks. But even then the majority of the assessment would need to be on their communication/documentation rather than the sole performance metric. Bonus points for them identifying a specific other metic and showing how they worked to optimize for that too without impacting the base measure.Quote from: SiliconWizard on November 16, 2019, 05:19:51 pmReal world teams have different priorities for their outputs (which can vary over time/situation). A very readable solution doesn't need to be significantly more resources than the "smallest", a high level coded and readable design comes in around 33-35 FF and 16-18 LUTs assuming you have access to the same half adders as the inscrutable code example hamster_nz gives above. Try handing that code to someone who hasn't been given the background problem and see if they can work out what its supposed to be doing.Quote from: SiliconWizard on November 16, 2019, 05:19:51 pmCompact and unreadable solutions don't have to give up genericy (lets keep making up words for this until one sticks). With parameters on those dimensions of the system its still possible to make exceptionally compact and unreadable systems built of primitives. I tested an example in hardware that got down to 15 FF and 13 LUTs (Xilinx 7 or 6 series) keeping to the fabric primitives of LUTs, FFs, and carry chain. It could go a few counts lower in either dimension, or start making bold trade offs to drastically reduce either the FF or LUT count at the expense of the other.P.S. some educational institutions are requiring videos to be submitted along with assignments as proof of work (particularly for practical electronics or remote learning courses), and plagiarism/matching tools aren't accessible to screen them.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 17, 2019, 08:38:32 am
content: Quote from: Someone on November 17, 2019, 04:30:20 amThere is a reason why the video updates at 2Hz not 0.5Hz - it makes it mostly useless to anybody who tries to use it as proof of work.That bit of code could be made much more understandable with a short comment on how it works - even "takes x steps forward, jump back x-1 steps, that is how slow progress is made", would be enough, I deliberately left that bit out.But... (and a rant here...) according to modern teachings comments in code is a bad thing (yeah, I don't really believe it either, but apparently this is now a thing). Fromhttps://dzone.com/articles/comments-on-comments:QuoteThis is part of the Agile way of doing things, where the requirements are not to be explicitly documented, with preference to them only being captured in your product testing framework. So if you write code that passes your tests, you have a working product.I find it all somewhat worrying, but the Agile thing is winning mindshare as the way to become "high-performing teams", and the meme seems to be infecting everything outside of software development too.So expect to see more uncommented code soon. As a side effect the mindest also support the unspoken "coders pissing higher" contest, where to maintain you pack in the pecking order you have to write code that uses more obscure language features, or esoteric techniques, to write "more advanced, more correct" code than your lesser coworkers.My thinking and goals for real code (not the challenge in this thread) is the opposite - the best code look like it was written by a 10 year old because it is so unsophisticated, but still works as good as a "all the bells and whistles" solution.

author: Someone
author_rank: Super Contributor
timestamp: November 17, 2019, 10:30:05 am
content: Quote from: hamster_nz on November 17, 2019, 08:38:32 amUseless?.. video shows functionally working system, slightly wrong rate that is trivial to adjust... 9/10 isn't useless. Recall that not only are students asking for work directly in some cases, but there is an industry of people procuring solutions to order for "instructive purposes only".Quote from: hamster_nz on November 17, 2019, 08:38:32 amNo need to rail against self documenting code, readability is vastly improved by simple things such as using names of the objects to communicate their purpose rather than their function. Its extremely common to see hierarchical naming in HDL with several layers of context for a signal. Breaking up the problem into understandable sections doesn't usually come at the cost of efficiency, but often does need a tidy up or even re-draft of the names and structures before finishing/submitting/pushing/etc.Simple code using no special features (as your code could be an example of) doesn't make for good communication, but did hit some pattern matching in the tools to result in a very small resource usage. Changing just the variable names and throwing in a couple of carefully named constants and/or generics would make a world of difference to the readability/understandability without affecting the implementation result.

author: SiliconWizard
author_rank: Super Contributor
timestamp: November 17, 2019, 04:25:35 pm
content: Quote from: hamster_nz on November 17, 2019, 08:38:32 amOh, I was too naive to consider that! I get the point. OTOH, I don't think a video should ever be proof of work.

author: NorthGuy
author_rank: Super Contributor
timestamp: November 17, 2019, 07:40:45 pm
content: Quote from: mrisco on November 14, 2019, 10:32:33 pmAre you sure about this? I think it's a really bad idea.The solution to the problem (a design, a program, software etc.) does not depend on the language. The language is just a tool. You use it to implement a solution which you have already designed. The language cannot make a mediocre design great. You don't worship the language. You just use it.Look at the hamster_nz's solution. Neat, isn't it? Why? Because he found a good algorithm and good data structure. Does it have anything to do with VHDL? Absolutely not. Once you know his solution, you can now easily implement it in Verilog, or assemble it from logic chips. Moreover, you can easily port it to MCU and implement it in PIC assembler, or in C on RaspberiPi, or in JavaScript and HTML object model in your Web browser. What matters here is only the hamster_nz's idea. This idea makes things simple. Without it, no amount of language worshipping would help.Likewise, if you want to teach someone to design things, teach them to think about their task, the data structures, algorithms, teach them to remove complexity. That's where the skills are, not in the languages.

author: Bassman59
author_rank: Super Contributor
timestamp: November 18, 2019, 08:41:33 pm
content: Quote from: Someone on November 17, 2019, 10:30:05 amSelf-documenting code helps the reader better understandwhatthe code does. Proper comments explainwhythe engineer wrote the code that way. Sometimes the why is more important than the what and the how.

author: Someone
author_rank: Super Contributor
timestamp: November 18, 2019, 10:07:00 pm
content: Quote from: Bassman59 on November 18, 2019, 08:41:33 pmLook at the code example. Now try and explain why counter and counter2 are good variable names. They certainly are counters, but are entirely dissimilar in bothwhatthey do andwhythey are required.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 18, 2019, 11:35:07 pm
content: Quote from: Someone on November 18, 2019, 10:07:00 pmWhat names would you suggest to make the code self-documenting?I feel that variable names like "increments_8192_times_then_jumps_back_8191_counts_to_implement_PWM_like_fading_for_the_13th_and_higher_bits" and "counts_from_zero_to_8192_so_the_top_bit_can_act_as_a_flag_for_when_the_other_counter_needs_to_jump_thereby_also_setting_the_PWM_time_quantum_and_resolution" might not be ideal variable names either.

author: Someone
author_rank: Super Contributor
timestamp: November 19, 2019, 01:03:28 am
content: Quote from: hamster_nz on November 18, 2019, 11:35:07 pmThanks for that insightful and well thought out reply professor...

author: NorthGuy
author_rank: Super Contributor
timestamp: November 19, 2019, 01:10:51 am
content: Quote from: Someone on November 19, 2019, 01:03:28 amCome on Someone. Don't sabotage it. Suggest the names you like.

author: Someone
author_rank: Super Contributor
timestamp: November 19, 2019, 02:15:49 am
content: Quote from: NorthGuy on November 19, 2019, 01:10:51 amI'm not going to waste time with anyone who jumps right to strawman arguments. Don't feed the troll and all that... not to mention its taking the thread off topic.

author: hamster_nz
author_rank: Super Contributor
timestamp: November 19, 2019, 09:13:52 am
content: Driving home tonight I thought of a different way to do the same thing, but without the need for two counters. So the implementation is even more indirect, It's bound to interest somebody, and will most likely annoy others.Code:library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.NUMERIC_STD.ALL;entity fade_counter isPort ( clk : in STD_LOGIC;nReset : in STD_LOGIC;led : out STD_LOGIC_VECTOR (7 downto 0));end fade_counter;architecture Behavioral of fade_counter issignal sync_reset : std_logic_vector(2 downto 0) := (others => '0');signal counter : unsigned(33 downto 0) := (others => '0');constant increment : unsigned(25 downto 0) := "00000000000010000000000001";beginLED <= std_logic_vector(counter(counter'high downto counter'high-7));process(clk, nReset)beginif nReset = '0' thensync_reset <= (others => '1');elsif rising_edge(clk) thensync_reset <= sync_reset(sync_reset'high-1 downto 0) & '0';end if;end process;process(clk)beginif rising_edge(clk) thenif sync_reset(2) = '1' thencounter <= (others => '0');elseif counter(12 downto 0) = "1111111111111" thencounter <= counter + (x"FF" & increment);elsecounter <= counter + (x"00" & increment);end if;end if;end if;end process;end Behavioral;