Continuous assignment seemingly not working
vhdl
Solution
In the first case, the `x_delayed(0)` actually has two drivers, out outside the process, being `x_delayed(0) <= x`, and an implicit one inside the DELAY process.
The driver inside the process is a consequence of a VHDL standard concept called "longest static prefix", described in VHDL-2002 standard (IEEE Std 1076-2002) section "6.1 Names", and the loop construction with a loop variable `i`, whereby the longest static prefix for `x_delayed(i)` is `x_delayed`.
The VHDL standard then further describes drives for processes in section "12.6.1 Drivers", which says "... There is a single driver for a given scalar signal S in a process statement, provided that there is at least one signal assignment statement in that process statement and that the longest static prefix of the target signal of that signal assignment statement denotes S ...".
So as a (probably surprising) consequence the `x_delayed(0)` has a driver in the DELAY process, which drives all std_logic elements to 'U' since unassigned, whereby the std_logic resolution function causes the resulting value to be 'U', no matter what value is driven by the external `x_delayed(0) <= x`.
But in the case of your code, there seems to be more to it, since there actually are some "0" values in the simulation output for `x_delayed(0)`, for what I can see from the figures. However, it is hard to dig further into this when I do not have the entire code.
One way to see that the loop is the reason, is to manually roll out the loop by replacing the `for ... loop` with:
x_delayed(1) <= x_delayed(1-1);
x_delayed(2) <= x_delayed(2-1);
...
x_delayed(NTAPS) <= x_delayed(NTAPS-1);
This is of course not a usable solution for configurable modules with NTAPS as a generic, but it may be interesting to see that the operation then is as intuitively expected.
EDIT: Multiple solutions are listed in "edit" sections after the question above, based on comments. A solution with variable, which allows for complex expressions if required, is shown below. If complex expression is not required, then as per OllieB's suggestion it is possible to reduce the assign to `x_delayed(1 to x_delayed_dir'high) <= x_delayed(0 to x_delayed_dir'high-1)`:
x_delayed(0) <= x;
DELAYS : process(samp_clk)
variable x_delayed_v : slv32_array(1 to NTAPS-1);
begin
if rising_edge(samp_clk) then
for i in 1 to NTAPS-1 loop
x_delayed_v(i) := x_delayed(i-1); -- More complex operations are also possible
end loop;
x_delayed(1 to x_delayed_dir'high) <= x_delayed_v;
end if; -- rising_edge(samp_clk)
end process;
Problem
I'm working on a FIR filter, specifically the delay line. `x_delayed` is initialized to all zeros. ``` 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')); ``` This does not work: ``` 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; ``` But this does: ``` 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; ``` The problem with this "solution" is that the first element in `x_delayed` is delayed by one sample, which it should not be. (The rest of the code expects `x_delayed(0)` to be the current sample). I'm using Xilinx ISE 13.2, simulating with ISim, but this was also confirmed simulating with ModelSim. What gives? Edit: The problem was essentially that, even though `x_delayed(0)` didn't appear to be driven inside the `process`, it was. After implementing Brian Drummond's idea it works perfectly: ``` 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; ``` Edit 2: I took OllieB's suggestion for getting rid of the `for` loop. I had to change it, since my `x_delayed` is indexed from `(0 to NTAPS-1)`, but we end up with this nice looking little process: ``` 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; ``` Edit 3: Following OllieB's next suggestion, it turns out the `x_delayed(0) <= (others => 'Z')` was unnecessary, following his previous change. The following works just fine: ``` 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; ```