0 logic elements in vhdl code - Page 1
Forum section: electronics / general

author: swampythe47
author_rank: Newbie
timestamp: August 02, 2018, 05:42:17 am
content: Can anyone please help me with my code? I am able to compile code but i am getting 0 logic elements. Its not working on FPGA board(cyclone 2).I am attaching 5 of my codes files.P.s.:-Ultrasonic is my top level entity.

author: Daixiwen
author_rank: Frequent Contributor
timestamp: August 02, 2018, 08:53:45 am
content: I haven't looked at all your code, but for starters in the trigger generator you place the code in a process(clk) but after that you didn't put a clock edge trigger. Either you write a clocked process and include a check for the clock edge in the process, or you make a combinatorial process but then you must put all the inputs in the process sensitivity list. With your code the synthesizer will ignore the (clk) sensitivity list and make a combinatorial process. This will give different results on the FPGA than what you could see in simulation.I see a circular reference on the reset signal between the trigger generator and the counter. You use the counter value to create a combinatorial reset signal, that is used itself to asynchronously reset the counter. I'm not sure how the synthesizer will interpret that but it probably won't be what you want.Did you have a look at all the warnings from the compilation process? If it removed all your logic, you will probably find the reason in the compiler report.Oh and I almost forgot. I know there are lots of example (even text books) that use the ieee.std_logic_unsigned and ieee.std_logic_signed libraries but you really shouldn't. They are not standard libraries, and it becomes a mess when you will need to start mixing signed and unsigned values in your design. It is a lot better to use the ieee.numeric_std library and use the "unsigned" type for your std_logic_vector signals.

author: iMo
author_rank: Super Contributor
timestamp: August 02, 2018, 10:43:14 am
content: That happens to me usually when I mess with clock names across the source. No clock, no funTry to rename "clk" in your Distance.. BCD.. Counter.. components to "fpgaclk" your entity ultrasonic uses (ultrasonic.txt). Or something like that.PS: as mentioned above you have to look into your log, look at Warnings, you have to find something like:.. "clk" signal not found/used/wired, all your logic in this component/entity has been optimized out..I do not use Altera, nor vhdl, so take it as a hint only

author: AndyC_772
author_rank: Super Contributor
timestamp: August 02, 2018, 11:03:22 am
content: This is exactly the sort of problem you can easily solve with a simulator. Generate a top level component which provides a clock and any other trigger signals your design requires, then look through to see which signals aren't doing what you expect.The level of complexity of this design is about at the point where you'll struggle to spot problems 'by inspection', especially since you've divided up an otherwise simple project into a set of individual components. This makes it unnecessarily complicated, IMHO.If you're using Altera then the free version of ModelSim is the way forward. Other simulators are, of course, available.

author: hamster_nz
author_rank: Super Contributor
timestamp: August 02, 2018, 10:40:16 pm
content: Serious question - why is there no indentation in your source code? Is it how you converted it to text, or do you truly not see the value of indentation?Compare the original:Code:library ieee;use ieee.std_logic_unsigned.all;use ieee.std_logic_1164.all;entity BCD_converter isport(Distance_input:in std_logic_vector(8 downto 0);hundreds:out std_logic_vector(3 downto 0);tens:out std_logic_vector(3 downto 0);unit:out std_logic_vector(3 downto 0));end BCD_converter;architecture bcdarch of BCD_converter isbeginprocess(Distance_input)variable bcd:std_logic_vector(20 downto 0);beginbcd:=(others=>'0');bcd(8 downto 0):=Distance_input;for i in 0 to 8 loopbcd(19 downto 0):=bcd(18 downto 0)&'0';if(i<8 and bcd(12 downto 9)>"0100") thenbcd(12 downto 9):=bcd(12 downto 9)+"0011";end if;if(i<8 and bcd(16 downto 13)>"0100") thenbcd(16 downto 13):=bcd(16 downto 13)+"0011";end if;if(i<8 and bcd(20 downto 17)>"0100") thenbcd(20 downto 17):=bcd(20 downto 17)+"0011";end if;end loop;hundreds<=bcd(20 downto 17);tens<=bcd(16 downto 13);unit<=bcd(12 downto 9);end process;end architecture;andCode:library ieee;use ieee.std_logic_unsigned.all;use ieee.std_logic_1164.all;entity BCD_converter isport(Distance_input:in std_logic_vector(8 downto 0);hundreds:out std_logic_vector(3 downto 0);tens:out std_logic_vector(3 downto 0);unit:out std_logic_vector(3 downto 0));end BCD_converter;architecture bcdarch of BCD_converter isbeginprocess(Distance_input)variable bcd:std_logic_vector(20 downto 0);beginbcd:=(others=>'0');bcd(8 downto 0):=Distance_input;for i in 0 to 8 loopbcd(19 downto 0):=bcd(18 downto 0)&'0';if(i<8 and bcd(12 downto 9)>"0100") thenbcd(12 downto 9):=bcd(12 downto 9)+"0011";end if;if(i<8 and bcd(16 downto 13)>"0100") thenbcd(16 downto 13):=bcd(16 downto 13)+"0011";end if;if(i<8 and bcd(20 downto 17)>"0100") thenbcd(20 downto 17):=bcd(20 downto 17)+"0011";end if;end loop;hundreds<=bcd(20 downto 17);tens<=bcd(16 downto 13);unit<=bcd(12 downto 9);end process;end architecture;I find the latter far easier to see what is going on, and see where it "has the wrong shape". I've seen this happen a bit lately, and am interested to find if it is a cultural thing, or a reaction to coding in Python....Strangely enough, although it is missing the "if rising_edge(clk) then" it will most likely work in simulation - the inputs will change, the clock will change, and the outputs will change, but as you are discovering there is a big simulation vs implementation mismatch waiting to get you.Even with the correct clocking added, the BCD conversion algorithm isn't very good for FPGA implementation. Without understanding the algorithm it is is obvious it will be both very slow, and use a lot of resources - the worst of both worlds

author: swampythe47
author_rank: Newbie
timestamp: August 03, 2018, 01:36:59 pm
content: I am now getting the logic elements but no output is seen as i assigning led pins as output

author: rstofer
author_rank: Super Contributor
timestamp: August 03, 2018, 02:23:48 pm
content: As I understand the BCD converter, there is only an 8 bit input and 3 each 4 bit outputs. I would implement that as 3 lookup tables in initialized RAM. No logic at all.In Xilinx Vivado, it is easy to read the values from a file during synthesisHere is some excellent initialization code from hamster_nz that reads a hex file during synthesis:Code:library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;use STD.textio.all;use ieee.std_logic_textio.all;entity VectorROM isgeneric (SIZE : integer := 32;ADDR_WIDTH : integer := 5;COL_WIDTH : integer := 16;NB_COL : integer := 1;FILENAME : STRING := "Vector.hex");port (clk : in std_logic;LD_VECTOR : in std_logic;addr : in std_logic_vector(ADDR_WIDTH-1 downto 0);do : out std_logic_vector(NB_COL*COL_WIDTH-1 downto 0));end VectorROM;architecture behavioral of VectorROM istype ram_type is array (SIZE-1 downto 0) of std_logic_vector (NB_COL*COL_WIDTH-1 downto 0);impure function ocram_ReadMemFile(FileName : STRING) return ram_type isfile FileHandle : TEXT open READ_MODE is FileName;variable CurrentLine : LINE;variable TempWord : std_logic_vector(15 downto 0);variable Result : ram_type;beginfor i in 0 to 1024 loopexit when endfile(FileHandle);readLine(FileHandle, CurrentLine);hread(CurrentLine, TempWord);-- Result(i) := resize(TempWord, 16);Result(i) := TempWord;end loop;return Result;end function;signal RAM : ram_type := ocram_ReadMemFile(FILENAME);---- this is where the RAM is accessed by high level logic--beginprocess(clk,LD_VECTOR)beginif rising_edge(clk) thenif LD_VECTOR = '1' thendo <= RAM(conv_integer(addr));end if;end if;end process;end behavioral;And a piece of the .hex fileCode:2001c0000186000000000000...ETA:Maybe the easy way is to declare the memory array as 256 words of 12 bits and use 3 hex digits in the file to define the contents of RAM. Probably have to change COL_WIDTH.

author: swampythe47
author_rank: Newbie
timestamp: August 05, 2018, 06:14:17 am
content: I guess there ismsome problem in my logic. Can anyone please rectify and tell me?

author: hamster_nz
author_rank: Super Contributor
timestamp: August 05, 2018, 06:39:18 am
content: Which bit are you having issues with? What are you attempting to do? What is happening, and what isn't?I will give you some good hints. but I wont write the code...Also, I tend to match the reply to the amount of information you give.... my time is as valuable as yours, So a brief post will usually only get a brief reply, (unless it is particularly insightful, then I will rant forever)

author: hamster_nz
author_rank: Super Contributor
timestamp: August 05, 2018, 08:24:09 am
content: Quote from: swampythe47 on August 05, 2018, 06:14:17 amWhat will most likely be the easiest is to work out a binary to BCD algorithm in a language you know, but under constraints that force you to write like it is a hardware description language.Once you have a suitable algorithm, the actual VHDL implementation will be easy. If you can't express the algorithm in a language you know, then you will have a hard time trying to implement in VHDL.To this end, you able to code & compile in C? Are you able to write a function that takes an unsigned integer between 0 and 511 parameter, and returns the same value, but in BCD?Here is my example, to give you an idea:Code:unsigned my_module(unsigned input) {unsigned rtn = 0;rtn = (input/100)%10;rtn *= 16;rtn += (input/10)%10;rtn *= 16;rtn += input%10;return rtn;}You don't have to use that code, anything that works will be fine.All we need is a program that shows what the return value from "my_module(500)" is, in hexadecimal? (It should be 0x500)If you want to use a different language to do your decimal to BCD conversion, that is fine - I know quite a few. All we just need a working bit of code that you can post in your reply.Once you post your reply, I'll give you a set of restrictions that you need to follow in your 'my_module()' function, that reflect writing code for an FPGA.

author: swampythe47
author_rank: Newbie
timestamp: August 07, 2018, 12:57:10 pm
content: I am nit getting any response. I just want you to check whether my coding logic is correct or not?

author: emece67
author_rank: Frequent Contributor
timestamp: August 07, 2018, 02:41:53 pm
content: .

author: emece67
author_rank: Frequent Contributor
timestamp: August 07, 2018, 02:56:42 pm
content: .

author: hamster_nz
author_rank: Super Contributor
timestamp: August 07, 2018, 09:46:20 pm
content: Quote from: emece67 on August 07, 2018, 02:56:42 pmFully agree... but I'm not going to bother helping somebody who either doesn't understand what they are trying to do or can't be bothered to work through the problem.Once we had an idea of what the OP was trying to do, I would add the following constraints on them:Expensive operations:* You are not to use division or modulus operators. These are very, very expensive operations in an FPGA.* You should avoid multiplication if possible - an FPGA may have only a dozen or so multiplier blocks, so they shouldn't be wasted on trivial things.Cheap operations:* Bitshifts are free* Logical AND/OR/NOT operations are very inexpensive* Addition / subtraction are also inexpensive.FPGAs have no 'stack' or temporary storage:* FPGAs don't have a stack so all variables need to be declared external to the function. In FPGAs storage gets implemented as a flip-flops in the FPGA fabric, and are statically allocated at 'build' time.* You can only assign a variable once as you pass through your function - this is the same restriction as a clock edge only allows you to update a flip-flop once per cycle.* FPGAs have a limited amount of flip-flops, so avoiding excessive variables is good.Latency and lopping* You only get one loop ('for' or 'while', whatever). It has to be in your 'main() function'* Data can take many cycles to flow through your BCD conversion function as required.Eventually I was hoping to get to something like this for the main():Code:int main(int c, char *argv[]){unsigned int test_case = 0x1F4; /* should convert to 0x500 */while(1) {unsigned output;output = my_module2(test_case);printf("0x%03x => 0x%03x\n", test_case, output);sleep(1);}return 0;}And this for the BCD conversion (an ugly slow, but perfectly workable way):Code:unsigned last = 0;unsigned count = 0;unsigned ones = 0;unsigned tens = 0;unsigned hundreds = 0;unsigned converting = 0;unsigned rtn = 0;unsigned my_module2(unsigned input) {/* Set the outputs */if(count == converting) {last = (hundreds<<8) | (tens<<4) | ones;rtn = (hundreds<<8) | (tens<<4) | ones;} else {rtn = last;}if(hundreds == 9 && tens == 9 && ones == 9) {/* Reset the counter */count = ones = tens = hundreds = 0;/* Sample the input, so it can't change mid conversion */converting = input;} else {count++;if(tens == 9 && ones == 9) {hundreds++;tens = ones = 0;} else if(ones == 9) {tens++;ones = 0;} else {ones++;}}return rtn;}Converting that function to VHDL is a doddle, and will work.However, a strange thing might happen, and the OP may have realized that this was a good solution:Code:unsigned bcd_table = { 0x000, 0x001.... 0x511};unsigned my_module2(unsigned input) {rtn = bcd_table[input&511]return rtn;}It complies with all the 'rules' and gets the job done with zero fuss, and near-zero latency. All the work is done offline in generating the table that maps inputs to outputs.

author: NorthGuy
author_rank: Super Contributor
timestamp: August 07, 2018, 10:20:17 pm
content: Quote from: hamster_nz on August 07, 2018, 09:46:20 pmThat's true, however, in the "bcd" case, it all should synthesise into a 9x12 LUT (9 inputs, 12 outputs). Given that the MSB of the result is always '0' and the LSB is straight wire from the LSB of the input, it is, in fact, 8x10 LUT - 10 slices in Xilinx (40 LUTs) - much simple than doing divisions.Thus, you describe the behaviour with any operations on the variables you want, and the tools should use this information to figure out the set of values to put into the 8x10 LUT, shouldn't they?

author: hamster_nz
author_rank: Super Contributor
timestamp: August 07, 2018, 11:51:10 pm
content: Quote from: NorthGuy on August 07, 2018, 10:20:17 pmOf course, and they will if you use a lookup table (however it might end up in BRAM rather than LUTs depending if the design is clocked)BCD conversion for big numbers (e.g. 12 bits or more) is when things get interesting, when you can't use lookup tables.

author: rstofer
author_rank: Super Contributor
timestamp: August 09, 2018, 02:12:32 pm
content: Quote from: hamster_nz on August 07, 2018, 09:46:20 pmThis really is the 'right' way to do the job for such a simple function, once converted to HDL. Among other things, if I wrote the conversion as a table lookup, I might be able to understand how it works a year from now.Earlier I showed an example of your code for building these tables from a file. That works fine for my application where the table is object code for a CPU. In the case of the converter, the table values are unlikely to change and there is no real reason for using an external file.

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 09, 2018, 09:38:03 pm
content: There's a problem with the way your counters are reset IMO.Since you don't use any global reset, a lot of your signals are in an unknown state initially. This may or may not be a problem when using FPGAs (since they have internal global resets anyway), although the initial state of some signals may not be what you want. I always suggest using explicit reset signals. And if you're trying to simulate your code, you'll get errors (undefined states).The reset signal of your counters rely on signals that themselves may have undefined inital states.Besides, the 'Trigger_generator' looks fishy to me. Again, it has no global reset and the reset condition of the internal counter 'trigg' doesn't look right to me?Code:if(outputCounter=ms250And100us) THENresetCounter<='1'; -- the reset signal for the counter is active low, so the counter would get out of reset only when having the ms250And100us value?elseresetCounter<='0';end if;There's a lot of room for improvement as well, I won't add to what has been said already. But what's up with the indentation and lack of whitespace? Was it in the process of copying your code for the forum or is it your habit of coding? If it's the latter, you may want to enter a VHDL obfuscation contest.

author: rstofer
author_rank: Super Contributor
timestamp: August 10, 2018, 12:46:48 am
content: As to the BCD conversion, maybe this will workCode:library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.NUMERIC_STD.ALL;entity BCD isPort ( Value : in STD_LOGIC_VECTOR ( 7 downto 0);BCD : out STD_LOGIC_VECTOR (11 downto 0));end BCD;architecture Behavioral of BCD istype LookupTableType is array(0 to 255) of std_logic_vector(11 downto 0);signal LookupTable : LookupTableType :=(x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009",x"010",x"011",x"012",x"013",x"014",x"015",x"016",x"017",x"018",x"019",x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009", -- change these linesx"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009", -- too lazy to type properx"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009", -- valuesx"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009",x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009",x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009",x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009",x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009",x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009",x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009",x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009",x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009",x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009",x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009",x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009",x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009",x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009",x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009",x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009",x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009",x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009",x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009", --x"000",x"001",x"002",x"003",x"004",x"005",x"006",x"007",x"008",x"009", -- down to herex"250",x"251",x"252",x"253",x"254",x"255");beginBCD <= LookupTable(to_integer(unsigned(Value)));end Behavioral;Note that most of the table initialization values are wrong. I just copied and pasted my way through it, I wasn't interested enough to type the proper values 256 times.I know this synthesizes but I didn't tie it to a constraints file and actually run it on a board.