002e4840 f4 f5 f6 f6 f7 f8 f9 f9 fa fb fc fc fd fe fe ff |................|
002e4850 00 01 01 02 03 03 04 05 06 06 07 08 09 09 0a 0b |................|
002e4860 0b 0c 0d 0e 0e 0f 10 11 11 12 13 13 14 15 16 16 |................|
002e4870 17 18 18 19 1a 1b 1b 1c 1d 1e 1e 1f 20 20 21 22 |............ !"|
002e4880 23 23 24 25 25 26 27 28 28 29 2a 2b 2b 2c 2d 2d |##$%%&'(()*++,--|
002e4890 2e 2f 30 30 31 32 33 33 34 35 35 36 37 38 38 39 |./00123345567889|
002e48a0 3a 3a 3b 3c 3d 3d 3e 3f 40 40 41 42 42 43 44 45 |::;<==>?@@ABBCDE|
002e48b0 45 46 47 47 48 49 4a 4a 4b 4c 4d 4d 4e 4f 4f 50 |EFGGHIJJKLMMNOOP|
002e48c0 51 52 52 53 54 55 55 56 57 57 58 59 5a 5a 5b 5c |QRRSTUUVWWXYZZ[\|
002e48d0 5c 5d 5e 5f 5f 60 61 62 62 63 64 64 65 66 67 67 |\]^__`abbcddefgg|
002e48e0 68 69 6a 6a 6b 6c 6c 6d 6e 6f 6f 70 71 71 72 73 |hijjkllmnoopqqrs|
002e48f0 74 74 75 76 77 77 78 79 79 7a 7b 7c 7c 7d 7e 7e |ttuvwwxyyz{||}~~|
002e4900 7f 80 81 81 82 83 84 84 85 86 86 87 88 89 89 8a |................|
002e4910 8b 8c 8c 8d 8e 8e 8f 90 90 91 92 93 93 94 95 95 |................|
begin
if rising_edge(clock_out) then
ldma_rdy := dma_rdy;
rdreq_sig <= '0';
valid_out <= '0';
if (ldma_rdy = '0') then
poscnt:=0;
end if;
if (ldma_rdy = '1' and poscnt<1024 and rdempty_sig = '0') then
rdreq_sig <= '1';
valid_out <= '1';
--po<=rdusedw_sig(7 downto 0);
po<=q_sig; --std_logic_vector(to_unsigned(counter, 8));
--po<=std_logic_vector(to_unsigned(counter, 8));
counter:=counter+1;
poscnt:=poscnt+1;
end if;
if rising_edge(clk_in) then
wrreq_sig <= '0';
data_sig <= x"00";
if (sync_in = '1') then
enabledata:='1';
bytepos:=0;
end if;
if (valid_in = '1' and enabledata = '1') then
bytebuf(7-bytepos):=dat;
bytepos:=bytepos+1;
if (bytepos = 8) then
wrreq_sig <= '1';
data_sig <= std_logic_vector(to_unsigned(counter, 8));
counter := counter+1;
bytepos:=0;
end if;
end if;
without the entire design, it's difficult to say whats going on, and whether you're just writing every value twice, or ready every valid value twice.
Can you post the code and the testbench you used to test the design?
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library dcf;
use dcf.all;
entity leddecoder is
port(valid_in: std_logic;
clk_in: std_logic;
sync_in: std_logic;
dat: in std_logic;
valid_out: out std_logic;
po: out std_logic_vector(7 downto 0);
clock_out: in std_logic;
rst: in std_logic;
dma_rdy: in std_logic;
watermark: in std_logic);
end leddecoder;
architecture behaviour of leddecoder is
signal rdclk_sig: std_logic;
signal wrempty_sig: std_logic;
signal wrfull_sig: std_logic;
signal q_sig: std_logic_vector(7 downto 0);
signal rdempty_sig: std_logic;
signal wrclk_sig: std_logic;
signal wrreq_sig: std_logic;
signal wrusedw_sig: std_logic_vector(11 downto 0);
signal data_sig: std_logic_vector(7 downto 0);
signal rdreq_sig: std_logic;
signal rdusedw_sig: std_logic_vector(11 downto 0);
COMPONENT dcf
PORT (
rdclk : IN STD_LOGIC ;
wrempty : OUT STD_LOGIC ;
wrfull : OUT STD_LOGIC ;
q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
rdempty : OUT STD_LOGIC ;
wrclk : IN STD_LOGIC ;
wrreq : IN STD_LOGIC ;
wrusedw : OUT STD_LOGIC_VECTOR (11 DOWNTO 0);
data : IN STD_LOGIC_VECTOR (7 DOWNTO 0);
rdreq : IN STD_LOGIC ;
rdusedw : OUT STD_LOGIC_VECTOR (11 DOWNTO 0)
);
END COMPONENT;
TYPE MACHINE_STATE IS (STATE_IDLE, STATE_WRITE_1, STATE_WRITE_2, STATE_PAUSE); -- Define the states
SIGNAL State : MACHINE_STATE := STATE_IDLE; -- Create a signal that uses
begin
dcf_inst : dcf PORT MAP (
data => data_sig,
rdclk => clock_out,
rdreq => rdreq_sig,
wrclk => clk_in,
wrreq => wrreq_sig,
q => q_sig,
rdempty => rdempty_sig,
wrempty => wrempty_sig,
wrfull => wrfull_sig,
wrusedw => wrusedw_sig,
rdusedw => rdusedw_sig
);
process(clock_out)
variable startread: std_logic := '0';
variable readpos: natural range 0 to 500:= 0;
variable data_avail: std_logic := '0';
variable cnt_enable: natural range 0 to 3:=0;
variable dpos: std_logic_vector(2 downto 0);
variable init: std_logic := '0';
variable transfer_started: std_logic := '0';
variable counter: natural range 0 to 255 := 0;
variable dma_rdy_toggled: std_logic := '1';
variable startcnt: integer := 0;
variable poscnt: integer := 0;
variable lrdempty_sig: std_logic := '0';
variable ldma_rdy: std_logic := '0';
begin
if rising_edge(clock_out) then
ldma_rdy := dma_rdy;
rdreq_sig <= '0';
valid_out <= '0';
if (ldma_rdy = '0') then
poscnt:=0;
end if;
if (ldma_rdy = '1' and poscnt<1024 and rdempty_sig = '0') then
rdreq_sig <= '1';
valid_out <= '1';
--po<=rdusedw_sig(7 downto 0);
po<=q_sig; --std_logic_vector(to_unsigned(counter, 8));
--po<=std_logic_vector(to_unsigned(counter, 8));
counter:=counter+1;
poscnt:=poscnt+1;
end if;
end if;
end process;
process(clk_in)
variable bytebuf: std_logic_vector(7 downto 0) := x"00";
variable enabledata: std_logic := '0';
variable bytepos: integer range 0 to 8 := 0;
variable counter: natural range 0 to 255 := 0;
begin
if (rst = '1') then
wrreq_sig <= '0';
elsif rising_edge(clk_in) then
wrreq_sig <= '0';
data_sig <= x"00";
if (sync_in = '1') then
enabledata:='1';
bytepos:=0;
end if;
if (valid_in = '1' and enabledata = '1') then
bytebuf(7-bytepos):=dat;
bytepos:=bytepos+1;
if (bytepos = 8) then
wrreq_sig <= '1';
data_sig <= std_logic_vector(to_unsigned(counter, 8));
counter := counter+1;
bytepos:=0;
end if;
end if;
end if;
end process;
end behaviour;
First off, if you're new to VHDL, I suggest you stay away from variables entirely. There is nothing you can do with variables that you cannot do with a signal. Signals will give you behaviour you expect, whereas variables do have some gotchas with them.
Without a testbench, it can be difficult to see whats going wrong. With simulation you can easily debug this code.
Is the FIFO a lookahead fifo? If it is, then I can you'll get the output twice at the start of a sequence as the read_request only goes high with the valid, meaning you'll be outputting the same output twice and marking it valid. This would be easy to see.
lused := to_integer(unsigned(rdusedw_sig));
if lused > 0 then
...
end if;
if rdempty_sig = 0 then
po <= rdusedw_sig(7 downto 0);
...
end if;
00002f90 01 01 00 01 01 00 01 02 01 00 01 01 01 00 01 01 |................|
00002fa0 00 01 01 01 00 01 01 00 01 02 01 00 01 01 01 00 |................|
00002fb0 01 01 00 01 02 01 00 01 01 00 01 02 01 00 01 01 |................|
00002fc0 01 00 01 01 00 01 02 01 00 01 01 01 00 01 01 00 |................|
00002fd0 01 01 01 00 01 01 00 01 02 01 00 01 01 00 01 01 |................|
00002fe0 01 00 01 01 00 01 02 01 00 01 01 01 00 01 01 00 |................|
00002ff0 01 02 01 00 01 01 01 00 01 01 00 01 01 01 00 01 |................|
00003000 00 00 00 ff fe fd fc fb fb fb fa fa f9 f9 f8 f8 |................|
00003010 f7 f7 f7 f6 f6 f5 f5 f4 f4 f4 f3 f3 f2 f2 f1 f1 |................|
00003020 f1 f0 f0 ef ef ee ee ee ed ed ec ec eb eb ea ea |................|
00003030 ea e9 e9 e8 e8 e7 e7 e7 e6 e6 e5 e5 e4 e4 e4 e3 |................|
00003040 e3 e2 e2 e1 e1 e1 e0 e0 df df de de dd dd dd dc |................|
00003050 dc db db da da da d9 d9 d8 d8 d7 d7 d7 d6 d6 d5 |................|
00003060 d5 d4 d4 d4 d3 d3 d2 d2 d1 d1 d0 d0 d0 cf cf ce |................|
00003070 ce cd cd cd cc cc cb cb ca ca ca c9 c9 c8 c8 c7 |................|
1 2
___ ___ ___ ___
clk ___| |___| |___| |___| |___
_____________________
empty _____________|
_______________
rd_en ____| ^ |______________
Empty is still 0
so it reads an empty FIFO
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 if rising_edge(clock_out) then ldma_rdy := dma_rdy; rdreq_sig <= '0'; valid_out <= '0'; if (ldma_rdy = '0') then poscnt:=0; end if; if (ldma_rdy = '1' and poscnt<1024 and rdempty_sig = '0') then rdreq_sig <= '1'; -- reads will occur after the FIFO is already empty -- as you are looking at the old state of rdempty_sig.
Hmm... can you give me a hint how to overcome that problem?
Hmm... can you give me a hint how to overcome that problem?
The second method performs or adds some form of size > N, N >=2 check. In this case, you can read from the fifo if "size >= N or size >= 1 and didn't read in the last (N-1) cycles" -- for N = 2. For this example, it means that when size >= 2 you will read at full rate.
if ldma_rdy = '1' and poscnt<1024 and rdempty_sig = '0' and unsigned(rdusedw_sig) > 0 then
...
end if;
variable delay: std_logic_vector(3 downto 0) :="1111";
...
delay:=delay(2 downto 0) & rdempty_sig;
if ldma_rdy = '1' and delay = "0000" and poscnt<1024 then
Stop using variables and you'll have a lot less problems with understanding why things work or don't work. I've been developing FPGAs and ASICs for over 2 decades and I've never resorted to using variables or used blocking (Verilog) statements in sequential (FF) code. The only place I use variables is for memories due to the extreme performance hit you will see in the simulator if you create a large memory in VHDL and don't use a variable declaration. Of course there are a few others here that do use them but they admittedly use them sparingly and not for creating FFs mostly for generating some combinational logic that feeds a FF or similar.so shouldn't something like that delay it for a few cycles:
Code:variable delay: std_logic_vector(3 downto 0) :="1111"; ... delay:=delay(2 downto 0) & rdempty_sig; if ldma_rdy = '1' and delay = "0000" and poscnt<1024 then
because this also doesn't seem to work :-(
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 variable ff_mess : unsigned (3 downto 0) := "0000"; process (clk) begin if rising_edge(clk) then ff_mess := ff_mess + 1; -- variable ff_mess has to be updated prior to the COMPARE! It is NOT a FF at this point it is a combinational ADD. if (ff_mess > 0) then -- actually does (ff_mess + 1) > 0 so now you have an ADD and a COMPARE in the same combinational cone, lower Fmax. -- do stuff end if; end if; end process;
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 11 variable active_tx := std_logic; process (clk) begin if rising_edge(clk) then tx_ok := tx_enabled AND tx_ready AND buffer_cnt > 10 AND tx_enable AND NOT rx_backpressure; if (tx_ok = '1') then -- now it's easy to see what this chunk of code is supposed to do, instead of decoding some long logic equation -- do some tx stuff end if; end if; end process;
Adding delay to the empty flag will just make things worse.and also that one:
delay:=delay(3 downto 0) & rdempty_sig;
if ldma_rdy = '1' and delay="00000" and poscnt<1024 then
why does that not work?
In that case I would expect to have at least 4 more entries in the dcfifo that should be enough to avoid a buffer underrun no?
1 2
___ ___ ___ ___
clk ___| |___| |___| |___| |___
_____________________
empty _____________|
_______________
rd_en ____| ^ |______________
Empty is still 0
so it reads an empty FIFO
1 2
___ ___ ___ ___ ___
clk ___| |___| |___| |___| |___| |___
_____________________________
empty _____________| ^
_______________ <- read while empty
rd_en ____| ^ |______________________
Empty is still 0, so it starts
another read of an empty FIFO
______________
delay ____________________________|
_______________________________
rd_en ____| ^ ^ ^ ^|______
OK E E E
Four reads are occuring with
three of them on an empty FIFO!
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 library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity test is port ( clk : in std_logic; o : out std_logic ); end test; architecture behav of test is begin process (clk) variable cnt : unsigned (3 downto 0) := x"0"; begin if rising_edge(clk) then cnt := cnt + 1; if (cnt < x"A") then o <= '1'; else o <= '0'; end if; end if; end process; end behav;
Stop using variables and you'll have a lot less problems with understanding why things work or don't work.
produces the following elaborated schematic.
View attachment 133068
Notice the registers for cnt that feed the ADD and then feed the comparison with x"A" before generating the o output.
Changing this to a signal results in the following circuit, which has slightly different timing but will also have a much improved Fmax.
View attachment 133069
signals are assigned at the end of the process
Code VHDL - [expand] 1 2 3 4 5 6 7 process begin op <= '0'; wait until rising_edge(clk); op <= ip; end process;
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?