0
\$\begingroup\$

I have a very frustrating problem and would really appreciate some help.

I am trying to test a RAM block using the switches and LED's on board the Nexys A7-100T FPGA development board. My code is synthesising fine but fails on implementation due to the errors shown in the image below.

I have also shown my constraint file and top level code file.

I am new to FPGA boards and I am unsure what I am doing wrong. I have tested this code on testbench and it works perfect. Would like to map it onto the FPGA to learn how.

EDIT

I have the clocks commented out in the constraints file as they caused even more errors.

Thanks!

enter image description here

Constraints file



#create_clock -period 10.000 -name clk -waveform {0.000 5.000} [get_ports clk]
#set_property -dict { PACKAGE_PIN E3    IOSTANDARD LVCMOS33 } [get_ports { clk }];

set_property -dict { PACKAGE_PIN P17   IOSTANDARD LVCMOS33 } [get_ports { Set_Button }]; #IO_L12P_T1_MRCC_14 Sch=btnl
set_property -dict { PACKAGE_PIN M17   IOSTANDARD LVCMOS33 } [get_ports { Enable_Button }]; #IO_L10N_T1_D15_14 Sch=btnr

set_property -dict { PACKAGE_PIN J15   IOSTANDARD LVCMOS33 } [get_ports { RAM_Address[0] }]; #IO_L24N_T3_RS0_15 Sch=sw[0]
set_property -dict { PACKAGE_PIN L16   IOSTANDARD LVCMOS33 } [get_ports { RAM_Address[1] }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=sw[1]
set_property -dict { PACKAGE_PIN M13   IOSTANDARD LVCMOS33 } [get_ports { RAM_Address[2] }]; #IO_L6N_T0_D08_VREF_14 Sch=sw[2]
set_property -dict { PACKAGE_PIN R15   IOSTANDARD LVCMOS33 } [get_ports { RAM_Address[3] }]; #IO_L13N_T2_MRCC_14 Sch=sw[3]

set_property -dict { PACKAGE_PIN H17   IOSTANDARD LVCMOS33 } [get_ports { Data_out[0] }]; #IO_L18P_T2_A24_15 Sch=led[0]
set_property -dict { PACKAGE_PIN K15   IOSTANDARD LVCMOS33 } [get_ports { Data_out[1] }]; #IO_L24P_T3_RS1_15 Sch=led[1]
set_property -dict { PACKAGE_PIN J13   IOSTANDARD LVCMOS33 } [get_ports { Data_out[2] }]; #IO_L17N_T2_A25_15 Sch=led[2]
set_property -dict { PACKAGE_PIN N14   IOSTANDARD LVCMOS33 } [get_ports { Data_out[3] }]; #IO_L8P_T1_D11_14 Sch=led[3]

Top level file



library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use work.Architecture_size.ALL;

entity RAM_Block is
 Port ( RAM_Address : in std_logic_vector (Data_width-1 downto 0); 
        Data_in  : in std_logic_vector (Data_width-1 downto 0);
        Set_Button : in std_logic;
        Enable_Button : in std_logic;
        Data_out : out std_logic_vector (Data_width-1 downto 0));
end RAM_Block;

architecture Behavioral of RAM_Block is

component Enabler_Block is
 Port ( A : in std_logic_vector(Data_width-1 downto 0);
        Enable : in std_logic;
        Q : out std_logic_vector(Data_width-1 downto 0));
end component;

type memory is array (0 to 3) of std_logic_vector (Data_width-1 downto 0);
signal RAM : memory := ("0000" , "0000" , "0000" , "0000");
signal RAM_output : std_logic_vector (Data_width-1 downto 0);
signal RAM_Address_int : integer;


begin



Enabler_Block_instance : Enabler_Block port map (A => RAM_output , Enable => Enable_Button , Q => Data_out);

RAM_Address_int <= conv_integer(unsigned(RAM_Address)); 

   Process (Set_Button , Enable_Button)

    begin

     if(rising_edge(Set_Button) and Set_Button = '1') then
        RAM(RAM_Address_int) <= Data_in;

     end if;

     if(rising_edge(Enable_Button) and Enable_Button = '1') then
        RAM_output <= RAM(RAM_Address_int);

     end if;

    end Process;

end Behavioral;

\$\endgroup\$
4
  • 1
    \$\begingroup\$ There are two things here : One, you should be careful about the coding style. especially with clocks. You need to code in a specific way for the tool to identify it as FF or RAM. There are language templates on Vivado on how to code a RAM. Second, all clocks should be connected to a clock capable PIN for efficient routing. \$\endgroup\$
    – maximus
    Commented Dec 19, 2020 at 11:10
  • 1
    \$\begingroup\$ It's definitely that the clocks you used in the design is not connected to a clock capable pin of an FPGA. Enable_Button is considered as a clock and it is connected M17 which is not a CC pin \$\endgroup\$
    – maximus
    Commented Dec 19, 2020 at 11:22
  • 1
    \$\begingroup\$ Were you able to fix this ? \$\endgroup\$
    – Mitu Raj
    Commented Dec 23, 2020 at 12:04
  • \$\begingroup\$ @MituRaj Yeah, I have provided an answer to explain how the problem was solved, thanks for your help! \$\endgroup\$
    – David777
    Commented Dec 28, 2020 at 20:29

4 Answers 4

5
\$\begingroup\$

The problem is statements:

if(rising_edge(Set_Button) and Set_Button = '1')
.
.
if(rising_edge(Enable_Button) and Enable_Button = '1')

When you synthesise this code, the synthesiser recognises these two signals as the clocks in your design. These are also Input Ports in your module. If these signals were truly clock inputs in your design (which I don't think you intended to do so), you should map these to Clock Capable Pins in the FPGA. Otherwise the synthesiser won't be able to use dedicated clock routing from the respective IOs thru BUFGs, to the flip-flops clocked by them. Hence, the error messages.

Well, anyway I don't think you intended to use them as clocks, so this is what you might be looking for instead -

if rising_edge(clk) then

   if Enable_button = '1' then 
      ..
   end if

   if Set_button = '1' then
      ...
   end if   

end if
\$\endgroup\$
3
\$\begingroup\$

Your design as it is isn't clocked at all.

This will be difficult to synthesize as the registers in the logic blocks have a clock and an enable input, and it is assumed that the FF switches on a rising clock edge while the enable is set.

What you are doing instead is taking over data on the rising edge of an enable signal, which must be synthesized by shunting the "enable" signal to the clock input of the FF. Since clock routing is separate (because clocks have high fanout and strict timing requirements), there is usually no good mechanism for that.

The error message you get complains that you are routing an input pin that isn't clock capable to a clock net, which leads to a very convoluted routing because the only place to connect these is on the other side of the chip.

The constraint it suggests would clarify that you aren't asking for this signal to be injected into a clock distribution net, which would relax the routing problem here, but limit the fanout of the signal.

The constraint also likely generates the routing you expect, with the clock tied high and the enable routed to the FF, but with no timing constraint on the enable, because constraints are tracked against a clock internally, which you don't have.

The problem should go away if you actually make this design clocked.

\$\endgroup\$
3
  • \$\begingroup\$ Thanks for your answer. Ok I see what Vivado doesn't like now however my entire is design is based on this. I never had this problem during simulation but now when using the FPGA board I see my designs aren't going to work. Would you recommend I change my design for all components to be clocked and then in my processes decide whether or not to set or enable based on the inputs on the clock rising edge? At least this will then synthesize onto the board? \$\endgroup\$
    – David777
    Commented Dec 19, 2020 at 10:32
  • 1
    \$\begingroup\$ @David777 The style is bad and simply won't work for most VHDL, but for something as simple as what you have here, LUT edge detection will work, although I'm skeptical that you'll effectively will have written a RAM. If all you want right now is to make some LEDs blink, just disable the dedicated clock routing as mentioned in the error message and take Simon's and Mitu Raj's lessons to heart for the next time. \$\endgroup\$
    – DonFusili
    Commented Dec 22, 2020 at 12:51
  • \$\begingroup\$ @DonFusili I understand what you mean, it is a poor example. However this will be for an actual RAM block, I just used the FPGA board with buttons as the set and enable inputs to speed up testing different data combinations. \$\endgroup\$
    – David777
    Commented Dec 28, 2020 at 20:31
2
\$\begingroup\$

The message is telling you that one of the pins is being used as a clock but it isn't really a good pin to use as a clock. I would first get rid of the extra "and Set_Button = '1')" and "and Enable_Button='1')". You only need the "rising_edge" part.

You should also split the process into two processes and make each sensitive to their respective clock.

If you still get the error, can you pick different pins for the "Set_Button" and "Enable_Button"?

\$\endgroup\$
2
  • \$\begingroup\$ Thanks for your advice. I split the processes up and changed their sensitivity list and it still didn't like it. Tried a few different pins as well with no success. See my comment Simon Richter's answer above \$\endgroup\$
    – David777
    Commented Dec 19, 2020 at 10:29
  • 1
    \$\begingroup\$ @David777 . Try removing the Xilinx pin constraint for Set_Button and Enable_Button. See if it will work with Xilinx picking the pin. \$\endgroup\$
    – IanJ
    Commented Dec 20, 2020 at 1:32
1
\$\begingroup\$

Just providing an update to this question. As per everyone's advice, I had modified my VHDL to clock the design and the problem is solved. This allowed the synthesiser to use clock capable pins for the clock and the other pins for the set and enable input.

It has however caused me more issues throughout my complete design as I have this same issue in other VHDL code. Thanks for everyone's help. I have accepted an answer however everyone's answer was very helpful and greatly appreciated!



library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use work.Architecture_size.ALL;

entity RAM_Block is
 Port ( Clock : in std_logic;
        RAM_Address : in std_logic_vector (Data_width-1 downto 0); 
        Data_in  : in std_logic_vector (Data_width-1 downto 0);
        Set : in std_logic;
        Enable : in std_logic;
        Data_out : out std_logic_vector (Data_width-1 downto 0);
        RAM_Address_LED : out std_logic_vector (Data_width-1 downto 0);
        Data_in_LED : out std_logic_vector (Data_width-1 downto 0));
end RAM_Block;

architecture Behavioral of RAM_Block is

component Enabler_Block is
 Port ( A : in std_logic_vector(Data_width-1 downto 0);
        Enable : in std_logic;
        Q : out std_logic_vector(Data_width-1 downto 0));
end component;

type ram_type is array (0 to 3) of std_logic_vector (Data_width-1 downto 0);
signal RAM : ram_type := (others => "0000");
signal RAM_output : std_logic_vector (Data_width-1 downto 0);
signal RAM_Address_int : integer;


begin

Data_in_LED <= Data_in; 

RAM_Address_LED <= RAM_Address;

Enabler_Block_instance : Enabler_Block port map (A => RAM_output , Enable => Enable , Q => Data_out);

RAM_Address_int <= conv_integer(unsigned(RAM_Address)); 

   Process (Clock)

    begin

     if(rising_edge(Clock)) then
     
       if(Set = '1') then
        RAM(RAM_Address_int) <= Data_in;
        
       end if;
       
     end if;
     
    end process;
    
    Process (Clock)

     begin

     if(rising_edge(Clock)) then
     
        if(Enable = '1') then
         RAM_output <= RAM(RAM_Address_int);
         
        end if;  
     end if;

    end Process;
   
end Behavioral;

```
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.