[syntax=vhdl]library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity circular_buffer is
generic(
DATA_WIDTH : integer := 8;
ADDR_WIDTH : integer := 12 -- 2^12 = 4096 = 4k
);
Port (
-- Input clock domain
clk : in STD_LOGIC;
rstn : in STD_LOGIC;
wr_en : in STD_LOGIC;
wr_addr : in STD_LOGIC_VECTOR (ADDR_WIDTH-1 downto 0);
data_in : in STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
-- Output clock domain
-- s_clk : in STD_LOGIC;
rd_en : in STD_LOGIC;
rd_addr : in STD_LOGIC_VECTOR (ADDR_WIDTH-1 downto 0);
data_out : out STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
full : out STD_LOGIC;
empty : out STD_LOGIC;
data_ready : out STD_LOGIC
);
end circular_buffer;
architecture Behavioral of circular_buffer is
constant ts_packet_size : integer := 188;
signal byte_count : unsigned(ts_packet_size-1 downto 0) := (others => '0');
signal fifo_empty : std_logic := '1';
signal fifo_full : std_logic := '0';
signal rd_ptr : unsigned(ADDR_WIDTH-1 downto 0) := (others => '0');
signal wr_ptr : unsigned(ADDR_WIDTH-1 downto 0) := (others => '0');
type memory_type is array (0 to ADDR_WIDTH-1) of std_logic_vector(DATA_WIDTH-1 downto 0);
signal memory : memory_type := (others => (others => '0'));
begin
full<= fifo_full;
empty <= fifo_empty;
process(clk, rstn)
begin
if rstn = '0' then
memory <= (others => (others => '0'));
rd_ptr <= (others => '0');
wr_ptr <= (others => '0');
fifo_full <= '0';
fifo_empty <= '1';
data_ready <= '0';
elsif rising_edge(clk) then
-- Write
if (wr_en = '1' and fifo_full = '0') then
memory(to_integer(wr_ptr)) <= data_in;
wr_ptr <= wr_ptr + 1;
byte_count <= byte_count + 1;
-- One packet is ready
if(byte_count = ts_packet_size) then
data_ready <= '1';
else
data_ready <= '0';
end if;
end if;
-- Read
if ( rd_en = '1' and fifo_empty = '1') then
data_out <= memory(to_integer(rd_ptr));
rd_ptr <= rd_ptr - 1;
end if;
-- Memory full
if (( wr_ptr + 1 = rd_ptr ) and (wr_en = '1') and (rd_en = '0')) then
fifo_full <= '1';
else
fifo_full <= '0';
end if;
-- Memory empty
if ((rd_ptr = wr_ptr) and (rd_en = '1') and (wr_en = '0')) then
fifo_empty <= '0';
else
fifo_empty <= '1';
end if;
end if;
end process;
end Behavioral;[/syntax]
if ( rd_en = '1' and [B]fifo_empty = '1'[/B]) then
data_out <= memory(to_integer(rd_ptr));
rd_ptr <= rd_ptr - 1;
end if;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity circular_buffer is
generic(
DATA_WIDTH : integer := 8;
ADDR_WIDTH : integer := 12 -- 2^12 = 4096 = 4k
);
Port (
-- Input clock domain
clk : in STD_LOGIC;
rstn : in STD_LOGIC;
wr_en : in STD_LOGIC;
wr_addr : in STD_LOGIC_VECTOR (ADDR_WIDTH-1 downto 0);
data_in : in STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
-- Output clock domain
-- s_clk : in STD_LOGIC;
rd_en : in STD_LOGIC;
rd_addr : in STD_LOGIC_VECTOR (ADDR_WIDTH-1 downto 0);
data_out : out STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
full : out STD_LOGIC;
empty : out STD_LOGIC;
data_ready : out STD_LOGIC
);
end circular_buffer;
architecture Behavioral of circular_buffer is
constant ts_packet_size : integer := 188;
signal byte_count : unsigned(ts_packet_size-1 downto 0) := (others => '0');
signal fifo_empty : std_logic := '1';
signal fifo_full : std_logic := '0';
signal rd_ptr : unsigned(ADDR_WIDTH-1 downto 0) := (others => '0');
signal wr_ptr : unsigned(ADDR_WIDTH-1 downto 0) := (others => '0');
type memory_type is array (0 to ADDR_WIDTH-1) of std_logic_vector(DATA_WIDTH-1 downto 0);
signal memory : memory_type := (others => (others => '0'));
begin
full <= fifo_full;
empty <= fifo_empty;
process(clk, rstn)
begin
if rstn = '0' then
memory <= (others => (others => '0'));
rd_ptr <= (others => '0');
wr_ptr <= (others => '0');
fifo_full <= '0';
fifo_empty <= '1';
data_ready <= '0';
elsif rising_edge(clk) then
-- Write
if (wr_en = '1' and fifo_full = '0') then
memory(to_integer(wr_ptr)) <= data_in;
wr_ptr <= wr_ptr + 1;
byte_count <= byte_count + 1;
-- One packet is ready
if(byte_count = ts_packet_size) then
data_ready <= '1';
else
data_ready <= '0';
end if;
end if;
-- Read ( If read enable is 1 and fifo is not empty)
if ( rd_en = '1' and fifo_empty = '0') then
data_out <= memory(to_integer(rd_ptr));
rd_ptr <= rd_ptr - 1;
end if;
-- Memory full
if (( wr_ptr + 1 = rd_ptr ) and (wr_en = '1') and (rd_en = '0')) then
fifo_full <= '1';
else
fifo_full <= '0';
end if;
-- Memory empty
if ((rd_ptr = wr_ptr) and (rd_en = '1') and (wr_en = '0')) then
fifo_empty <= '1';
else
fifo_empty <= '0';
end if;
end if;
end process;
end Behavioral;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity tb_circular_buffer is
end tb_circular_buffer;
architecture tb of tb_circular_buffer is
component circular_buffer
generic(
DATA_WIDTH : integer := 8;
ADDR_WIDTH : integer := 12
);
port (
clk : in std_logic;
rstn : in std_logic;
wr_en : in std_logic;
wr_addr : in std_logic_vector (ADDR_WIDTH-1 downto 0);
data_in : in std_logic_vector (DATA_WIDTH-1 downto 0);
rd_en : in std_logic;
rd_addr : in std_logic_vector (ADDR_WIDTH-1 downto 0);
data_out : out std_logic_vector (DATA_WIDTH-1 downto 0);
full : out std_logic;
empty : out std_logic;
data_ready : out std_logic
);
end component;
constant DWIDTH : integer := 8;
constant AWIDTH : integer := 12;
signal clk : std_logic;
signal rstn : std_logic;
signal wr_en : std_logic;
signal wr_addr : std_logic_vector (AWIDTH-1 downto 0);
signal data_in : std_logic_vector (DWIDTH-1 downto 0);
signal rd_en : std_logic;
signal rd_addr : std_logic_vector (AWIDTH-1 downto 0);
signal data_out : std_logic_vector (DWIDTH-1 downto 0);
signal full : std_logic;
signal empty : std_logic;
signal data_ready : std_logic;
constant clk_period : time := 10 ns;
begin
dut : circular_buffer
port map (clk => clk,
rstn => rstn,
wr_en => wr_en,
wr_addr => wr_addr,
data_in => data_in,
rd_en => rd_en,
rd_addr => rd_addr,
data_out => data_out,
full => full,
empty => empty,
data_ready => data_ready);
-- Clock generation
clk_process :process
begin
clk <= '1';
wait for clk_period/2;
clk <= '0';
wait for clk_period/2;
end process;
stimuli : process
begin
-- intial state
wr_en <= '0';
wr_addr <= (others => '0');
data_in <= (others => '0');
rd_en <= '0';
rd_addr <= (others => '0');
-- Reset generation
rstn <= '0';
wait for 20 ns;
rstn <= '1';
wait for 20 ns;
-- single write
wr_en <= '1';
data_in <= x"FF";
wr_addr <= x"001";
wait for 10 ns;
wr_en <= '0';
-- single read
rd_en <= '1';
rd_addr <= x"001";
wait for 10 ns;
rd_en <= '0';
wr_en <= '1';
-- write to all locations
for i in 1 to 4096 loop
data_in <= conv_std_logic_vector(i,8);
wr_addr <= conv_std_logic_vector(i-1,12);
wait for 10 ns;
end loop;
wr_en <= '0';
wait;
end process;
end tb;
Code VHDL - [expand] 1 2 3 4 5 6 -- Memory empty if ((rd_ptr = wr_ptr) and (rd_en = '1') and (wr_en = '0')) then fifo_empty <= '1'; else fifo_empty <= '0'; end if;
Code VHDL - [expand] 1 2 3 for i in 1 to 5 loop -- wait for 5 clocks wait until rising_edge(clk); end loop;
[syntax=vhdl]library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity circular_buffer is
generic(
DATA_WIDTH : integer := 8;
ADDR_WIDTH : integer := 12 -- 2^12 = 4096 = 4k
);
Port (
-- Input clock domain
clk : in STD_LOGIC;
rstn : in STD_LOGIC;
wr_en : in STD_LOGIC;
wr_addr : in STD_LOGIC_VECTOR (ADDR_WIDTH-1 downto 0);
data_in : in STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
-- Output clock domain
-- s_clk : in STD_LOGIC;
rd_en : in STD_LOGIC;
rd_addr : in STD_LOGIC_VECTOR (ADDR_WIDTH-1 downto 0);
data_out : out STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0);
full : out STD_LOGIC;
empty : out STD_LOGIC;
error : out STD_LOGIC;
data_ready : out STD_LOGIC
);
end circular_buffer;
architecture Behavioral of circular_buffer is
constant ts_packet_size : integer := 188;
signal byte_count : unsigned(ts_packet_size-1 downto 0) := (others => '0');
signal fifo_empty : std_logic := '1';
signal fifo_full : std_logic := '0';
signal ready : std_logic := '0';
signal rd_ptr : unsigned(ADDR_WIDTH-1 downto 0) := (others => '0');
signal wr_ptr : unsigned(ADDR_WIDTH-1 downto 0) := (others => '0');
type memory_type is array (0 to ADDR_WIDTH-1) of std_logic_vector(DATA_WIDTH-1 downto 0);
signal memory : memory_type := (others => (others => '0'));
begin
full <= fifo_full;
empty <= fifo_empty;
data_ready <= ready;
error <= '1' when (fifo_empty='1' and rd_en='1') or (fifo_full='1' and wr_en='1') else '0';
process(clk, rstn)
begin
if rstn = '0' then
memory <= (others => (others => '0'));
rd_ptr <= (others => '0');
wr_ptr <= (others => '0');
fifo_full <= '0';
fifo_empty <= '1';
ready <= '0';
elsif rising_edge(clk) then
-- Write
if (wr_en = '1' and fifo_full = '0') then
memory(to_integer(wr_ptr)) <= data_in;
wr_ptr <= wr_ptr + 1;
byte_count <= byte_count + 1;
-- One packet is ready
if (byte_count = ts_packet_size) then
ready <= '1';
else
ready <= '0';
end if;
end if;
-- Read
if ( rd_en = '1' and fifo_empty = '0' and ready = '1') then
data_out <= memory(to_integer(rd_ptr));
rd_ptr <= rd_ptr - 1;
end if;
-- Memory full
if (( wr_ptr + 1 = rd_ptr ) and (wr_en = '1') and (rd_en = '0')) then
fifo_full <= '1';
else
fifo_full <= '0';
end if;
-- Memory empty
if ((rd_ptr = wr_ptr) and (rd_en = '1') and (wr_en = '0')) then
fifo_empty <= '1';
elsif ((rd_ptr /= wr_ptr) and (rd_en = '1') and (wr_en = '0')) then -- if we read but write and read pointers do not point to the same location
fifo_empty <= '0';
elsif (( rd_en = '0') and (wr_en = '1') and (fifo_full = '0')) then -- if we don't read and we write and the fifo is not full
fifo_empty <= '0';
end if;
end if;
end process;
end Behavioral;[/syntax]
[syntax=vhdl]
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
entity tb_circular_buffer is
end tb_circular_buffer;
architecture tb of tb_circular_buffer is
component circular_buffer
generic(
DATA_WIDTH : integer := 8;
ADDR_WIDTH : integer := 12
);
port (
clk : in std_logic;
rstn : in std_logic;
wr_en : in std_logic;
wr_addr : in std_logic_vector (ADDR_WIDTH-1 downto 0);
data_in : in std_logic_vector (DATA_WIDTH-1 downto 0);
rd_en : in std_logic;
rd_addr : in std_logic_vector (ADDR_WIDTH-1 downto 0);
data_out : out std_logic_vector (DATA_WIDTH-1 downto 0);
full : out std_logic;
empty : out std_logic;
error : out std_logic;
data_ready : out std_logic
);
end component;
constant DWIDTH : integer := 8;
constant AWIDTH : integer := 12;
signal clk : std_logic;
signal rstn : std_logic;
signal wr_en : std_logic;
signal wr_addr : std_logic_vector (AWIDTH-1 downto 0);
signal data_in : std_logic_vector (DWIDTH-1 downto 0);
signal rd_en : std_logic;
signal rd_addr : std_logic_vector (AWIDTH-1 downto 0);
signal data_out : std_logic_vector (DWIDTH-1 downto 0);
signal full : std_logic;
signal empty : std_logic;
signal error : std_logic;
signal data_ready : std_logic;
constant clk_period : time := 8 ns; --125MHz
begin
dut : circular_buffer
port map (clk => clk,
rstn => rstn,
wr_en => wr_en,
wr_addr => wr_addr,
data_in => data_in,
rd_en => rd_en,
rd_addr => rd_addr,
data_out => data_out,
full => full,
empty => empty,
error => error,
data_ready => data_ready);
-- Clock generation
clk_process : process
begin
clk <= '1';
wait for clk_period/2;
clk <= '0';
wait for clk_period/2;
end process;
stimuli : process
begin
-- intial state
wr_en <= '0';
wr_addr <= (others => '0');
data_in <= (others => '0');
rd_en <= '0';
rd_addr <= (others => '0');
-- Reset generation
rstn <= '0';
wait for clk_period;
rstn <= '1';
wait for clk_period;
-- single write
wr_en <= '1';
wait until rising_edge(clk);
data_in <= x"FF";
wr_addr <= x"001";
wait until rising_edge(clk);
wr_en <= '0';
--rd_en <= '1';
--rd_addr <= x"001";
--wait until rising_edge(clk);
--rd_en <= '0';
-- write to all locations
for i in 1 to 4096 loop
wr_en <= '1';
data_in <= conv_std_logic_vector(i,8);
wr_addr <= conv_std_logic_vector(i-1,12);
wait until rising_edge(clk);
wr_en <= '0';
end loop;
wait;
end process;
end tb;[/syntax]
[syntax=vhdl] -- write to all locations
for i in 1 to 4096 loop
wr_en <= '1';
data_in <= conv_std_logic_vector(i,8);
wr_addr <= conv_std_logic_vector(i-1,12);
wait until rising_edge(clk);
wr_en <= '0';
end loop;
[/syntax]
Yes, the simulator stops with a message, it tells you which code error causes the stop. Learn to read the simulator output.my code stops here
Code VHDL - [expand] 1 type memory_type is array (0 to ADDR_WIDTH-1) of std_logic_vector(DATA_WIDTH-1 downto 0);
Code VHDL - [expand] 1 type memory_type is array (0 to 2**ADDR_WIDTH-1) of std_logic_vector(DATA_WIDTH-1 downto 0);
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity circular_buffer is generic( DATA_WIDTH : integer := 8; ADDR_WIDTH : integer := 12 -- 2^12 = 4096 = 4k ); Port ( -- Input clock domain clk : in STD_LOGIC; rstn : in STD_LOGIC; wr_en : in STD_LOGIC; wr_addr : in STD_LOGIC_VECTOR (ADDR_WIDTH-1 downto 0); data_in : in STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0); -- Output clock domain -- s_clk : in STD_LOGIC; rd_en : in STD_LOGIC; rd_addr : in STD_LOGIC_VECTOR (ADDR_WIDTH-1 downto 0); data_out : out STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0); full : out STD_LOGIC; empty : out STD_LOGIC; error : out STD_LOGIC; data_ready : out STD_LOGIC ); end circular_buffer; architecture Behavioral of circular_buffer is constant ts_packet_size : integer := 188; --signal byte_count : unsigned(DATA_WIDTH-1 downto 0) := (others => '0'); signal byte_count : integer range 1 to DATA_WIDTH := 1 ; signal packet_count : unsigned((8*ts_packet_size)-1 downto 0) := (others => '0'); signal fifo_full : std_logic := '0'; signal fifo_empty : std_logic := '0'; signal ready : std_logic := '0'; signal byte_flag: std_logic := '0'; signal rd_ptr : unsigned(ADDR_WIDTH-1 downto 0) := to_unsigned(0, ADDR_WIDTH); signal wr_ptr : unsigned(ADDR_WIDTH-1 downto 0) := to_unsigned(0, ADDR_WIDTH); type memory_type is array (0 to 2**ADDR_WIDTH-1) of std_logic_vector(DATA_WIDTH-1 downto 0); signal memory : memory_type := (others => (others => '0')); begin full <= fifo_full; empty <= fifo_empty; data_ready <= ready; error <= '1' when (fifo_empty='1' and rd_en='1') or (fifo_full='1' and wr_en='1') else '0'; process(clk, rstn) begin if rstn = '0' then memory <= (others => (others => '0')); rd_ptr <= to_unsigned(0, ADDR_WIDTH); wr_ptr <= to_unsigned(0, ADDR_WIDTH); byte_count <= 1; packet_count<= (others => '0'); fifo_full <= '0'; fifo_empty <= '1'; ready <= '0'; byte_flag <= '0'; elsif rising_edge(clk) then -- Write if (wr_en = '1' and fifo_full = '0') then memory(to_integer(wr_ptr)) <= data_in; wr_ptr <= wr_ptr + 1; -- One packet is ready or not if (packet_count = (8*ts_packet_size)) then ready <= '1'; packet_count <= (others => '0'); else ready <= '0'; packet_count <= packet_count + 1; end if; -- -- one byte counter -- if(byte_count < DATA_WIDTH) then -- byte_flag <= '0'; -- byte_count <= byte_count + 1; -- else -- byte_count <= 1; -- byte_flag <= '1'; -- end if; end if; -- Read -- We read after having one complete transport stream packet if ( rd_en = '1' and fifo_empty = '0' and ready = '1') then data_out <= memory(to_integer(rd_ptr)); rd_ptr <= rd_ptr - 1; end if; -- Memory full if (( wr_ptr + 1 = rd_ptr ) and (wr_en = '1') and (rd_en = '0')) then fifo_full <= '1'; else fifo_full <= '0'; end if; -- Memory empty if ((rd_ptr = wr_ptr) and (rd_en = '1') and (wr_en = '0')) then fifo_empty <= '1'; elsif ((rd_ptr /= wr_ptr) and (rd_en = '1') and (wr_en = '0')) then -- if we read but write and read pointers do not point to the same location fifo_empty <= '0'; elsif (( rd_en = '0') and (wr_en = '1') and (fifo_full = '0')) then -- if we don't read and we write and the fifo is not full fifo_empty <= '0'; end if; end if; end process; end Behavioral;
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; use IEEE.STD_LOGIC_ARITH.ALL; entity tb_circular_buffer is end tb_circular_buffer; architecture tb of tb_circular_buffer is component circular_buffer generic( DATA_WIDTH : integer := 8; ADDR_WIDTH : integer := 12 ); port ( clk : in std_logic; rstn : in std_logic; wr_en : in std_logic; wr_addr : in std_logic_vector (ADDR_WIDTH-1 downto 0); data_in : in std_logic_vector (DATA_WIDTH-1 downto 0); rd_en : in std_logic; rd_addr : in std_logic_vector (ADDR_WIDTH-1 downto 0); data_out : out std_logic_vector (DATA_WIDTH-1 downto 0); full : out std_logic; empty : out std_logic; error : out std_logic; data_ready : out std_logic ); end component; constant DWIDTH : integer := 8; constant AWIDTH : integer := 12; signal clk : std_logic; signal rstn : std_logic; signal wr_en : std_logic; signal wr_addr : std_logic_vector (AWIDTH-1 downto 0); signal data_in : std_logic_vector (DWIDTH-1 downto 0); signal rd_en : std_logic; signal rd_addr : std_logic_vector (AWIDTH-1 downto 0); signal data_out : std_logic_vector (DWIDTH-1 downto 0); signal full : std_logic; signal empty : std_logic; signal error : std_logic; signal data_ready : std_logic; constant clk_period : time := 8 ns; --125MHz begin dut : circular_buffer port map (clk => clk, rstn => rstn, wr_en => wr_en, wr_addr => wr_addr, data_in => data_in, rd_en => rd_en, rd_addr => rd_addr, data_out => data_out, full => full, empty => empty, error => error, data_ready => data_ready); -- Clock generation clk_process : process begin clk <= '1'; wait for clk_period/2; clk <= '0'; wait for clk_period/2; end process; stimuli : process begin -- intial state wr_en <= '0'; wr_addr <= (others => '0'); data_in <= (others => '0'); rd_en <= '0'; rd_addr <= (others => '0'); -- Reset generation rstn <= '0'; wait for clk_period; rstn <= '1'; wait for clk_period; -- single write wait for clk_period; wr_en <= '1'; wait until rising_edge(clk); data_in <= x"FF"; wr_addr <= x"001"; wait until rising_edge(clk); wr_en <= '0'; -- write to all locations for i in 1 to 4096 loop wr_en <= '1'; data_in <= conv_std_logic_vector(i,8); wr_addr <= conv_std_logic_vector(i-1,12); wait until rising_edge(clk); wr_en <= '0'; end loop; -- read for i in 1 to 188 loop rd_en <= '1'; rd_addr <= conv_std_logic_vector(i-1,12); wait until rising_edge(clk); rd_en <= '0'; end loop; wait; end process; end tb;
signal packet_count : unsigned(10 downto 0) := (others => '0');
1. I have a packet counter so it counts the data that is written to the circular buffer and when it reaches 188 bytes then the ready_data flag should go high. When I check the waveform , when counter reaches 1504 (=188*8) there is a clock cycle that counter has no value which i do not understand why ? So I believe because of that cycle on the next cycle of reading ( if read operation works !) I already missed one data which is E0 that is written to this address "5DF" (Please see the waveform in the attachment)
Looks like it got written to me...I already missed one data which is E0 that is written to this address "5DF"
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity circular_buffer is generic( DATA_WIDTH : integer := 8; ADDR_WIDTH : integer := 12 -- 2^12 = 4096 = 4k ); Port ( -- Input clock domain clk : in STD_LOGIC; rstn : in STD_LOGIC; wr_en : in STD_LOGIC; wr_addr : in STD_LOGIC_VECTOR (ADDR_WIDTH-1 downto 0); data_in : in STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0); -- Output clock domain s_clk : in STD_LOGIC; rd_en : in STD_LOGIC; rd_addr : in STD_LOGIC_VECTOR (ADDR_WIDTH-1 downto 0); data_out : out STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0); full : out STD_LOGIC; empty : out STD_LOGIC; error : out STD_LOGIC; data_ready : out STD_LOGIC ); end circular_buffer; architecture Behavioral of circular_buffer is constant ts_packet_size : integer := 188; signal byte_count : integer range 1 to DATA_WIDTH := 1; signal packet_count : unsigned(10 downto 0) := (others => '0'); -- 2^11 = 2048 enough for 1504 signal fifo_full : std_logic := '0'; signal fifo_empty : std_logic := '0'; signal ready : std_logic := '0'; signal byte_flag : std_logic := '0'; signal rd_ptr : unsigned(ADDR_WIDTH-1 downto 0) := to_unsigned(0, ADDR_WIDTH); signal wr_ptr : unsigned(ADDR_WIDTH-1 downto 0) := to_unsigned(0, ADDR_WIDTH); signal test_read : std_logic := '0'; type memory_type is array (0 to 2**ADDR_WIDTH-1) of std_logic_vector(DATA_WIDTH-1 downto 0); signal memory : memory_type := (others => (others => '0')); begin full <= fifo_full; empty <= fifo_empty; data_ready <= ready; error <= '1' when (fifo_empty='1' and rd_en='1') or (fifo_full='1' and wr_en='1') else '0'; process(clk, s_clk, rstn, wr_en) begin if rstn = '0' then memory <= (others => (others => '0')); rd_ptr <= to_unsigned(0, ADDR_WIDTH); wr_ptr <= to_unsigned(0, ADDR_WIDTH); byte_count <= 1; packet_count<= (others => '0'); fifo_full <= '0'; fifo_empty <= '1'; ready <= '0'; byte_flag <= '0'; data_out <= (others => '0'); test_read <= '0'; elsif rising_edge(clk) then -- Write if (wr_en = '1' and fifo_full = '0') then memory(to_integer(wr_ptr)) <= data_in; wr_ptr <= wr_ptr + 1; -- One packet is ready or not if (packet_count = (8*ts_packet_size)) then ready <= '1'; packet_count <= (others => '0'); else ready <= '0'; packet_count <= packet_count + 1; end if; end if; -- Memory full if (( wr_ptr + 1 = rd_ptr ) and (wr_en = '1') and (rd_en = '0')) then fifo_full <= '1'; else fifo_full <= '0'; end if; -- Memory empty if ((rd_ptr = wr_ptr) and (rd_en = '1') and (wr_en = '0')) then fifo_empty <= '1'; elsif ((rd_ptr /= wr_ptr) and (rd_en = '1')) then -- if we read but write and read pointers do not point to the same location fifo_empty <= '0'; elsif ((rd_en = '0') and (wr_en = '1') and (fifo_full = '0')) then fifo_empty <= '0'; elsif rising_edge(wr_en) then fifo_empty <= '0'; end if; end if; end process; read_process : process(s_clk) begin if(rising_edge(s_clk)) then if(rstn = '1') then -- Read -- We read after having one complete transport stream packet if ( rd_en = '1' and fifo_empty = '0' and ready = '1') then report" ready to read" severity note; data_out <= memory(to_integer(rd_ptr)); rd_ptr <= rd_ptr - 1; end if; end if; end if; end process; end Behavioral;
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity circular_buffer is generic( DATA_WIDTH : integer := 8; ADDR_WIDTH : integer := 12 -- 2^12 = 4096 = 4k ); Port ( -- Input clock domain clk : in STD_LOGIC; rstn : in STD_LOGIC; wr_en : in STD_LOGIC; wr_addr : in STD_LOGIC_VECTOR (ADDR_WIDTH-1 downto 0); data_in : in STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0); -- Output clock domain s_clk : in STD_LOGIC; rd_en : in STD_LOGIC; rd_addr : in STD_LOGIC_VECTOR (ADDR_WIDTH-1 downto 0); data_out : out STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0); full : out STD_LOGIC; empty : out STD_LOGIC; error : out STD_LOGIC; data_ready : out STD_LOGIC ); end circular_buffer; architecture Behavioral of circular_buffer is constant ts_packet_size : integer := 188; signal byte_count : integer range 1 to DATA_WIDTH := 1; signal packet_count : unsigned(10 downto 0) := (others => '0'); -- 2^11 = 2048 enough for 1504 signal fifo_full : std_logic := '0'; signal fifo_empty : std_logic := '0'; signal ready : std_logic := '0'; signal byte_flag : std_logic := '0'; signal rd_ptr : unsigned(ADDR_WIDTH-1 downto 0) := to_unsigned(0, ADDR_WIDTH); signal wr_ptr : unsigned(ADDR_WIDTH-1 downto 0) := to_unsigned(0, ADDR_WIDTH); signal test_read : std_logic := '0'; type memory_type is array (0 to 2**ADDR_WIDTH-1) of std_logic_vector(DATA_WIDTH-1 downto 0); signal memory : memory_type := (others => (others => '0')); begin full <= fifo_full; empty <= fifo_empty; data_ready <= ready; wr_ptr <= unsigned(wr_addr); rd_ptr <= unsigned(rd_addr); error <= '1' when (fifo_empty='1' and rd_en='1') or (fifo_full='1' and wr_en='1') else '0'; process(clk, s_clk, rstn, wr_en, wr_addr, data_in) begin if rstn = '0' then memory <= (others => (others => '0')); rd_ptr <= to_unsigned(0, ADDR_WIDTH); wr_ptr <= to_unsigned(0, ADDR_WIDTH); byte_count <= 1; packet_count<= (others => '0'); fifo_full <= '0'; fifo_empty <= '1'; ready <= '0'; byte_flag <= '0'; data_out <= (others => '0'); test_read <= '0'; elsif rising_edge(clk) then -- Write if (wr_en = '1' and fifo_full = '0') then memory(to_integer(wr_ptr)) <= data_in; wr_ptr <= wr_ptr + 1; -- One packet is ready or not if (packet_count = (8*ts_packet_size)) then ready <= '1'; packet_count <= (others => '0'); else ready <= '0'; packet_count <= packet_count + 1; end if; end if; end if; end process; read_process : process(s_clk, rd_addr, wr_en, rd_en, memory) begin if(rising_edge(s_clk)) then if(rstn = '1') then if ( rd_en = '1') then data_out <= memory(to_integer(rd_ptr)); rd_ptr <= rd_ptr - 1; end if; end if; end if; end process; end Behavioral;
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; use IEEE.STD_LOGIC_ARITH.ALL; entity tb_circular_buffer is end tb_circular_buffer; architecture tb of tb_circular_buffer is component circular_buffer generic( DATA_WIDTH : integer := 8; ADDR_WIDTH : integer := 12 ); port ( clk : in std_logic; rstn : in std_logic; wr_en : in std_logic; wr_addr : in std_logic_vector (ADDR_WIDTH-1 downto 0); data_in : in std_logic_vector (DATA_WIDTH-1 downto 0); s_clk : in std_logic; rd_en : in std_logic; rd_addr : in std_logic_vector (ADDR_WIDTH-1 downto 0); data_out : out std_logic_vector (DATA_WIDTH-1 downto 0); full : out std_logic; empty : out std_logic; error : out std_logic; data_ready : out std_logic ); end component; constant DWIDTH : integer := 8; constant AWIDTH : integer := 12; signal clk : std_logic; signal rd_clk : std_logic; signal rstn : std_logic; signal wr_en : std_logic; signal wr_addr : std_logic_vector (AWIDTH-1 downto 0); signal data_in : std_logic_vector (DWIDTH-1 downto 0); signal rd_en : std_logic; signal rd_addr : std_logic_vector (AWIDTH-1 downto 0); signal data_out : std_logic_vector (DWIDTH-1 downto 0); signal full : std_logic; signal empty : std_logic; signal error : std_logic; signal data_ready : std_logic; constant clk_period : time := 8 ns; --125MHz -- Signal used to end simulator when we finished submitting our test cases signal sim_done : boolean := false; begin -- DUT instantiation dut : circular_buffer port map (clk => clk, rstn => rstn, wr_en => wr_en, wr_addr => wr_addr, data_in => data_in, s_clk => rd_clk, rd_en => rd_en, rd_addr => rd_addr, data_out => data_out, full => full, empty => empty, error => error, data_ready => data_ready); -- Clock generation write_clk_process : process begin if not sim_done then clk <= '1'; wait for clk_period/2; clk <= '0'; wait for clk_period/2; else wait; end if; end process; read_clk_process : process begin if not sim_done then rd_clk <= '1'; wait for clk_period/2; rd_clk <= '0'; wait for clk_period/2; else wait; end if; end process; stimuli : process -- Reset generation procedure async_rst is begin wait until rising_edge(clk); wait for clk_period; rstn <= '0'; wait for clk_period; rstn <= '1'; end procedure async_rst; begin -- intial state(default values) wr_en <= '0'; wr_addr <= (others => '0'); data_in <= (others => '0'); rd_en <= '0'; rstn <= '0'; rd_addr <= (others => '0'); wait for clk_period; async_rst; -- single write wait for 2*clk_period; wr_en <= '1'; wait until rising_edge(clk); data_in <= x"AB"; wr_addr <= x"00A"; wait until rising_edge(clk); data_in <= x"FA"; wr_addr <= x"00B"; wait until rising_edge(clk); wr_en <= '0'; -- single read (to check empty condition) rd_en <= '1'; wait until rising_edge(clk); rd_addr <= x"00A"; wait until rising_edge(clk); rd_addr <= x"00B"; wait until rising_edge(clk); rd_en <= '0'; sim_done <= true; wait; end process; end tb;
[COLOR="#FF0000"][B]wr_ptr <= unsigned(wr_addr);
rd_ptr <= unsigned(rd_addr);[/B][/COLOR]
error <= '1' when (fifo_empty='1' and rd_en='1') or (fifo_full='1' and wr_en='1') else '0';
process(clk, s_clk, rstn, wr_en, wr_addr, data_in)
begin
if rstn = '0' then
memory <= (others => (others => '0'));
[COLOR="#FF0000"][B] rd_ptr <= to_unsigned(0, ADDR_WIDTH);
wr_ptr <= to_unsigned(0, ADDR_WIDTH)[/B][/COLOR];
Do not directly contact users using primate messages to get answers.design_newbie said:Hello,
I am not sure what are you talking about in the thread, I have an issue with the pointer. I don't know how to implement the following :HTML:https://www.edaboard.com/showthread.php?384013-Circular-buffer-design
There is a memory with a range of addresses , then you have pointers which point to those addresses , I don't know how to relate the address and pointer in VHDL. Or if there is other ways to read from an address in memory.
What I had before in my design for write and read was as following :
Code:begin if rstn = '0' then memory <= (others => (others => '0')); rd_ptr <= to_unsigned(0, ADDR_WIDTH); wr_ptr <= to_unsigned(0, ADDR_WIDTH); byte_count <= 1; packet_count<= (others => '0'); fifo_full <= '0'; fifo_empty <= '1'; ready <= '0'; byte_flag <= '0'; data_out <= (others => '0'); test_read <= '0'; elsif rising_edge(clk) then -- Write if (wr_en = '1' and fifo_full = '0') then memory(to_integer(wr_ptr)) <= data_in; wr_ptr <= unsigned(wr_addr); wr_ptr <= wr_ptr + 1; -- One packet is ready or not if (packet_count = (8*ts_packet_size)) then ready <= '1'; packet_count <= (others => '0'); else ready <= '0'; packet_count <= packet_count + 1; end if; end if; end if; end process; read_process : process(s_clk, rd_addr, wr_en, rd_en, memory) begin if(rising_edge(s_clk)) then if(rstn = '1') then if ( rd_en = '1') then data_out <= memory(to_integer(rd_ptr)); rd_ptr <= rd_ptr - 1; end if; end if; end if; end process;
but because I got the feedback to go through the design backward to find the issue , i tried to remove everything and just do a write and read which messed up even more with my design and I am so confused now. How can I relate my pointer to the address ? what is the best way to debug this ?
Would you please suggest me a solution or a path to follow ?
Thank you in advance
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity circular_buffer is generic( DATA_WIDTH : integer := 8; ADDR_WIDTH : integer := 12 -- 2^12 = 4096 = 4k ); Port ( -- Input clock domain clk : in STD_LOGIC; rstn : in STD_LOGIC; wr_en : in STD_LOGIC; wr_addr : in STD_LOGIC_VECTOR (ADDR_WIDTH-1 downto 0); data_in : in STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0); -- Output clock domain s_clk : in STD_LOGIC; rd_en : in STD_LOGIC; rd_addr : in STD_LOGIC_VECTOR (ADDR_WIDTH-1 downto 0); data_out : out STD_LOGIC_VECTOR (DATA_WIDTH-1 downto 0); full : out STD_LOGIC; empty : out STD_LOGIC; error : out STD_LOGIC; data_ready : out STD_LOGIC ); end circular_buffer; architecture Behavioral of circular_buffer is constant ts_packet_size : integer := 188; signal byte_count : integer range 1 to DATA_WIDTH := 1; signal packet_count : unsigned(10 downto 0) := (others => '0'); -- 2^11 = 2048 enough for 1504 signal fifo_full : std_logic := '0'; signal fifo_empty : std_logic := '0'; signal ready : std_logic := '0'; signal byte_flag : std_logic := '0'; signal rd_ptr : unsigned(ADDR_WIDTH-1 downto 0) := to_unsigned(0, ADDR_WIDTH); signal wr_ptr : unsigned(ADDR_WIDTH-1 downto 0) := to_unsigned(0, ADDR_WIDTH); signal test_read : std_logic := '0'; type memory_type is array (0 to 2**ADDR_WIDTH-1) of std_logic_vector(DATA_WIDTH-1 downto 0); signal memory : memory_type := (others => (others => '0')); begin full <= fifo_full; empty <= fifo_empty; data_ready <= ready; error <= '1' when (fifo_empty='1' and rd_en='1') or (fifo_full='1' and wr_en='1') else '0'; process(clk, s_clk, rstn, wr_en, wr_addr, data_in, rd_en) begin if rstn = '0' then rd_ptr <= to_unsigned(0, ADDR_WIDTH); wr_ptr <= to_unsigned(0, ADDR_WIDTH); byte_count <= 1; packet_count<= (others => '0'); fifo_full <= '0'; fifo_empty <= '1'; ready <= '0'; byte_flag <= '0'; -- data_out <= (others => '0'); test_read <= '0'; elsif rising_edge(clk) then -- Write if (wr_en = '1' and fifo_full = '0') then memory(to_integer(unsigned(wr_addr))) <= data_in; wr_ptr <= wr_ptr + 1; -- One packet is ready or not if (packet_count = (8*ts_packet_size)) then ready <= '1'; packet_count <= (others => '0'); else ready <= '0'; packet_count <= packet_count + 1; end if; end if; end if; end process; read_process : process(s_clk, rd_addr, wr_en, rd_en, memory) begin if(rising_edge(s_clk)) then if(rstn = '1') then if ( rd_en = '1') then data_out <= memory(to_integer(unsigned(rd_addr))); rd_ptr <= rd_ptr - 1; end if; end if; end if; end process; end Behavioral;
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; use IEEE.STD_LOGIC_ARITH.ALL; entity tb_circular_buffer is end tb_circular_buffer; architecture tb of tb_circular_buffer is component circular_buffer generic( DATA_WIDTH : integer := 8; ADDR_WIDTH : integer := 12 ); port ( clk : in std_logic; rstn : in std_logic; wr_en : in std_logic; wr_addr : in std_logic_vector (ADDR_WIDTH-1 downto 0); data_in : in std_logic_vector (DATA_WIDTH-1 downto 0); s_clk : in std_logic; rd_en : in std_logic; rd_addr : in std_logic_vector (ADDR_WIDTH-1 downto 0); data_out : out std_logic_vector (DATA_WIDTH-1 downto 0); full : out std_logic; empty : out std_logic; error : out std_logic; data_ready : out std_logic ); end component; constant DWIDTH : integer := 8; constant AWIDTH : integer := 12; signal clk : std_logic; signal rd_clk : std_logic; signal rstn : std_logic; signal wr_en : std_logic; signal wr_addr : std_logic_vector (AWIDTH-1 downto 0); signal data_in : std_logic_vector (DWIDTH-1 downto 0); signal rd_en : std_logic; signal rd_addr : std_logic_vector (AWIDTH-1 downto 0); signal data_out : std_logic_vector (DWIDTH-1 downto 0); signal full : std_logic; signal empty : std_logic; signal error : std_logic; signal data_ready : std_logic; constant clk_period : time := 8 ns; --125MHz -- Signal used to end simulator when we finished submitting our test cases signal sim_done : boolean := false; begin -- DUT instantiation dut : circular_buffer port map (clk => clk, rstn => rstn, wr_en => wr_en, wr_addr => wr_addr, data_in => data_in, s_clk => rd_clk, rd_en => rd_en, rd_addr => rd_addr, data_out => data_out, full => full, empty => empty, error => error, data_ready => data_ready); -- Clock generation write_clk_process : process begin if not sim_done then clk <= '1'; wait for clk_period/2; clk <= '0'; wait for clk_period/2; else wait; end if; end process; read_clk_process : process begin if not sim_done then rd_clk <= '1'; wait for clk_period/2; rd_clk <= '0'; wait for clk_period/2; else wait; end if; end process; stimuli : process -- Reset generation procedure async_rst is begin wait until rising_edge(clk); wait for clk_period; rstn <= '0'; wait for clk_period; rstn <= '1'; end procedure async_rst; begin -- intial state(default values) wr_en <= '0'; wr_addr <= (others => '0'); data_in <= (others => '0'); rd_en <= '0'; rd_addr <= (others => '0'); rstn <= '0'; wait for clk_period; async_rst; -- single write wait for 2*clk_period; wr_en <= '1'; wait until rising_edge(clk); data_in <= x"AB"; wr_addr <= x"00A"; wait until rising_edge(clk); wr_en <= '0'; wait until rising_edge(clk); -- single read (to check empty condition) rd_en <= '1'; rd_addr <= x"00A"; assert data_out = x"AB" report "data out is not correct" severity warning; wait until rising_edge(clk); rd_en <= '0'; -- write to all locations for i in 1 to 4096 loop wr_en <= '1'; data_in <= conv_std_logic_vector(i,8); wr_addr <= conv_std_logic_vector(i-1,12); wait until rising_edge(clk); wr_en <= '0'; end loop; -- Instruct "clk_process" to halt execution. sim_done <= true; wait; end process; end tb;
Code VHDL - [expand] 1 2 3 data_out <= memory(to_integer(unsigned(rd_addr))); memory(to_integer(unsigned(wr_addr))) <= data_in;
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?