- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm trying to learn VHDL so I thought I'd try converting the "my_first_fpga" example from verilog to VHDL (how complicated can adding one to a number be?), three hours later, lots of googling and searching through books has yielded no result. Sorry if this is the wrong place to ask (if so where is a better place?)
So I run this code through the simulator, apply a 50Mhz clock to CLK and get nothing from the counter bus. to make sure the process is running I output CLK to OUT, if I hard code a value ie X"FFFF0000" to counter it outputs that value but counter := counter +1 gets me no where. Also is it possible to step through code as with C? Here is my code:-- import std_logic from the IEEE library
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
-- this is the entity
entity counter_example is
port (
CLK : in std_logic;
OUT1: out std_logic;
Q : out std_logic_vector(31 downto 0));
end counter_example;
architecture counter_code of counter_example is
begin
process (CLK)
variable counter : std_logic_vector(31 downto 0);
begin
counter := counter + 1;
OUT1 <= CLK; -- Sanity Check that I am actually outputting something
Q <= counter;
end process;
end counter_code;
Thanks.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thats the reason why i stay with verilog HDL as VHDL has so much typo for such simple stuff.
module counter_example { CLK, OUT1 Q }; input CLK; output OUT1; output [31:0] Q; always @ ( posedge CLK ) Q <= Q + 1; // or write 32'd1 to avoid warnings due to truncation always @ ( posedge CLK ) OUT1 <= CLK; endmodule // thats it stepping trough like c code, haven't seen that even on our SUN used for ASIC designs with much much more expensiv tools ($$$ per year)- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The edge sensitive condition is missing. See the VHDL templates in Quartus editor for the basic syntax of clock synchronous logic.
Although VHDL is a hardware description language rather than being executed line by line like a C program, you can single step it in a simulator as ModelSim, that is interpreting the VHDL text in this place.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks, a friend suggested verilog over VHDL, maybe I should listen to him.
Question: The following worksQ : buffer std_logic_vector(31 downto 0));
if CLK'EVENT AND CLK = '1' then
Q <= Q + 1 ;
end if;
But if the counter is stored in a variable and copied to Q on a positive edge it doesn't work. ie: if CLK'EVENT AND CLK = '1' then
counter := counter + 1;
Q <= counter ;
end if;
Why doesn't that work?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
First off, welcome to VHDL.
2nd. There is a reason it is not updating with the variable and its all down to how the language works. You should find that if you swap around the counter + 1 statement and the q <= counter statement (so the Q output is set first) it will work. This is because variables are updated immediately, whereas signals are not. The code you currently have will work in a simulator, but when you synthesise it, as the variable is used to assing a value to Q, there is no need to store the value in counter between clock cycles (because you have stored the value in Q. Now if you swapped the 2 statements around to this:if CLK'EVENT AND CLK = '1' then
Q <= counter ;
counter := counter + 1;
end if;
The synethsiser notes that counter is not assigned to a register at the end of the process, but you do give the value to Q before you increment it, so it will create one for you to store the value of counter between clocks. Like I said before, either way round will work in simulation, but not in synthesis. 3rdly. As you are new to VHDL please can I ask you to stop using std_logic_unsigned/arith now, and use the IEEE standard instead, which is numeric_std, so you dont get into bad (or old fashioned) habits. You can also use rising_edge(clk) instead of clk'event and clk = '1', as it is slightly safer to use in simulation. The rising_edge function will only trigger when the clk signal changes from '0' or 'L' to '1' or 'H', whereas the latter will trigger whenever the clk signal changes from anything to '1' (so 'X', 'U', '-', '0', 'Z', 'H', 'L'). the numeric_std library offers the signed and unsigned types which you can use in the same file (with the std_logic_unsigned/signed you cannot use both types at the same time). You could also do this counter simply by doing this:
signal counter : unsigned(31 downto 0);
.....
process(clk)
begin
if rising_edge(clk) then
counter <= counter + 1;
end if;
end process;
Q <= std_logic_vector(counter);
Another thing to keep in mind is that port lists only HAVE to be std_logic/vector at the top level, theres nothing to stop you using integers, unsigneds, booleans, fixed point types in the port definition of an entity.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You should show complete library and signal/variable definition.
Generally, this code is supposed to work. But possibly, you found a way to thwart it. if CLK'EVENT AND CLK = '1' then
counter := counter + 1;
Q <= counter ;
end if;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- You should show complete library and signal/variable definition. Generally, this code is supposed to work. But possibly, you found a way to thwart it.
if CLK'EVENT AND CLK = '1' then
counter := counter + 1;
Q <= counter ;
end if;
--- Quote End --- Like I said, it thwarts the synthesisor because there it sees no point in registering counter, because it registers Q instead. Because counter never read's back from Q, counter is always assumed to be 0. The best way to fix it and make it synethsise is swap the 2 statement, or do this instead: if CLK'EVENT AND CLK = '1' then
counter := Q;
counter := counter + 1;
Q <= counter ;
end if;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Tricky, that got me up and running :)
Does verilog operate the same way in relation to instruction flow and signal vs variable? Also is there a good source for these idiosyncrasies in the language? In an unrelated question every time I recompile I need to goto Tools -> Simulator Tool -> Generate Functional Simulation Netlist to run a simulation, is there a way to automatically generate the netlist or am I doing something wrong?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Thanks Tricky, that got me up and running :) Does verilog operate the same way in relation to instruction flow and signal vs variable? Also is there a good source for these idiosyncrasies in the language? In an unrelated question every time I recompile I need to goto Tools -> Simulator Tool -> Generate Functional Simulation Netlist to run a simulation, is there a way to automatically generate the netlist or am I doing something wrong? --- Quote End --- I do not know anything about verilog, though the words blocking and non-blocking assignments has been used before to equate signals and variables in VHDL from time to time. for the 2nd point you're simulating a post-P&R netlist, which will be slow (but will function as it would on real hardware). In modelsim you can simulate your VHDL text files directly with no synthesis required. You will need to create a testbench to stimulate all of the inputs (like generating a clock) but thats quite straight forward. To generate a clock in a VHDL testbench you can just use the line:
signal clock : std_logic := '0';
clk <= not clk after 10 ns; --will give 50MHz clock
and then just connect the clock to the clk port on your counter.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
in verilog you can use blocking and non blocking assignments, you can mix them but you need to decide which one you use inside an always block for this particular block
non blocking q <= counter; counter <= counter + 1; is the same as if you swap the lines counter <= counter + 1; q <= counter; both work the same way. but if you use blocking assignments then it does matter in which order you write your code. i personaly use non blocking assingments as ther are enough bugs around to catch ...- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I found the "Start Compilation and Simulation" option in Quartus which saves a few steps, however I thought I'd try setting up a test bench. I installed ModelSim, when I run the simulation and look in wave I can see the clock but counter_out has no value. Did I set this up correctly?
-- import std_logic from the IEEE library
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
-- this is the entity
entity counter_example is
port (
counter_out : buffer unsigned(31 downto 0));
end counter_example;
architecture counter_code of counter_example is
signal clock : std_logic := '0';
begin
process (clock)
begin
clock <= not clock after 10 ns; --will give 50MHz clock
if rising_edge(clock) then
counter_out <= counter_out + 1;
end if;
end process;
end counter_code;
Thanks
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Your process that generates the clock is also triggered by the clock, which won't work. It's a bit like the chicken-and-egg problem ;)
You should have two processes, one to generate the clock, and another one that triggers on it: Clockgen: process
begin
clock <= not clock after 10 ns; --will give 50MHz clock
end process;
Sim: process (clock)
begin
if rising_edge(clock) then
counter_out <= counter_out + 1;
end if;
end process;
It is also a good idea to add a reset signal to give your counter (and clock) an initial value. If you don't do that counter_out will start with UUUUU (uninitialised) in the simulator and will become XXXXX (unknown) at the first clock cycle.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- Your process that generates the clock is also triggered by the clock, which won't work. It's a bit like the chicken-and-egg problem ;) You should have two processes, one to generate the clock, and another one that triggers on it:
Clockgen: process
begin
clock <= not clock after 10 ns; --will give 50MHz clock
end process;
--- Quote End --- This does not have to be inside a process, as it is a simple 1 line statement. Also, remember do not put this kind of code in your synthesisable code. Keep them separate as a testbench and a counter. If you put this code in and tried to synthesise it you'll some odd things getting generated.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, I mixed up with the way I usually do a clock, which is either
Clockgen: process
begin
wait for 10ns;
clock <= not clock;
end process;
orClockgen: process
begin
clock <= '0';
wait for 10ns;
clock <= '1';
wait for 10ns;
end process;
The latter is longer but doesn't require to initialize the clock value
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page