Ciągłe zadanie najwyraźniej nie działa
Pracuję nad filtrem FIR, szczególnie linią opóźnienia.x_delayed
jest inicjowany na wszystkie zera.
type slv32_array is array(natural range <>) of std_logic_vector(31 downto 0);
...
signal x_delayed : slv32_array(0 to NTAPS-1) := (others => (others => '0'));
To nie działa:
x_delayed(0) <= x; -- Continuous assignment
DELAYS : process(samp_clk)
begin
if rising_edge(samp_clk) then
for i in 1 to NTAPS-1 loop
x_delayed(i) <= x_delayed(i-1);
end loop;
end if; -- rising_edge(samp_clk)
end process;
Ale to robi:
DELAYS : process(samp_clk)
begin
if rising_edge(samp_clk) then
x_delayed(0) <= x; -- Registering input
for i in 1 to NTAPS-1 loop
x_delayed(i) <= x_delayed(i-1);
end loop;
end if; -- rising_edge(samp_clk)
end process;
Problem z tym „rozwiązaniem” polega na tym, że pierwszy element tox_delayed
jest opóźniony o jedną próbkę, którą powiniennie być. (Reszta kodu oczekujex_delayed(0)
byćobecny próba).
Używam Xilinx ISE 13.2, symulując z ISim, ale potwierdzono to również symulując za pomocą ModelSim.
Co daje?
Edytować:
Problem polegał zasadniczo na tym, chociażx_delayed(0)
nie wyglądało na to, że był w środkuprocess
, to było.
Po wdrożeniuPomysł Briana Drummonda działa doskonale:
x_delayed(0) <= x;
-- Synchronous delay cycles.
DELAYS : process(samp_clk)
begin
-- Disable the clocked driver, allowing the continuous driver above to function correctly.
-- https://stackoverflow.com/questions/18247955/#comment26779546_18248941
x_delayed(0) <= (others => 'Z');
if rising_edge(samp_clk) then
for i in 1 to NTAPS-1 loop
x_delayed(i) <= x_delayed(i-1);
end loop;
end if; -- rising_edge(samp_clk)
end process;
Edytuj 2:
wziąłemSugestia OllieB za pozbycie sięfor
pętla. Musiałem to zmienić, ponieważ mójx_delayed
jest indeksowany z(0 to NTAPS-1)
, ale kończymy na tym ładnie wyglądającym małym procesie:
x_delayed(0) <= x;
DELAYS : process(samp_clk)
begin
x_delayed(0) <= (others => 'Z');
if rising_edge(samp_clk) then
x_delayed(1 to x_delayed'high) <= x_delayed(0 to x_delayed'high-1);
end if; -- rising_edge(samp_clk)
end process;
Edytuj 3:
NastępującyNastępna sugestia OllieB, okazuje sięx_delayed(0) <= (others => 'Z')
było niepotrzebne po jego poprzedniej zmianie. Poniższe działa dobrze:
x_delayed(0) <= x;
DELAYS : process(samp_clk)
begin
if rising_edge(samp_clk) then
x_delayed(1 to x_delayed'high) <= x_delayed(0 to x_delayed'high-1);
end if;
end process;