Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"ERROR: wire not found for $posedge" when synthesizing dynamic array insertion #130

Open
Xiretza opened this issue Aug 22, 2020 · 12 comments

Comments

@Xiretza
Copy link
Contributor

Xiretza commented Aug 22, 2020

The following file:

library ieee;
use ieee.std_logic_1164.all,
    ieee.numeric_std.all;

entity ent is
	port (
		clk : in std_logic;
		y : out std_logic_vector(2 downto 0)
	);
end entity;

architecture a of ent is
	type arr_t is array(3 downto 0) of std_logic_vector(2 downto 0);
	signal arr : arr_t;

	signal x : natural;
begin
	x <= 0;

	process(clk)
	begin
		if rising_edge(clk) then
			arr(x) <= (others => '0');
		end if;
	end process;

	y <= arr(0);
end architecture;

When run through yosys, produces the following error:

$ yosys -m ghdl -p 'ghdl ent.vhd -e'
[snip]
 Yosys 0.9+3477 (git sha1 3cb3978ff, gcc 10.1.0 -march=x86-64 -mtune=generic -O2 -fno-plt -fvar-tracking-assignments -fdebug-prefix-map=/build/yosys-git/src=/usr/src/debug -fPIC -Os)


-- Running command `ghdl ent.vhd -e' --

1. Executing GHDL.
note: top entity is "ent"
Importing module ent.
ERROR: wire not found for $posedge

Looking at the output of ghdl --synth, it's suspicious that not a single process is generated, instead everything is represented with latch semantics (sig <= sig when not set else next):

$ ghdl --synth ent.vhd -e
library ieee;
use ieee.std_logic_1164.all , ieee.numeric_std.all;
entity ent is
  port (
    clk: in std_logic;
    y: out std_logic_vector (2 downto 0)
  );
end entity;

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

architecture rtl of ent is
  signal wrap_clk: std_logic;
  signal wrap_y: std_logic_vector (2 downto 0);
  signal arr : std_logic_vector (11 downto 0);
  signal x : std_logic_vector (30 downto 0);
  signal n4_o : std_logic;
  signal n5_o : std_logic_vector (1 downto 0);
  signal n12_o : std_logic_vector (2 downto 0);
  signal n13_o : std_logic;
  signal n14_o : std_logic;
  signal n15_o : std_logic;
  signal n16_o : std_logic;
  signal n17_o : std_logic;
  signal n18_o : std_logic;
  signal n19_o : std_logic;
  signal n20_o : std_logic;
  signal n21_o : std_logic_vector (2 downto 0);
  signal n22_o : std_logic;
  signal n23_o : std_logic_vector (2 downto 0);
  signal n24_o : std_logic_vector (2 downto 0);
  signal n25_o : std_logic;
  signal n26_o : std_logic_vector (2 downto 0);
  signal n27_o : std_logic_vector (2 downto 0);
  signal n28_o : std_logic;
  signal n29_o : std_logic_vector (2 downto 0);
  signal n30_o : std_logic_vector (2 downto 0);
  signal n31_o : std_logic;
  signal n32_o : std_logic_vector (2 downto 0);
  signal n33_o : std_logic_vector (11 downto 0);
begin
  wrap_clk <= clk;
  y <= wrap_y;
  wrap_y <= n12_o;
  -- ent.vhd:14:15
  arr <= n33_o; -- (signal)
  -- ent.vhd:16:15
  x <= "0000000000000000000000000000000"; -- (signal)
  -- ent.vhd:22:19
  n4_o <= '1' when rising_edge (wrap_clk) else '0';
  -- ent.vhd:23:27
  n5_o <= x (1 downto 0);  --  trunc
  -- ent.vhd:27:16
  n12_o <= arr (2 downto 0);
  -- ent.vhd:23:24
  n13_o <= n5_o (1);
  -- ent.vhd:23:24
  n14_o <= not n13_o;
  -- ent.vhd:23:24
  n15_o <= n5_o (0);
  -- ent.vhd:23:24
  n16_o <= not n15_o;
  -- ent.vhd:23:24
  n17_o <= n14_o and n16_o;
  -- ent.vhd:23:24
  n18_o <= n14_o and n15_o;
  -- ent.vhd:23:24
  n19_o <= n13_o and n16_o;
  -- ent.vhd:23:24
  n20_o <= n13_o and n15_o;
  n21_o <= arr (2 downto 0);
  -- ent.vhd:23:24
  n22_o <= n17_o and n4_o;
  -- ent.vhd:23:24
  n23_o <= n21_o when n22_o = '0' else "000";
  n24_o <= arr (5 downto 3);
  -- ent.vhd:23:24
  n25_o <= n18_o and n4_o;
  -- ent.vhd:23:24
  n26_o <= n24_o when n25_o = '0' else "000";
  n27_o <= arr (8 downto 6);
  -- ent.vhd:23:24
  n28_o <= n19_o and n4_o;
  -- ent.vhd:23:24
  n29_o <= n27_o when n28_o = '0' else "000";
  n30_o <= arr (11 downto 9);
  -- ent.vhd:23:24
  n31_o <= n20_o and n4_o;
  -- ent.vhd:23:24
  n32_o <= n30_o when n31_o = '0' else "000";
  n33_o <= n32_o & n29_o & n26_o & n23_o;
end rtl;

Not entirely sure if the plugin should support this kind of construct, or if GHDL shouldn't be generating it in the first place.

@tgingold
Copy link
Member

tgingold commented Sep 5, 2020

I understand the reason of the bug, but I am not sure how to fix it.
The result can either be a RAM (with a read port that has a fixed address) or an expanded register sets.

I plan to fix it by generating an expanded register set. But your testcase is a little bit too artificial.

@eine
Copy link
Contributor

eine commented Sep 5, 2020

Might it be worth supporting some specific attribute, as some vendors do? Typically, options are "all RAM", "all registers", "choose automatically" or "set through attribute". The latter allows to override the general setting for some specific signal/constant.

@efykse
Copy link

efykse commented Sep 28, 2020

I'm facing a similar issue when trying to use assertions on RAM content (for formal verification):

library ieee;
use ieee.std_logic_1164.all;

entity ram_assertion is
   port (
      clk  : in std_logic;
      data : in std_logic_vector(7 downto 0);
      addr : in integer range 0 to 15);
end entity;

architecture rtl of ram_assertion is
   type t_ram is array (natural range <>) of std_logic_vector(7 downto 0);
   signal ram : t_ram(15 downto 0);
begin

   process(clk)
   begin
      if rising_edge(clk) then
         ram(addr) <= data;
      end if;
   end process;

   default clock is rising_edge(clk);

   assert always ram(0) = x"00";

end architecture;

This leads to

# yosys -m ghdl

 Yosys 0.9+3582 (git sha1 8fbb5171, clang 7.0.1-8 -fPIC -Os)

yosys> ghdl --std=08 -i ram_assertion.vhd -e ram_assertion
1. Executing GHDL.
Importing module ram_assertion.
ERROR: wire not found for $posedge
ERROR: Assert `GetSize(ports) >= it.second->port_id' failed in kernel/rtlil.cc:1613.

An option to implement the RAM as registers would be a nice workaround.

@tmeissner
Copy link
Contributor

tmeissner commented Sep 28, 2020

@efykse Sure that the ram array isn't optimized away? I don't know exactly if an assertion count as something similar like an output, but without the assert the ram would be a write-only memory, which is optimized away in synthesis tools I know.

As an example, a design of mine with an array as register file can be successfully compiled & proven: formal_hw_verification: vai_reg. One of the differences is that there is logic which depends on the content of the register file.

@efykse
Copy link

efykse commented Sep 28, 2020

Yes, good point @tmeissner. But the error is still the same if I add an output that depends on the ram contents (please see code below).

In your example, I see that you have a reset on the contents of s_register. If I add a reset of the RAM contents (commented-out below), I get no errors. The reset probably prevents the synthesis of a dedicated RAM, preventing the error from occuring.

library ieee;
use ieee.std_logic_1164.all;

entity ram_assertion is
   port (
      clk      : in  std_logic;
      sreset   : in  std_logic;
      data_in  : in  std_logic_vector(7 downto 0);
      addr     : in  integer range 0 to 15;
      data_out : out std_logic_vector(7 downto 0));
end entity;

architecture rtl of ram_assertion is
   type t_ram is array (natural range <>) of std_logic_vector(7 downto 0);
   signal ram : t_ram(15 downto 0);
begin

   process(clk)
   begin
      if rising_edge(clk) then
         ram(addr) <= data_in;
         data_out  <= ram(addr);
--       if sreset then
--          ram <= (others => (others => '0'));
--       end if;
      end if;
   end process;

   default clock is rising_edge(clk);

   assert always ram(0) = x"00";

end architecture;

@tmeissner
Copy link
Contributor

tmeissner commented Sep 28, 2020

@efykse Yes, that could be the case with the reset. For formal, you don't want a dedicated BRAM, as you can't really verify it's content anymore.

However, even when I remove the reset in my vai_reg design, the compilation & verifiying works. So, it also depends on other things like write or read logic implementation.

@efykse
Copy link

efykse commented Sep 28, 2020

Yes, I agree. Ideally any assertions on the RAM content should prevent its inference as a RAM, the same way that the reset does.

@efykse
Copy link

efykse commented Sep 29, 2020

I found a workaround by invoking GHDL with the "-dm" option to prevent inference of memories.

@Xiretza
Copy link
Contributor Author

Xiretza commented Jan 6, 2021

This is still an issue with 8b3e740 - here's a less artificial test case, since that was a concern:

library ieee;
use ieee.std_logic_1164.all,
    ieee.numeric_std.all;

entity ent is
	port (
		clk : in std_logic;

		set : in std_logic;
		index : in std_logic_vector(1 downto 0);
		val : in std_logic_vector(7 downto 0);

		out0 : out std_logic_vector(7 downto 0);
		out1 : out std_logic_vector(7 downto 0);
		out2 : out std_logic_vector(7 downto 0);
		out3 : out std_logic_vector(7 downto 0)
	);
end entity;

architecture a of ent is
	type arr_t is array(3 downto 0) of std_logic_vector(7 downto 0);
	signal arr : arr_t;
begin
	process(clk)
	begin
		if rising_edge(clk) then
			if set = '1' then
				arr(to_integer(unsigned(index))) <= val;
			end if;
		end if;
	end process;

	out0 <= arr(0);
	out1 <= arr(1);
	out2 <= arr(2);
	out3 <= arr(3);
end architecture;

Without -dm (which just isn't an option for larger designs):

$ yosys -m ghdl -p 'ghdl ent.vhd -e'
[...]
 Yosys 0.9+3830 (git sha1 b00e55a16, gcc 10.2.0 -march=x86-64 -mtune=generic -O2 -fno-plt -fvar-tracking-assignments -fdebug-prefix-map=/build/yosys-git/src=/usr/src/debug -fPIC -Os)
[...]
1. Executing GHDL.
note: top entity is "ent"
Importing module ent.
ERROR: wire not found for $posedge

@rjordans
Copy link

rjordans commented Feb 2, 2021

I ran into this problem today as well, or at least it seems so, I haven't been able to pinpoint the problem in our code yet but the 'wire not found on $posedge' error appears and adding -dm seems to get the design loaded properly. The problem is though that it explodes then without the RAM inference...

This is running with today's build of https://github.com/YosysHQ/fpga-toolchain

@ibkvictor
Copy link

I am still having this issue. The -dm option does not let yosys synthesis my vhdl design. could you please assist?

@tgingold
Copy link
Member

tgingold commented Nov 1, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants