VHDL Case Statement - Page 1
Forum section: electronics / general

author: admiralk
author_rank: Regular Contributor
timestamp: February 27, 2021, 01:44:34 pm
content: I am trying to implement a 74150, 16 to 1 multiplexer, using a case statement and while I do not get any errors, it is not working.Code:architecture Behavioral of U_74150 isbeginprocess (E0,E1,E2,E3,E4,E5,E6,E7,E8,E9,E10,E11,E12,E13,E14,E15,SEL)begincase SEL iswhen "0000" => W <= NOT E0;when "0001" => W <= NOT E1;when "0010" => W <= NOT E2;when "0011" => W <= NOT E3;when "0100" => W <= NOT E4;when "0101" => W <= NOT E5;when "0110" => W <= NOT E6;when "0111" => W <= NOT E7;when "1000" => W <= NOT E8;when "1001" => W <= NOT E9;when "1010" => W <= NOT E10;when "1011" => W <= NOT E11;when "1100" => W <= NOT E12;when "1101" => W <= NOT E13;when "1110" => W <= NOT E14;when "1111" => W <= NOT E15;when others => W <= NOT '0';end case;end process;end Behavioral;If I send the input straight through and do not invert it, everything works fine.I does work using a select statement, but why does it not using the case statement?

author: AndyC_772
author_rank: Super Contributor
timestamp: February 27, 2021, 02:15:28 pm
content: In what specific way is it "not working"?What tools are you using? Are you simulating the code, or synthesizing it and loading it onto a real device?

author: Bassman59
author_rank: Super Contributor
timestamp: February 27, 2021, 04:44:04 pm
content: show us your simulation results, please.Synthesis output is not interesting.

author: admiralk
author_rank: Regular Contributor
timestamp: February 27, 2021, 04:49:21 pm
content: I am just doing simulations for now, do not have anything to load it onto. I only started learning VHDL this week and this is my first design other than an and gate, an or gate, and an inverter. I just reran it and it worked this time. Before I was getting undefined results, even on the select bus. The RTL schematic is still wrong though. I am not sure how much of a difference that makes?I am using ISE because this is just a component in a project using a CPLD.

author: rstofer
author_rank: Super Contributor
timestamp: February 27, 2021, 06:14:17 pm
content: What about the surrounding code? Signal declarations, that sort of thing.In synthesis, which probably generated those block diagrams, unused logic is eliminated. For example, if SEL doesn't show up in the top level PORT list (assuming you are using the component directly from the top level), the logic will be eliminated. Why it works for one incantation and not another may be one of life's mysteries.The inputs, and particularly the output, need to show up in the PORT list as well. You have to PROVE to the synthesizer that the logic levels can change internally and this change results from something ultimately happening to signals on the PORT list.Bottom line: Post the entire code.This is just a thought, I haven't tried it but I have seen examples where logic is removed during synthesis.

author: SiliconWizard
author_rank: Super Contributor
timestamp: February 27, 2021, 06:58:29 pm
content: Yes, I can't see a problem with the piece of code the OP posted. But if they are looking at synthesis result, then the most likely cause here is pruned logic as rstofer suggested.Route all input and output signals to external pins of your FPGA to make sure it can't make any assumption about any signal.Note: this would be a good opportunity to start making a habit of looking at the synthesis reports. Yes they are usually pretty annoying to read and telling the important info from the minor warnings is hard (especially when you're not familiar yet), but if any logic is eliminated, if any signal is assumed at a fixed level (the report will usually express this as "<xxx signal> is stuck at Zero/One"), then you'll see that there.

author: gnuarm
author_rank: Super Contributor
timestamp: February 27, 2021, 07:56:34 pm
content: Quote from: SiliconWizard on February 27, 2021, 06:58:29 pmSynthesis reports are such a piece of crap! I'm not saying they aren't important, but they generate so much dross that it is at best time consuming to go through them and at worse impractical. I recall working on a design where every counter that didn't use the carry out would generate a pruned logic warning. So I had to note them and check off each warning against the list of acceptable warnings. Of course any new warnings would have to be investigated to see if it was "intentional" or not.Fortunately in that case the identifier was consistent, so there was a way to relate the pruned logic to the source code. I've seen times when every iteration the names changed! This is one of the reasons to use labels on everything hierarchical.

author: rstofer
author_rank: Super Contributor
timestamp: February 27, 2021, 08:53:43 pm
content: Quote from: gnuarm on February 27, 2021, 07:56:34 pmThis is a really good idea. I'll incorporate it the next time I write some VHDL.

author: pgo
author_rank: Regular Contributor
timestamp: February 27, 2021, 09:03:41 pm
content: Hi,The ISE schematics are often misleading with missing components or connections so they cannot be used to confirm a result although useful in simple designs to indicate results.It is surprisingly easy to simulate a stale design that has not been re-synthesised. I suspect this accounts for some of your inconsistent results i.e. it works now but not before. Make sure the design files have been saved!You do not need to worry about pruning due to unused inputs if you are synthesising this component in isolation unless the design is actually has redundant internal circuitry.You need to provide the test-bench and simulation results to allow judgement on the simulation.bye

author: admiralk
author_rank: Regular Contributor
timestamp: February 28, 2021, 12:15:18 am
content: The only changes I remember making were to remove the "NOT"s and then put them back in, but it did not work when I first put them back in.ComponentCode:entity U_74150 isPort ( E0 : in STD_LOGIC;E1 : in STD_LOGIC;E2 : in STD_LOGIC;E3 : in STD_LOGIC;E4 : in STD_LOGIC;E5 : in STD_LOGIC;E6 : in STD_LOGIC;E7 : in STD_LOGIC;E8 : in STD_LOGIC;E9 : in STD_LOGIC;E10 : in STD_LOGIC;E11 : in STD_LOGIC;E12 : in STD_LOGIC;E13 : in STD_LOGIC;E14 : in STD_LOGIC;E15 : in STD_LOGIC;SEL : in STD_LOGIC_VECTOR(4-1 downto 0);W : out STD_LOGIC);end U_74150;architecture Behavioral of U_74150 isbeginprocess (E0,E1,E2,E3,E4,E5,E6,E7,E8,E9,E10,E11,E12,E13,E14,E15,SEL)begincase SEL iswhen "0000" => W <= NOT E0;when "0001" => W <= NOT E1;when "0010" => W <= NOT E2;when "0011" => W <= NOT E3;when "0100" => W <= NOT E4;when "0101" => W <= NOT E5;when "0110" => W <= NOT E6;when "0111" => W <= NOT E7;when "1000" => W <= NOT E8;when "1001" => W <= NOT E9;when "1010" => W <= NOT E10;when "1011" => W <= NOT E11;when "1100" => W <= NOT E12;when "1101" => W <= NOT E13;when "1110" => W <= NOT E14;when "1111" => W <= NOT E15;when others => W <= NOT '0';end case;end process;end Behavioral;and test benchCode:ENTITY U_74150_tb ISEND U_74150_tb;ARCHITECTURE behavior OF U_74150_tb IS-- Component Declaration for the Unit Under Test (UUT)COMPONENT U_74150PORT(E0 : IN std_logic;E1 : IN std_logic;E2 : IN std_logic;E3 : IN std_logic;E4 : IN std_logic;E5 : IN std_logic;E6 : IN std_logic;E7 : IN std_logic;E8 : IN std_logic;E9 : IN std_logic;E10 : IN std_logic;E11 : IN std_logic;E12 : IN std_logic;E13 : IN std_logic;E14 : IN std_logic;E15 : IN std_logic;SEL : IN std_logic_vector(3 downto 0);W : OUT std_logic);END COMPONENT;--Inputssignal E0 : std_logic := '0';signal E1 : std_logic := '0';signal E2 : std_logic := '0';signal E3 : std_logic := '0';signal E4 : std_logic := '0';signal E5 : std_logic := '0';signal E6 : std_logic := '0';signal E7 : std_logic := '0';signal E8 : std_logic := '0';signal E9 : std_logic := '0';signal E10 : std_logic := '0';signal E11 : std_logic := '0';signal E12 : std_logic := '0';signal E13 : std_logic := '0';signal E14 : std_logic := '0';signal E15 : std_logic := '0';signal SEL : std_logic_vector(3 downto 0) := (others => '0');--Outputssignal W : std_logic;BEGIN-- Instantiate the Unit Under Test (UUT)uut: U_74150 PORT MAP (E0 => E0,E1 => E1,E2 => E2,E3 => E3,E4 => E4,E5 => E5,E6 => E6,E7 => E7,E8 => E8,E9 => E9,E10 => E10,E11 => E11,E12 => E12,E13 => E13,E14 => E14,E15 => E15,SEL => SEL,W => W);-- Stimulus processstim_proc: processbegin-- hold reset state for 100 ns.wait for 100 ns;-- insert stimulus hereE0 <= '1';E1 <= '1';E2 <= '1';E3 <= '1';E4 <= '1';E5 <= '0';E6 <= '1';E7 <= '1';E8 <= '1';E9 <= '1';E10 <= '1';E11 <= '0';E12 <= '0';E13 <= '0';E14 <= '0';E15 <= '0';SEL <= "0000";wait for 10 ns;SEL <= "0001";wait for 10 ns;SEL <= "0010";wait for 10 ns;SEL <= "0011";wait for 10 ns;SEL <= "0100";wait for 10 ns;SEL <= "0101";wait for 10 ns;SEL <= "0110";wait for 10 ns;SEL <= "0111";wait for 10 ns;SEL <= "1000";wait for 10 ns;SEL <= "1001";wait for 10 ns;SEL <= "1010";wait for 10 ns;SEL <= "1011";wait for 10 ns;SEL <= "1100";wait for 10 ns;SEL <= "1101";wait for 10 ns;SEL <= "1110";wait for 10 ns;SEL <= "1111";wait for 10 ns;SEL <= "0000";wait;end process;END;The test bench never changed. It is not hierarchical at this point because I wanted to get the first component working before I moved on.@SiliconWizard what synthesis reports are you referring to? In the console it says it is disregarding this lineCode:when "1111" => W <= NOT E15;as unnecessary, which makes sense to an extent since there are no more cases and I have to include a with others case.

author: gnuarm
author_rank: Super Contributor
timestamp: February 28, 2021, 02:35:25 am
content: Quote from: admiralk on February 28, 2021, 12:15:18 amThis is not correct. There is nothing about that line which is unnecessary. The others case covers cases in simulation, but since all logical combinations of zeros and ones have been covered the others case is not needed in synthesis, so maybe it is referring to the others line. I suggest you track down what is mean by the warning. At least I assume it is a warning. If you didn't assign it a value of NOT E15, what value would it have? NOT '0'?

author: gnuarm
author_rank: Super Contributor
timestamp: February 28, 2021, 02:37:55 am
content: Quote from: rstofer on February 27, 2021, 08:53:43 pmJust to be clear I was referring to "hierarchy" as including all the structure inside a design entity. Every process has a name as well as pretty much anything that can be named. Beats having to go back into the code to find the line that you need to stick a name onto. It's kinda like in schematics where the default name is node1, node2, etc. I don't know how people can use a simulation without net names.

author: admiralk
author_rank: Regular Contributor
timestamp: February 28, 2021, 03:08:07 am
content: Quote from: gnuarm on February 28, 2021, 02:35:25 amIt was not a warning or error, just an info.QuoteMaybe I read it wrong and it was line 75 that was discarded? That was the one with with others.

author: admiralk
author_rank: Regular Contributor
timestamp: February 28, 2021, 03:17:06 am
content: I am going to chalk this up to what ever the problem was, it is gone now, and move on. I would like to thank you all for your input and not trying to redesign my project.

author: gnuarm
author_rank: Super Contributor
timestamp: February 28, 2021, 04:33:29 am
content: Oh yeah, I almost forgotI would not insert all that code to generate an incrementing count. I would infer a counter and have a simple case for decoding.Someone on my project actually codes like that. He explicitly wrote out the logic for a many bit counter that loops around at some counts I know nothing about because he wrote out the ands and ors for each bit!!! His test bench, which is emulating an I2C device, is done as waveforms rather than constructing a simple I2C device to return results. Now he expects me to debug his code.

author: pgo
author_rank: Regular Contributor
timestamp: February 28, 2021, 07:57:09 am
content: Hi GnuARM,A comment on your comment on synthesising a counter for a testbench,I would not think this a good choice for atestbench- just use aforloop.There is no need for it to be synthesiable.Forloops witharraysof test vectors, is another easy approach for testingsimplecomponents.I agree that a higher-level testbench is good for complex designs - the extra smarts pays off in the long run.byee.g.

author: gnuarm
author_rank: Super Contributor
timestamp: February 28, 2021, 08:07:38 am
content: Yes, I didn't mean to imply the test bench needed to be synthesizable. By all means use a for loop. Or whatever you are comfortable working with.Oh, and add lots of comments explaining what is going on. It's hard enough returning to your own code a month or few later. Trying to read someone else's code is much harder without clear comments.

author: rstofer
author_rank: Super Contributor
timestamp: February 28, 2021, 02:39:54 pm
content: Quote from: admiralk on February 28, 2021, 03:08:07 amThat is normal whenever you have fully covered the input signal range and then add a 'default' condition. To be pedantic about it, I always add the default case and expect to see the INFO.This becomes a little less obvious when you are creating finite state machines with MANY states and allowing the compiler to select one-hot encoding. For 100 states, the state word is 100 bits wide but, by definition, only 1 bit is set per state index. It sometimes happens that in the state type declaration, a state is named which hasn't yet been written. The default case will trap those, don't overlook or remove the default case.

author: SiliconWizard
author_rank: Super Contributor
timestamp: February 28, 2021, 04:02:16 pm
content: Quote from: admiralk on February 28, 2021, 03:08:07 amYes, it refers to the "when others" case.Note that this case is actually ONLY discarded by synthesis. Simulation would not discard it, and in simulation, this case would actually be potentially covered. Why? std_logic can have other states than '1' and '0'! Such as 'Z' (high impedance), 'U' (uninitialiazed), and a few others. In simulation, that would matter, as your inputs could be in one of those other states, and thus your "case" would be incomplete without the "when others".In synthesis, for *read* signals of std_logic type, only the states '1' and '0' can be handled for obvious reasons. The inputs of logic cells can't determine if a signal is in any other state than this. So for synthesis, your "case" would be complete without the "when others". Keeping it anyway for simulation needs is a good idea. You may want to choose something else than "not '0'" as the default state for the output though, so it's easier to spot in simulation. Again, in synthesis, this won't matter.

author: SiliconWizard
author_rank: Super Contributor
timestamp: February 28, 2021, 04:12:21 pm
content: As a side note, there is a much less clunky way of implementing the same.Declare your "En" ports as a single "E : in std_logc_vector(15 downto 0)".Then the body of your entity could be a one-liner:Code:W <= not E(to_integer(unsigned(SEL)));You'll just need to add "use IEEE.numeric_std.all;" along with other IEEE libraries you're using.I'm pretty sure this would synthesize exactly the same as your long "case" approach, but it'll be interesting to compare both and report back. AFAIK, MUXes in FPGAs are usually optimized for those indexed selections and the tools try to map your MUXes to that anyway.

author: admiralk
author_rank: Regular Contributor
timestamp: February 28, 2021, 09:40:32 pm
content: Thanks again for the suggestions. As I said, I have only been learning VHDL for a week and have a lot to learn. My only other experience with a HDL was the nand2tetris site.

author: Evan.Cornell
author_rank: Regular Contributor
timestamp: March 01, 2021, 01:30:51 pm
content: Quote from: admiralk on February 28, 2021, 09:40:32 pmI would highly recommendhttps://vhdlwhiz.com/for learning. I have paid for the Dot Matrix VHDL and FPGA Course as well as the new continuing membership. The explanations are quite thorough and easy to understand. Worth the money if you're just getting into VHDL.

author: gnuarm
author_rank: Super Contributor
timestamp: March 01, 2021, 04:09:52 pm
content: Quote from: admiralk on February 28, 2021, 09:40:32 pmWhen you find educational sources, make sure they include coverage of VHDL-2008. That was a significant improvement in the language with many usability features that make life with VHDL much better.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 01, 2021, 04:32:40 pm
content: Quote from: gnuarm on March 01, 2021, 04:09:52 pmThat's true. But I'm often surprised how far behind many courses and tutorials are. Heck, there are still many out there that don't even cover VHDL-93 properly and still stick to the original VHDL-87!

author: gnuarm
author_rank: Super Contributor
timestamp: March 01, 2021, 06:36:51 pm
content: Quote from: SiliconWizard on March 01, 2021, 04:32:40 pmAnd those are the ones that show up high in the Google list! There is a university in Germany I think, that had a bunch of good web pages on VHDL perhaps two decades ago. So clearly not covering 2008. The pages are gone, but Google continues to show them in a search and will gladly present the ancient page for your enjoyment. It is actually a good site, well organized and no errors that I can recall, just missing the last two or three updates to the language.

author: Bassman59
author_rank: Super Contributor
timestamp: March 01, 2021, 07:03:31 pm
content: Quote from: rstofer on February 27, 2021, 08:53:43 pmUse labels everywhere. Every process should have a label. Case statements should have labels. Generate statements should have labels. I even put labels on if/then statements when the nesting gets deep. Labels are your friends!

author: Bassman59
author_rank: Super Contributor
timestamp: March 01, 2021, 07:06:53 pm
content: Quote from: SiliconWizard on March 01, 2021, 04:32:40 pmHow many pieces of vendor-supplied example code -- in their fucking language-support manuals -- have ancient shit likeclk'event and clk = '1'instead ofrising_edge(clk)? And have no labels?It's no wonder that in 2021 the newbies write code as if the language hasn't advanced past its 1987 version.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 01, 2021, 07:38:05 pm
content: Quote from: Bassman59 on March 01, 2021, 07:06:53 pmYep...

author: admiralk
author_rank: Regular Contributor
timestamp: March 01, 2021, 08:49:37 pm
content: Quote from: Evan.Cornell on March 01, 2021, 01:30:51 pmI would love to take a structured course, but I am often working 10 hour days and when you add in all the other chores and what not I have to get done, there is not much time left for it. I have gone through most ofand found it helpful. I plan to roughly revisit the nand2tetris course. I started readingFPGA-Based System Designon my breaks. This would be a good time to go back throughDigital Fundamentalsas well and program the circuits.I will try to find more modern sources for the language, I still need to learn modern C++ also, I am pretty much limited to 98.

author: gnuarm
author_rank: Super Contributor
timestamp: March 02, 2021, 01:51:45 am
content: Quote from: SiliconWizard on March 01, 2021, 07:38:05 pmI'm working on an open source project with a guy who has his roots in some old software that uses drawn waveforms to drive simulations. It doesn't use VHDL-2008 so he won't use any of the expedients. His code is very hard to read and debug.I see many educational institutions still using clk'event and std_logic_arith. I know this stuff will work, but there are issues depending on the systems you are using from what I've been told. There being no standard each vendor's implementation is different. It also bugs me that people keep using std_logic_vector as their default type when unsigned or signed give you much more capability and if nothing else, is much easier to type!!!

author: Bassman59
author_rank: Super Contributor
timestamp: March 02, 2021, 04:39:03 am
content: Quote from: gnuarm on March 02, 2021, 01:51:45 amMy crystal ball says: run away.QuoteBecause an instructor wrote the curriculum in the last century and it hasn't been updated since. I wonder what software and hardware they want the students to use for development.And you can see this is the case, as many instructors put class notes online, so you may come across them in a web search for something else.QuoteYou're absolutely right about using unsigned and signed types where they are useful. Ignore anyone who says to not use those types on entity port lists, too! Use ranged integers or naturals, too! Define an enumerated type instead of using std_logic_vector(X downto Y) with a bunch of constants!There are so many useful features in VHDL that get ignored because they're either not specifically called out with examples in the synthesis reference manuals, or the class instructors never mention them. For example, the VHDL record can greatly simplify your port lists.

author: gnuarm
author_rank: Super Contributor
timestamp: March 02, 2021, 05:48:14 am
content: Quote from: Bassman59 on March 02, 2021, 04:39:03 amYeah, I've thought of that. I was pretty psyched about working on it, but it is very poorly managed and I'm sick of dealing with the consequences of not having a set of requirements analysis. We barely have anything documented at all. Every time I push for something to be documented they create another spreadsheet rather than do a proper job of it!QuoteNot only the old courses, I've helped student who are still being told this is how you do it. I guess many professors have not written any VHDL in over 20 years. The students don't understand what is wrong with using these as it "seems to work". I swear, I'm going to punch the next guy who tells me that!QuoteI've never gotten into records much. Seems a bit of work if you don't have an actual reason to bundle signals. I guess it is less typing given the many times you have to declare things in VHDL. I used to copy a set of regular expressions in my source files that allow me to generate the different formats for the entity declaration, the component instance and the signals declaration to save on the typing. Maybe I'll try using records next time. The record declaration would need to be in a package to be useful, right?

author: nctnico
author_rank: Super Contributor
timestamp: March 02, 2021, 10:46:13 am
content: Quote from: admiralk on February 28, 2021, 03:17:06 amStill a better way to implement something like this is using a for-loop. I'm not sure whether this excersize was to explicitely teach the case statement but for these kind of constructs a case statement is the worst choice. You have to write an expression for each input condition; that way writing VHDL gets cumbersome and lengthy.Using functions, conditional code (generate), arrays, for-loops, records and numeric signals (which are easy to cast as an index to an array) make life much easier and VHDL code shorter & easier to follow / maintain.Early in my career I made it a point to write VHDL as short as possible. Take time to understand how more complex constructs work and what kind of FPGA logic it results in. It paid off in spades. My first project was a 16 channel 'something'. A couple of months later my boss asked: we need your design to support 30 channels. How long does that take to re-code? My answer: 5 minutes. I just need to change 16 into 30. Not long after that the number of channels had to be upgraded to 128 with took the same amount of effort.

author: SMB784
author_rank: Frequent Contributor
timestamp: March 02, 2021, 06:09:09 pm
content: Quote from: Bassman59 on March 01, 2021, 07:06:53 pmSadly verilog is just as bad with this.Most code examples are done in verilog 1995 (not even 2001!) when SystemVerilog has come so much further and is so much more readable/easier to debug. All kinds of really non-obvious errors and pitfalls can arise with verilog 1995 that are mostly corrected in SystemVerilog, and yet people still do their teaching with verilog 1995. Its crazy!

author: Bassman59
author_rank: Super Contributor
timestamp: March 02, 2021, 07:15:51 pm
content: Quote from: gnuarm on March 02, 2021, 05:48:14 amYes, the record type needs to be declared in a package, so it's visible to all entities that use it on ports. My designs tend to have a types_pkg package file so I can have types and constants and enumerations of all sorts shared across entities. That's how you make your entity ports have things more useful than simply std_logic and std_logic_vector.Here's an example of where a record type is useful. The design had a lot of parameters that can be set by user command. The parameters are also stored in nonvolatile memory for recall at power-up or reset. So there's an entity that manages the user setting and getting the parameter values, an entity that manages the non-volatile storage (write and recall) and of course there are the various entities that actually use the parameters.Obviously the parameters had to each be ports on each entity's port list. The command parser needed to drive as outputs a "new" parameter when the user changed it, along with a strobe telling the non-volatile memory manager to store that new parameter. The parser needed to take in the recalled parameters, too.When I first started the design, there were only a handful of parameters, so having each on the port list was "manageable." But then as more things needed to be parametrized, the entity port lists got unwieldy. So I just wrapped up all of the parameters into one record. To support the user updating parameters, I created a second record with "new parameter" values and a write strobe for each. A "parameter manager" entity sat in the middle, dealing with new things from the command parser, initial values that are read from non-volatile store at reset, and it output the parameters used by the whole design.Each entity that needed to consume parameters takes that record as an input. One port on the list, not ... a whole bunch.The only annoyance is that the synthesis tool complained when a member of the parameter record wasn't used within a given entity.But it sure made adding new parameters a cinch.

author: admiralk
author_rank: Regular Contributor
timestamp: March 02, 2021, 08:08:30 pm
content: Quote from: nctnico on March 02, 2021, 10:46:13 amI did not realize loops even existed in VHDL until it was mentioned here. I originally used a select statement, then learned about the case statement and changed it.

author: nctnico
author_rank: Super Contributor
timestamp: March 02, 2021, 08:50:16 pm
content: I strongly suggest to go through a VHDL book and look at all the language constructs that are available. And then go through a synthesis guid (like this one from Xilinx:https://www.xilinx.com/support/documentation/sw_manuals/xilinx2019_2/ug901-vivado-synthesis.pdf) to learn how VHDL language constructs get mapped onto FPGA logic. I'll admit there is a lot to learn so don't try learn everything in one go.Take a good mental note of what Bassman59 wrote earlier: most examples are horrible. I fully agree with that! For fun look at examples of a priority encoder. 9 out of 10 examples will write a line for each input combination. 1 out of 10 will use function (which uses a loop) which can be used for an arbitrary number of inputs. VHDL allows a large degree of code re-useability but very few seem so make full advantage of it.One of the worst projects I've seen uses Python scripts to create VHDL files for registers connected to an address/data bus. It could have been written so much simpler using just VHDL and on top of that they could have made a generic component for it!

author: emece67
author_rank: Frequent Contributor
timestamp: March 02, 2021, 09:18:05 pm
content: .

author: NorthGuy
author_rank: Super Contributor
timestamp: March 02, 2021, 10:59:30 pm
content: Quote from: Bassman59 on March 01, 2021, 07:06:53 pmWhat difference does it make?

author: pgo
author_rank: Regular Contributor
timestamp: March 03, 2021, 02:41:23 am
content: clk'event and clk='1'vsrising_edge(clk)The first detects any transition that results in a final signal state of '1' on clock e.g. 'H'->'1'The second is an IEEE standard library function that only detects sensible rising edges e.g.'0' -> '1', '0'->'H' etc.For synthesis is makes no difference. For absolutely bug-free VHDL is make not much difference for simulation.It's main advantages are:It's easier to read!!Most editors will highlight the keyword so above++In simulation it correctly rejects invalid transitions as rising edges.byePS I taught Digital Systems for many years and the first version always annoyed me!I couldn't persuade other staff to change for some reason.

author: emece67
author_rank: Frequent Contributor
timestamp: March 03, 2021, 09:06:21 am
content: .

author: pgo
author_rank: Regular Contributor
timestamp: March 03, 2021, 09:22:32 am
content: Hi,rising_edge() function correctly handles 0->H transitions so will also work for the I2C case as stated.FUNCTION rising_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN ISBEGINRETURN (s'EVENT AND (To_X01(s) = '1') AND(To_X01(s'LAST_VALUE) = '0'));END;I don't have access to the source library at the moment so the above is from the internet but I believe it is representative of how the function is implemented.bye

author: emece67
author_rank: Frequent Contributor
timestamp: March 03, 2021, 11:18:42 am
content: .

author: NorthGuy
author_rank: Super Contributor
timestamp: March 03, 2021, 02:35:50 pm
content: Quote from: pgo on March 03, 2021, 02:41:23 amSince you teach the language, you're focused on the language. In contrast, I am focused on the design, and I want to use the language to describe my design with as little effort as possible.The easiest way to infer flip-flops is to create a clocking process. So, I have a 4-line template which I paste. It happened to be "rising_edge" variety, so I use "rising_edge" everywhere. It could have been "clock'event" variety just as well, in which case I would use "clock'event" everywhere. Makes no difference, except one - with "rising_edge" I need to change the clock name twice. With "clock'event" I would have to do it three times. So, I would say "rising_edge" is somewhat better. But it would be even better if there was a construct where I need to change the clock name only once. Sorry, not in VHDL

author: Bassman59
author_rank: Super Contributor
timestamp: March 03, 2021, 04:57:37 pm
content: Quote from: NorthGuy on March 03, 2021, 02:35:50 pmYou're missing the point, which is thatrising_edge(clk)is the proper modern idiom to use when inferring edge-sensitive flip-flops.Also, your editor doesn't have a find-and-replace feature?QuoteWe know you're a Verilog partisan, so explain why the sensitivity lists for always blocks that are used to infer flip-flops with an asynchronous reset are sensitive to the edge of that reset?To wit:always @(posedge clk, negedge rst_l) beginif (!rst_l) beginq <= 1'b0;endelse beginq <= d;endendFlip-flop async resets arenotedge triggered!Also the above always block doesn't explicitly say that theq <= dassignment happens on the rising edge. It's implied because we know there are only two events which trigger the block. We explicitly test only for the state ofrst_lfirst, and if that test is false, then we assume that the rising edge ofclkwas the trigger event.But even the test forrst_lbeing low is sorta weird. The only event onrst_lthat triggers the block results in that signal being low, so testing for it being low is redundant.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 03, 2021, 05:53:39 pm
content: Quote from: emece67 on March 02, 2021, 09:18:05 pmYou also have:- Function/procedure overloading, which is quite handy (and is used liberally in the standard IEEE libraries.)- Generic packages (in VHDL-2008): great stuff.- A lot of goodies for test bench code.- Absolutely not exhaustive.There are good and modern VHDL books out there, but the challenge for beginners will be to spot them when you don't actually know what you're looking for yet.As to courses, they often are outdated indeed and rarely get into much depth either - often both for lack of knowledge/practice from those who teach, and for lack of time. Using "advanced" VHDL features can be immensely useful, but the hard part is to understand what those features are exactly and how they can actually map to hardware. (To put it simply - even though it's a simplification - that's what you'd call "synthesizable".) Many courses do no bother too much as it needs to get more in depth, so they tend to stick to a very simple subset which is guaranteed to be synthesizable without having to think much. So I'm not entirely blaming them.Yes, I also wish more modern VHDL (/SystemVerilog) was taught, but OTOH, last thing you want is to get a bunch of young engineers writing overly convoluted code that is either not synthesizable (and may take days/weeks for them to figure out why), or synthesizable but with very poor results...

author: pgo
author_rank: Regular Contributor
timestamp: March 03, 2021, 09:05:31 pm
content: Quote from: emece67 on March 03, 2021, 11:18:42 amHi emecce67,I'm sorry if my post could be taken as a correction.What you said was entirely correct.You mentionedTo_X01()so I thought the expansion ofrising_edge()would be interestingbye

author: pgo
author_rank: Regular Contributor
timestamp: March 03, 2021, 09:19:58 pm
content: Hi All,This thread has wandered a bit from the original question - but why not!Just to widen the discussion further - I think theeasiestway to do the original process is to use array indexing (with a default value at top of process). This requires conversion functions or casts.BUT please keep in mind that often when teaching something the idea is to illustrate some point or technique, not necessarily to implement the functionality cleverly. It may not even be the simplest solution. I would however expect it to be equally efficient in actual synthesis.The outcome of this is that the original solution posted ends up being pretty close to the usual solution given for the problem or just used as good example of a case statement.Case statements really come into their own in more complex situations such as state machines but these are not good initial examples.byePS. Pet peeve - people who think they are writing code not hardware. OK test-benchesarecode but the synthesis stuff needs to be written with hardware in mind.

author: admiralk
author_rank: Regular Contributor
timestamp: March 04, 2021, 03:18:19 am
content: Speaking of books; Does anyone have an opinion onEffective Coding with VHDL: Principles and Best Practicefor modern VHDL?Quote from: SiliconWizard on March 03, 2021, 05:53:39 pmQuote from: pgo on March 03, 2021, 09:19:58 pmI understand both of these thoughts very well. I have allways found it better to do something simply, and do it well, than to make it flashy, and mediocre at best.

author: gnuarm
author_rank: Super Contributor
timestamp: March 04, 2021, 07:17:52 am
content: Quote from: Bassman59 on March 03, 2021, 04:57:37 pmThat's a bit silly. I don't invoke a search and replace to change two things. It's more work than it's worth.QuoteThat's not exactly correct. All logic in HDLs take action on the transition. Then that state is assumed to hold until something else takes action on the signal. If you model a pull-up resistor with an 'H' or 'L' even that takes action when the signal that had been driving it makes the change to release the drive (an edge if you will).Yes, I know this is not considered to be edge sensitive logic, but that's the way models in HDL work,bothHDLs.The only difference between saying rising_edge(signal_name) and addingsignal_nameto the sensitivity list is the sensitivity list acts on both edges. You can describe a FF thus.A <= B when rising_edge(clk);Works pretty much like any other concurrent assignment. The implied sensitivity list is (B, clk), so sensitive to edges of both signals, yet A only changes when there is a rising edge on clk.Quote

author: NorthGuy
author_rank: Super Contributor
timestamp: March 04, 2021, 02:46:04 pm
content: Quote from: pgo on March 03, 2021, 09:19:58 pmIn my purely pragmatic view, you do not need anything on top of the process, nor do you need any process at all:Code:e <= e15&e14&e13&e12&e11&e10&e9&e8&e7&e6&e5&e4&e3&e2&e1&e0;mux <= e(to_integer(sel));

author: Bassman59
author_rank: Super Contributor
timestamp: March 04, 2021, 04:14:49 pm
content: Quote from: gnuarm on March 04, 2021, 07:17:52 amMy assumption was that NorthGuy wanted to change the name of the clock in more than one process/block. Basically a refactor. Hence, search and replace. In emacs, that'sM-x replace-string.QuoteActually, they take action when there is an event on a signal. An assignment to a signal creates an event on that signal, even if the new value assigned is the same as the previous.QuoteWell, yes, but the point is that the always block should not be sensitive to the edge of the reset if the reset is actually a level.QuoteNo --the sensitivity list triggers the process on any event on its signals.This is why we are discussing the use of VHDL'srising_edge(clk)vsclk'event and clk = '1'! The process is sensitive to any event on the signals in the list. We have shown, the transition from 'H' to '1' creates an event which the latter idiom will say "yes! You have a rising edge!" whereas the former (therising_edge()function)will not.QuoteYes, it does.QuoteYes, and the B on the list is superfluous -- and that's why the model for the synchronous process includes only the clock and async resets. You don't trigger the process on changes in the D input. Remember the model here: a D flip-flop ignores its D input except on the active edge of the clock input.QuoteWhat I'm saying is that the block is triggered by the falling edge of rst_l, and Verilog doesn't have a way of describing the innards of the block in a non-redundant way.Yes, the clock can toggle whilerst_lis asserted low. Yes, the correct operation is for the clock to be ignored asrst_llow has precedence.But the block is sensitive only to the falling edge ofrst_lso the test forrst_l = '0'is redundant but necessary because Verilog gives you no way to discern that the block was triggered byrst_land not the clock. VHDL says, "there was some event on a signal on your sensitivity list, please check for the conditions of interest on all of them."

author: NorthGuy
author_rank: Super Contributor
timestamp: March 04, 2021, 04:28:53 pm
content: Quote from: Bassman59 on March 04, 2021, 04:14:49 pmNo, you misunderstood my post. What I said is that when I want to create a clocked process I paste a template:Code:process(clk)beginif rising_edge(clk) thenend if;end process;then I need to change the clock name twice:Code:process(clk_mine)beginif rising_edge(clk_mine) thenend if;end process;That's a lot of redundancy here.P.S. Sorry, cannot answer your Verilog question. I don't use Verilog and know very little about it.

author: gnuarm
author_rank: Super Contributor
timestamp: March 04, 2021, 09:02:34 pm
content: Quote from: NorthGuy on March 04, 2021, 02:46:04 pmOne of the issues of advanced age is the lack of instant learning. I never took notes in classes through graduate school. But now I code in VHDL infrequent enough that when I run into a stumbling block and research it to find out the cause and how to deal with it, I seldom retain the details. However...I seem to recall that there is an issue, perhaps tool specific, with indexing an array with a non-static signal. I remember being thwarted by terms like "globally non-static" and "locally non-static" and having little idea of what the **** they are talking about. Am I misremembering this? Have you used this code?

author: asmi
author_rank: Super Contributor
timestamp: March 04, 2021, 09:29:03 pm
content: In Verilog/SystemVerilog you specify a working edge of a clock straight in the block declaration, so that you only specify a clock once.In VHDL it would look likeprocess (rising_edge(clk))begin//what happens on a rising edgeend process;I never understood why in VHDL there is a construct "if rising_edge(clk)" - to me the presence of "if" implies a possibility of "else" - but what "else" can really happen in this case?

author: gnuarm
author_rank: Super Contributor
timestamp: March 04, 2021, 09:37:46 pm
content: Quote from: Bassman59 on March 04, 2021, 04:14:49 pmIf I used emacs enough to be facile with it, I would just use C-x M-c M-butterflyQuoteI think you just described a transaction, not an event. An event is always a change in value. I discovered this once when my code was malfunctioning and traced it to a bug in the simulator that was running an event triggered process on transactions. Very tricky to figure out. Maybe the code was not malfunctioning, but in debugging the simulator kept stopping on a breakpoint when there was no signal value change. Without a signal value change the code should not have been run at all.QuoteI don't know why you assert that given acknowledgement of the previous statement. Simulators don't run on levels. They run on edges. When you use a signal name in a sensitivity list that isfunctionally similarto saying rising_edge(x) OR falling_edge(x).QuoteSorry, I fail to see the difference. Ok, I guess you mean it includes other values than 0, 1, L and H, yes, that is true. However, there is no reason to run a clocked process on any event other than the ones that will result in a change in a signal or variable value. That's why they use neg_edge for the low true reset.QuoteOk, but there's no point to this assertion. I don't think this is what the issue is about. I think you are actually talking about the logic used in the IF statements. The sensitivity list typically simply has "clk" and runs on ALL events. It is the conditional logic that must separate the times the FF needs to change the output. We need to not confuse the two.QuoteI don't understand what you mean. Once in the block the logic has to distinguish the reset from the clock. Are you calling that "redundant"?QuoteSo Verilog and VHDL are the same in this respect, no? Or am I missing your point?This conversation is getting hard to follow.

author: gnuarm
author_rank: Super Contributor
timestamp: March 04, 2021, 09:41:41 pm
content: Quote from: asmi on March 04, 2021, 09:29:03 pmI suppose your code does not use async resets? Others do and that needs to be separated.I read that the VHDL standard specifies what it synthesizable. Seems the specify some specific formats. I don't know that they explain the whys. I do know there were many earlier languages to design logic with that simply allowed you to specify "this is a register assignment" which would simply create a register. No one uses them anymore.

author: asmi
author_rank: Super Contributor
timestamp: March 04, 2021, 09:50:58 pm
content: Quote from: gnuarm on March 04, 2021, 09:41:41 pmIn that case you specify your working reset edge in a block header as well. In VHDL-speak it would be something like:process (rising_edge(clk) or rising_edge(async_reset))beginif (async_reset = 1)begin//reset logicend else begin//clock logicendend processThough I almost never use async resets in my designs.

author: nctnico
author_rank: Super Contributor
timestamp: March 04, 2021, 10:18:12 pm
content: Async resets are never edge sensitive.It is always something like this:Code:process (reset, clk)beginif reset ='1' then--reset statementselseif rising_edge(clk) then-- clock synchronous logicend if;end if;end process;The reason to do this is because most flipflops in FPGAs / CLPDs support asynchronous reset only. However there are setup/hold requirements and time is needed to let the logic settle before the next clock edge arrives. So all in all it is a good idea to make sure the asynchronous reset has a timing relation to the clock.

author: asmi
author_rank: Super Contributor
timestamp: March 04, 2021, 10:45:53 pm
content: Quote from: nctnico on March 04, 2021, 10:18:12 pmWHAT? Async resets are edge-sensitive by definition as reset happens immediately as soon as reset reaches active level.

author: pgo
author_rank: Regular Contributor
timestamp: March 04, 2021, 11:28:44 pm
content: Hi All,I think most of this comes down to terminology.A edge-sensitive input is one that has effect ONLY on an edge. This would be a clock input. I think everyone would agree that this is a very special kind of input where a considerable degree of care has been taken to make it have effect only on a particular edge.To give an example of the difference when considering reset inputs and the fact that they MAY have an effect on an edge:Consider a set dominant,set-reset flip-flop (without any clock) i.e.S R Action0 0 hold1 0 set0 1 reset1 1 setFor the following sequence1. R = 1 Q = 02. S = 1 Q = 13. S = 0 Q = 0The change at step 3 is due to the negation of S but the value of Q is actually determined by the value of R . The result is sensitive to S and respond on both changes of S.

author: NorthGuy
author_rank: Super Contributor
timestamp: March 04, 2021, 11:53:57 pm
content: Quote from: gnuarm on March 04, 2021, 09:02:34 pmI don't remember seeing these error messages. Vivado produced a perfect mux:Here's the whole VHDL file:Code:library ieee;use ieee.std_logic_1164.all;use ieee.numeric_std.all;entity top isport (mux: out std_logic; sel: in unsigned(3 downto 0);e0,e1,e2,e3,e4,e5,e6,e7,e8,e9,e10,e11,e12,e13,e14,e15: in std_logic);end top;architecture bhv of top issignal e: std_logic_vector(15 downto 0);begine <= e15&e14&e13&e12&e11&e10&e9&e8&e7&e6&e5&e4&e3&e2&e1&e0;mux <= e(to_integer(sel));end bhv;

author: gnuarm
author_rank: Super Contributor
timestamp: March 05, 2021, 12:08:54 am
content: Quote from: asmi on March 04, 2021, 09:50:58 pmSo you think VHDL needs to be more like Verilog? I don't really get your point. Even Verilog has the redundancy of specifying async_reset more than once. In VHDL a process uses a sensitivity list which may rule out using a function (I'm not certain). So you specify in the logic that the FF is edge sensitive. Your issue is just that it has more typing? Yeah, I think we all have figured out that VHDL requires more typing than Verilog.If you don't have an async reset you can't meet requirements in many designs. Without an async control there is no way to set a chip into known state if the clock fails. This can be a significant issue in equipment that has safety concerns. Obviously not all equipment has such requirements.

author: gnuarm
author_rank: Super Contributor
timestamp: March 05, 2021, 12:21:02 am
content: Quote from: nctnico on March 04, 2021, 10:18:12 pmOk, one more time... Because processes only run on signal events (value changes) all assignments are edge sensitive functionally. The assignment is made at the time the process is run which is always triggered by an edge (value change) in the signal in the sensitivity list.Additional assignments may be made to the same value on other edges than the initial edge such as in a combinational logic process.Code:Foo:process(A, B)beginY <= A or B;end process;A goes a '1' and Y is set to a '1'. B goes to a '1' and the process runs again, but still assigns a '1' to Y. Every action in process Foo happens on some edge of a signal. So no, this is not "edge triggered logic", but the code is all edge triggered because of the sensitivity list.

author: pgo
author_rank: Regular Contributor
timestamp: March 05, 2021, 04:21:47 am
content: Quote from: gnuarm on March 05, 2021, 12:21:02 amHiYou are discussing how the VHDL simulator works - far enough.Most people describe this as event driven rather than edge triggered.I think the distinction is not vitally important but consider the following.In VHDL a process sensitive to a signal X will be evaluated for a change of 'H'->'1'. Most people would not consider this an edge.In terms of actual hardware this distinction would disappear because it is not physically realizable to implement a circuit sensitive to this transition.I think it helps to use the term 'edge-triggered' to refer to clock related events but this is just an preference but I think a common one..bye

author: gnuarm
author_rank: Super Contributor
timestamp: March 05, 2021, 07:29:18 am
content: Quote from: pgo on March 05, 2021, 04:21:47 amYes, you are absolutely right. But look at the context of this discussion where someone was complaining the Verilog syntax requires specifying the edge of the async input. So this discussion is about the HDL world and not the physical world of logic devices.

author: pgo
author_rank: Regular Contributor
timestamp: March 05, 2021, 09:38:58 am
content: Hi,I don't use Verilog but but I am curious is is permissible to use:Code:always @(posedge clock, reset) beginif (reset) beginq <= 1'b0;endelse beginq <= d;endendor is mixing posedge with an unqualified signal not allowed?(I know it would be less efficient to simulate but resembles the VHDL style more).Also is is allowed to use posedge outside of the sensitivity list?

author: NorthGuy
author_rank: Super Contributor
timestamp: March 05, 2021, 04:47:53 pm
content: Quote from: pgo on March 05, 2021, 09:38:58 amWouldn't that trigger "q <= d" coming out of reset, even if the clock is not present?

author: pgo
author_rank: Regular Contributor
timestamp: March 05, 2021, 09:05:59 pm
content: Yes,That was why I asked if posedge ca be used outside of a sensitivity list.bye

author: nctnico
author_rank: Super Contributor
timestamp: March 06, 2021, 01:03:58 am
content: Quote from: gnuarm on March 05, 2021, 12:21:02 amWhy would a process run only when a signal changes? That would make sense if you make a simulator and optimise it to only do stuff when a signal changes (which can go horribly wrong.. ghdl..) but the code holds true whether the process is being run continuously or only when the signal changes. The functionality / meaning of the code doesn't change.

author: gnuarm
author_rank: Super Contributor
timestamp: March 06, 2021, 02:25:32 am
content: Quote from: nctnico on March 06, 2021, 01:03:58 amI don't follow your reasoning at all. An event on one signal causes another signal to change. So an event is the precursor to any process running to change the value of signals that have a dependency on the changed signal. Otherwise, why would you need to doanything? Until a signal changes you can just leave everything where it is and do nothing.The way simulators work is to schedule transactions. An event causes a process to run and the assignments in the process create a scheduled action on a signal. Typically the action is one delta time away (a way to order transactions with no time ticking off the game clock), but they can be scheduled some time off if running a timing sim. Otherwise nothing happens until the next event.

author: Daixiwen
author_rank: Frequent Contributor
timestamp: March 08, 2021, 08:19:25 am
content: Quote from: nctnico on March 06, 2021, 01:03:58 amBecause it says so in the VHDL specification? VHDL 2008, §11.3QuoteSo in a simulator, the process must be paused until one of the signals from the list changes. This is of course for simulators. When synthesizing, the tool must map this to actual hardware, and usually only recognises two types of sensitivity lists:a clock (single edge) and an (a)synchronous reseta combinatorial process with all input signals in the sensitivity listIf you deviate from those you will either generate some hardware that doesn't behave as described, or have the tool yell at you.

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 10, 2021, 04:39:02 pm
content: Quote from: nctnico on March 06, 2021, 01:03:58 amThere was a whole thread about this, how simulation and synthesis can diverge and what the standard says. I don't remember the topic's title but I suggest looking it up. In short, this is just how processes are defined in the VHDL standard. I suggest getting ahold of it (even if it's and older version) and read a bit.

author: emece67
author_rank: Frequent Contributor
timestamp: March 10, 2021, 04:47:42 pm
content: .