I am using Vivado 2016.4 to program the Nexys4 DDR 7-segment display.
I have a very simple VHDL project, which works as follows:
100 MHz clock is used to increment an 8-bit counter
when this counter overflows, it inverts the value of a local signal called "slowclk". Hence, "slowclk" is "clk" divided by 512.
the "slowclk" is used to increment another 8-bit counter, the output of which is assigned to the 7-segment display segment selector pins on the board.
Complete VHDL source:
Spoiler
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity segdisp is
port ( clk : in std_logic;
seg_en : out std_logic_vector(7 downto 0);
seg_cs : out std_logic_vector(7 downto 0) );
end;
architecture top of segdisp is
signal r_count: natural range 0 to 255 := 0;
signal disp_next: std_logic := '0';
signal seg_cs_int: natural range 0 to 255;
signal clkdiv: natural range 0 to 255 := 0;
signal slowclk: std_logic := '0';
function int2slv(arg: integer; length: positive) return std_logic_vector is
begin
return std_logic_vector(to_unsigned(arg, length));
end function;
begin
seg_cs <= int2slv(seg_cs_int, seg_cs'length);
seg_en <= not X"80";
divider: process (clk)
begin
if rising_edge(clk) and clk = '1' then
if clkdiv = 255 then
clkdiv <= 0;
slowclk <= not slowclk;
else
clkdiv <= clkdiv + 1;
end if;
end if;
end process;
main: process (slowclk)
begin
if rising_edge(slowclk) and slowclk = '1' then
seg_cs_int <= seg_cs_int + 1;
end if;
end process;
end architecture top;
Note: I understand that given such division, the effect on the digit segments will still not be visible - I just want to demonstrate the timing problem.
However, the design fails to meet timing constraints as follows in attached pictures:
Timing constraint failures in more detail, including the full source VHDL:
Clock routing on the FPGA:
The following is the .xdc constraints file (commented-out definitions are omitted):
From what little I know about FPGA clock routing and resources, I understand this to be due to the high-frequency clock and associated logic being in different regions to each other, thus requiring the implementation run to route the clock signal through awkward paths; as a consequence, the total signal propagation time is such, that before the logic relevant to the current clock pulse is evaluated, the next clock front is already present.
Am I correct in this thinking? And in either case, how can I fix the timing issues that Vivado warns about?
Question
maximb
Hi,
I am using Vivado 2016.4 to program the Nexys4 DDR 7-segment display.
I have a very simple VHDL project, which works as follows:
Complete VHDL source:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity segdisp is
port ( clk : in std_logic;
seg_en : out std_logic_vector(7 downto 0);
seg_cs : out std_logic_vector(7 downto 0) );
end;
architecture top of segdisp is
signal r_count: natural range 0 to 255 := 0;
signal disp_next: std_logic := '0';
signal seg_cs_int: natural range 0 to 255;
signal clkdiv: natural range 0 to 255 := 0;
signal slowclk: std_logic := '0';
function int2slv(arg: integer; length: positive) return std_logic_vector is
begin
return std_logic_vector(to_unsigned(arg, length));
end function;
begin
seg_cs <= int2slv(seg_cs_int, seg_cs'length);
seg_en <= not X"80";
divider: process (clk)
begin
if rising_edge(clk) and clk = '1' then
if clkdiv = 255 then
clkdiv <= 0;
slowclk <= not slowclk;
else
clkdiv <= clkdiv + 1;
end if;
end if;
end process;
main: process (slowclk)
begin
if rising_edge(slowclk) and slowclk = '1' then
seg_cs_int <= seg_cs_int + 1;
end if;
end process;
end architecture top;
Note: I understand that given such division, the effect on the digit segments will still not be visible - I just want to demonstrate the timing problem.
However, the design fails to meet timing constraints as follows in attached pictures:
Timing constraint failures in more detail, including the full source VHDL:
Clock routing on the FPGA:
The following is the .xdc constraints file (commented-out definitions are omitted):
## Clock signal
set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports { clk }]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0.000 5.000} [get_ports { clk }]
...
set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports {seg_cs[7]}]
set_property -dict {PACKAGE_PIN R10 IOSTANDARD LVCMOS33} [get_ports {seg_cs[6]}]
set_property -dict {PACKAGE_PIN K16 IOSTANDARD LVCMOS33} [get_ports {seg_cs[5]}]
set_property -dict {PACKAGE_PIN K13 IOSTANDARD LVCMOS33} [get_ports {seg_cs[4]}]
set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports {seg_cs[3]}]
set_property -dict {PACKAGE_PIN T11 IOSTANDARD LVCMOS33} [get_ports {seg_cs[2]}]
set_property -dict {PACKAGE_PIN L18 IOSTANDARD LVCMOS33} [get_ports {seg_cs[1]}]
set_property -dict {PACKAGE_PIN H15 IOSTANDARD LVCMOS33} [get_ports {seg_cs[0]}]
set_property -dict {PACKAGE_PIN J17 IOSTANDARD LVCMOS33} [get_ports {seg_en[0]}]
set_property -dict {PACKAGE_PIN J18 IOSTANDARD LVCMOS33} [get_ports {seg_en[1]}]
set_property -dict {PACKAGE_PIN T9 IOSTANDARD LVCMOS33} [get_ports {seg_en[2]}]
set_property -dict {PACKAGE_PIN J14 IOSTANDARD LVCMOS33} [get_ports {seg_en[3]}]
set_property -dict {PACKAGE_PIN P14 IOSTANDARD LVCMOS33} [get_ports {seg_en[4]}]
set_property -dict {PACKAGE_PIN T14 IOSTANDARD LVCMOS33} [get_ports {seg_en[5]}]
set_property -dict {PACKAGE_PIN K2 IOSTANDARD LVCMOS33} [get_ports {seg_en[6]}]
set_property -dict {PACKAGE_PIN U13 IOSTANDARD LVCMOS33} [get_ports {seg_en[7]}]
...
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 33 [current_design]
set_property CONFIG_MODE SPIx4 [current_design]
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
From what little I know about FPGA clock routing and resources, I understand this to be due to the high-frequency clock and associated logic being in different regions to each other, thus requiring the implementation run to route the clock signal through awkward paths; as a consequence, the total signal propagation time is such, that before the logic relevant to the current clock pulse is evaluated, the next clock front is already present.
Am I correct in this thinking? And in either case, how can I fix the timing issues that Vivado warns about?
Link to comment
Share on other sites
2 answers to this question
Recommended Posts
Archived
This topic is now archived and is closed to further replies.