Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] VHDL dcfifo duplicate values on read output

Status
Not open for further replies.
If you insist on using variables you will come up a lot of resistance - Using them is seen as "bad form" and make people think of you as a converted software programmer, not someone who thinks in circuits.

well unfortunately that's what I am and I don't think that I'll become a good FPGA circuit designer that quickly.
I'm trying to study that area and pick up information.
The books just said that signals are only required to interconnect processes, while variables are used for local processes (they didn't mention anything about that those are not preferred). Anyway I picked it up thanks.

But it still doesn't solve my original problem.

delay:=delay(3 downto 0) & rdempty_sig;
if ldma_rdy = '1' and delay="00000" and poscnt<1024 then

Adding delay to the empty flag will just make things worse.
original empty flag to read relationship.

I still don't get it, because closer to the end of the buffer "delay" would be 00001 -- meaning it would not read anything from the dcfifo, it continues... 00010 ... still not reading (still delaying) 00100 again .. it would delay the whole read quite a few cycles until 1 disappears in the std_logic_vector until enough data is stacked up in the fifo.
Since the output (12 MHz) is running faster than the input (5 MHz) this should not be a problem?

However it doesn't work as mentioned so there is a problem and indeed I don't understand the circuit...
 

well unfortunately that's what I am and I don't think that I'll become a good FPGA circuit designer that quickly.
I'm trying to study that area and pick up information.
The books just said that signals are only required to interconnect processes, while variables are used for local processes (they didn't mention anything about that those are not preferred). Anyway I picked it up thanks.

But it still doesn't solve my original problem.

delay:=delay(3 downto 0) & rdempty_sig;
if ldma_rdy = '1' and delay="00000" and poscnt<1024 then

I still don't get it, because closer to the end of the buffer "delay" would be 00001 -- meaning it would not read anything from the dcfifo, it continues... 00010 ... still not reading (still delaying) 00100 again .. it would delay the whole read quite a few cycles until 1 disappears in the std_logic_vector until enough data is stacked up in the fifo.
Since the output (12 MHz) is running faster than the input (5 MHz) this should not be a problem?

However it doesn't work as mentioned so there is a problem and indeed I don't understand the circuit...
Your variable based shift register behaves differently than you describe.
The code will instead make this happen 0001, 0011, 0111, 1111 when the empty flag goes empty and 1111, 1110, 1100, 1000, 0000 when going non-empty. Your whole method of doing this is not very hardware like.

Have you ever heard of the work rate word problem? you are filling the fifo with 5 MHz data and reading at 12 MHz so you will underflow the FIFO a bunch of times repeatedly as the input rate does not match the maximum output rate. Therefore delaying the empty flag just aggravates the problem. Can't you read a timing diagram? It's pretty obvious that delaying the empty flag only makes things worse. You are generating the read based on the empty flag unless you've radically changed your VHDL software program. I think you need to read a book on logic design, which I don't think they teach to software engineers. You also seem to suffer from the software compile run on hardware mentality which is flawed when it comes to FPGA design as this is hardware and hardware is much harder to debug on hardware as you end up with severe limitations on visibility. That is why others and myself have told you to run this on a simulator and see all the signals and the interactions between them.
 

However it doesn't work as mentioned so there is a problem and indeed I don't understand the circuit...

Please - use a simulator. You'll likely get the problem fixed within a day.
 

Please - use a simulator. You'll likely get the problem fixed within a day.

I tried that but didn't get very far...

Since I'm new to this I tried following tutorial
https://www.youtube.com/watch?v=qZNL1C0TwY8 (but selected VHDL and selected 10ms / 20ms / 40ms)

Is there a 1ms limitation with Modelsim Starter?

Can someone fix the Picture uploading?
"error: Upload failed due to failure writing temporary file."

Edaboard Error:
https://i.snag.gy/hgz0t6.jpg

Modelsim:
https://i.snag.gy/RGdXFv.jpg

https://i.snag.gy/jViZDT.jpg


Edit:
ok got it ... the waveform did not get generated into the VHDL testbench file... Modelsim is cruel.. but I can handle that
 
Last edited:

@player80:

Other than the ESA, I don't think anyone prefers variables in the long run. ads_ee and TD gave my combined "useful for naming common subexpressions" and "not useful for locally declared signals" opinions already. I'll just add that VHDL is terrible at times -- you should be able to declare signals local to a process and you should have some option to declare a variable that defaults to undefined at the end of a process.


The issue you have is explained as follows:
Upon seeing empty, it takes 1 cycle to generate a read.
Upon seeing a read, it takes 1 cycle to generate empty.
Decisions are made on every cycle.

This means the effects of (empty = 0) on cycle N will not modify the value of empty until cycle N+2. It will affect the value of read on cycle N+1.
so you have:
Code:
cycle 0:  empty = 0, read = 0, next_empty = 0, next_read = 1 // empty is 0, so next_read is 1.
cycle 1:  empty = 0, read = 1, next_empty = 1, next_read = 1 // empty is 0, so next_read is 1.  read is 1, so next_empty is 1
cycle 2:  empty = 1, read = 1, next_empty = 1, next_read = 0 // fifo is empty, but read is 1.  fifo underflow.


For your exact case, you can solve this by setting the logic to be:
(user_wants_to_read = '1' and empty = '0' and read = '0')

This gives:
Code:
cycle 0:  empty = 0, read = 0, next_empty = 0, next_read = 1 // empty is 0, so next_read is 1.
cycle 1:  empty = 0, read = 1, next_empty = 1, next_read = 1 // empty is 0 but read is 1, so next_read is 0.  read is 1, so next_empty is 1
cycle 2:  empty = 1, read = 0, next_empty = 1, next_read = 0 // fifo is empty.

The downside is that this can only read every other cycle. For your case, where data comes in at 5MHz and is processed at 12MHz, this can be ok.

In the more general case, you can use an almost_empty (proxy for size > 1) or similar signal giving two similar expression that can be used.
version 1: (user_wants_to_read = '1' and empty = '0' and (read = '0' or almost_empty = '0'))
version 2: (user_wants_to_read = '1' and ((read = '0' and empty = '0') or (almost_empty = '0')))
 

I tried that but didn't get very far...

Since I'm new to this I tried following tutorial
https://www.youtube.com/watch?v=qZNL1C0TwY8 (but selected VHDL and selected 10ms / 20ms / 40ms)

Is there a 1ms limitation with Modelsim Starter?

That shows how to generate a testbench from an input waveform - not really that useful in the long run. You have much more control generating these things in code.
There is no time limitation in modelsim stater (maybe if you're hand drawing a waveform). It just has a 10000 line limit, after which it runs really slowly.

a basic testbench would be something like:


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
entity some_tb is
end entity some_tb;   -- no IO, because it's a testbench
 
architecture test of some_tb is
  constant CLK_PERIOD : time  := 10 ns;   -- this is nice and easy to read on the wave viewer
  
  signal clk    : std_logic := '1';
  signal rst    : std_logic;
  
  signal ips    : std_logic_vector(7 downto 0);
  signal ops    : std_logic_vector(7 downto 0);
  
  procedure wait_for_clks( n : integer := 1) is 
  begin
    for i in 1 to n loop
      wait until rising_edge(clk);
    end loop;
  end procedure wait_for_clks;
begin
 
  -- clock and reset generation
  rst <= '1', '0' after 3.5 * CLK_PERIOD;
  clk <= not clk after CLK_PERIOD;
  
  -- the Design under test
  DUT_inst : entity my_lib.my_ent
  port map (
    ---ips..
    -- ops
  )
 
  stim_proc : process
  begin
    ip  <= x"00";
    wait until rst = '0';
    wait_for_clks;
    
    ip  <= x"0A";
    
    wait_for_clks(10);
    
    ip <= x"FF";
    
    wait_for_clks(1000);
    
    ip <= x"A5";
    
    wait;  -- end testbench
  end process;
 
end architecture;

 

Can someone fix the Picture uploading?
"error: Upload failed due to failure writing temporary file."

I never use a url for uploading I normally upload directly from a file local to my machine.
 

"error: Upload failed due to failure writing temporary file."

Edaboard Error

Try deleting the S in 'https' in your url. The reason is because S has to do with a security layer.

Also try the 'Add an Image' button, rather than the 'Insert Image' icon.
 

That shows how to generate a testbench from an input waveform - not really that useful in the long run. You have much more control generating these things in code.
There is no time limitation in modelsim stater (maybe if you're hand drawing a waveform). It just has a 10000 line limit, after which it runs really slowly.

a basic testbench would be something like:


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
entity some_tb is
end entity some_tb;   -- no IO, because it's a testbench
 
architecture test of some_tb is
  constant CLK_PERIOD : time  := 10 ns;   -- this is nice and easy to read on the wave viewer
  
  signal clk    : std_logic := '1';
  signal rst    : std_logic;
  
  signal ips    : std_logic_vector(7 downto 0);
  signal ops    : std_logic_vector(7 downto 0);
  
  procedure wait_for_clks( n : integer := 1) is 
  begin
    for i in 1 to n loop
      wait until rising_edge(clk);
    end loop;
  end procedure wait_for_clks;
begin
 
  -- clock and reset generation
  rst <= '1', '0' after 3.5 * CLK_PERIOD;
  clk <= not clk after CLK_PERIOD;
  
  -- the Design under test
  DUT_inst : entity my_lib.my_ent
  port map (
    ---ips..
    -- ops
  )
 
  stim_proc : process
  begin
    ip  <= x"00";
    wait until rst = '0';
    wait_for_clks;
    
    ip  <= x"0A";
    
    wait_for_clks(10);
    
    ip <= x"FF";
    
    wait_for_clks(1000);
    
    ip <= x"A5";
    
    wait;  -- end testbench
  end process;
 
end architecture;


I have been trying for quite some time now but Quartus won't give me any output files into modelsim/rtl_work

The youtube video works okay (except that modelsim is not generating any appropriate vhdl code for the waveforms which obviously is a bug in QII 13.01, I'm using a Cyclone II so I can't go higher). However if I try to reproduce this with my other testproject it doesn't work.

Modelsim only shows up:
work (empty) path rtl_work
rtl_work (empty)

and indeed the directory is almost empty, there's only _temp and _info in it.

Quartus II shows up the top level vhdl file in the Design Units tab on the left side below "work"

I have also compared the settings between my project and the youtube sample project (which also works locally) but I couldn't find any difference so far.

does anyone know how to fix that?


----

ok got it ... there was an error in the vhdl code referencing to a non existing library (while the Analysis & Synthesis did not complain about it Modelsim did). I fixed that now and will try to continue to build the testbench
 
Last edited:

Seems like I got it work thanks for all the help.

The simulation really helped a little bit to see what's going on!
The biggest problem was probably that all that is new to me and I had some issues understanding the replies (even though they were really good).
The simulation was the key to fix the issue.

Thanks a lot for all the feedback and ideas (and guidance).
 
Last edited:

I have been trying for quite some time now but Quartus won't give me any output files into modelsim/rtl_work

The youtube video works okay (except that modelsim is not generating any appropriate vhdl code for the waveforms which obviously is a bug in QII 13.01, I'm using a Cyclone II so I can't go higher). However if I try to reproduce this with my other testproject it doesn't work.

Modelsim only shows up:
work (empty) path rtl_work
rtl_work (empty)

and indeed the directory is almost empty, there's only _temp and _info in it.

Quartus II shows up the top level vhdl file in the Design Units tab on the left side below "work"

I have also compared the settings between my project and the youtube sample project (which also works locally) but I couldn't find any difference so far.

does anyone know how to fix that?


----

ok got it ... there was an error in the vhdl code referencing to a non existing library (while the Analysis & Synthesis did not complain about it Modelsim did). I fixed that now and will try to continue to build the testbench

The code I gave you should not be compiled in quartus. It is much more straight forward to compile the code directly in modelsim as you then have more control. You can type the following commands straight into the modelsim console

Code:
#compile the code
vcom my_entity.vhd
vcom my_testbench.vhd

vsim my_testbench

# set the simulation time, or if you have a self checking testbench, do run -all
run 10 us
 
Ah that's convenient! Thanks
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top