Hello,
I am fairly new to FPGA development and learning about constraining my system but am really struggling. My system 'works' at certain clock frequencies but change something and I have I/O glitches so I clearly haven't constrained the IO properly.
I've read and tried to understand
http://www.alterawiki.com/wiki/TimeQuest_User_Guide by Rysc and while that helped a lot I am struggling with generating the constraints.
I've done quite a bit of googling to try to find examples or references I can use as a base but my system doesn't fit the normal source synchronous simple examples.
Paint representation of the system:
The system is an 8 bit 5v micro "host" and an 8-bit 5v processor unit "parasite" connected via the MAX10 FPGA which implements various FIFO buffers as well as the boot ROM (via user FLASH) for the parasite uP. For the curious both uPs are 6502 variants. The 2MHzE clock comes from the host via buffers. The 8MHz FPGA clock is unrelated to the 2MHz clock. The FPGA generates the output clock for the parasite CPU using the PLL again via buffers (delay). All signal lines are buffered with delays.
I've tried to create the clocks but don't think I've got them defined right because TQ lists my clock input CLK_0n_p25 in the unconstrained inputs list.
The CPUs address timing goes from falling to falling which I think I have OK. The CPU read (FPGA out) goes from falling edge so I think that is OK too. The CPU write (FPGA in) setup is from the rising edge and hold is falling edge. I can't work out how to constrain this. The PLL will be reprogramable at runtime to change the parasite clock frequency so I don't want to hard code magic numbers for periods into the constraints but istead do it properly from the correct edges.
PLL[1] is the parasite CPU clock out skewed -5ns by the PLL.
PLL[2] is the parasite CPU clock no skew for internal timing.
I understand the setup errors I get as a result of the skewed clocks - I need to set up the multicycle paths between the clocks properly.
SDC (it is in a bit of a state because I have hacked at it a lot to try to get it working/understand what I'm doing..)
Code:
# needed?
set_time_format -unit ns -decimal_places 3
# physical clocks
create_clock -name clk_2MHzE -period 500 [get_ports {CLK_0n_p25}]
create_clock -name clk_8M_in -period 125 [get_ports {CLK_8meg_in_p26}]
# derived
create_generated_clock -name clk_flash -source [get_nets {cg|u0|int_osc_0|wire_clkout}] -divide_by 16 [get_nets {cg|clk_flash}]
# parasite clock at the pin
create_generated_clock -name parasite_phi0_out -source [get_pins {cg|internal_pll_inst|altpll_component|auto_generated|pll1|clk[1]}] [get_ports {parasite_phi0}]
# create external parasite cpu clock n ns delay
create_generated_clock -name parasite_phi0_ext -source [get_ports {parasite_phi0}] -offset 4.5
# virtual
#create_clock -name host_2MHzE_ext -period 500
#set_clock_latency -source -30 [get_clocks {host_2MHzE_ext}]
#set_clock_latency -source -5 [get_clocks {host_2MHzE_ext}]
#set_clock_latency seems to do nothing on virtual clocks
create_generated_clock -name host_2MHzE_ext -source [get_ports {CLK_0n_p25}] -offset -5
# name pll clocks
create_generated_clock -name parasite_phi0 -source [get_pins {cg|internal_pll_inst|altpll_component|auto_generated|pll1|clk[2]}]
# pll
derive_pll_clocks -create_base_clocks
derive_clock_uncertainty
# clock groups
set_clock_groups -asynchronous \
-group [get_clocks {clk_8M_in}] \
-group [get_clocks {int_osc_clk clk_flash}] \
-group [get_clocks {clk_2MHzE host_2MHzE_ext}] \
-group [get_clocks { \
cg|internal_pll_inst|altpll_component|auto_generated|pll1|clk[1] \
cg|internal_pll_inst|altpll_component|auto_generated|pll1|clk[2] \
parasite_phi0 parasite_phi0_out parasite_phi0_ext \
}]
#
# host i/o
# HOST->FPGA addr : 100ns setup + 5ns board delay, 15ns hold 100+5 & 15-5
set_input_delay -clock { host_2MHzE_ext } -clock_fall -max 105 [get_ports {host_a[*] host_r_nw host_tube_n}]
set_input_delay -clock { host_2MHzE_ext } -clock_fall -min 10 [get_ports {host_a[*] host_r_nw host_tube_n}]
# HOST->FPGA data : (500-110)ns setup, 30ns hold + 5ns board delay. 390+5 & 30-5
set_input_delay -clock { host_2MHzE_ext } -clock_fall -max 395 [get_ports {host_d[*]}]
set_input_delay -clock { host_2MHzE_ext } -clock_fall -min 25 [get_ports {host_d[*]}]
# FPGA->HOST data : 60ns setup + 5ns board delay, 10ns hold. 65+5 & -10+5
set_output_delay -clock { host_2MHzE_ext } -clock_fall -max 70 [get_ports {host_d[*]}]
set_output_delay -clock { host_2MHzE_ext } -clock_fall -min -5 [get_ports {host_d[*]}]
##
## parasite i/o
# PARA->FPGA addr : ~12 setup, ~10ns hold, ? delay. originally measured
set_input_delay -clock { parasite_phi0_ext } -clock_fall -max 12 [get_ports {parasite_a[*] parasite_r_nw}]
set_input_delay -clock { parasite_phi0_ext } -clock_fall -min 0 [get_ports {parasite_a[*] parasite_r_nw}]
# PARA->FPGA data : 5 setup, 10 hold, 3? delay.
set_input_delay -clock { parasite_phi0_ext } -max 13 [get_ports {parasite_d[*]}]
set_input_delay -clock { parasite_phi0_ext } -clock_fall -add_delay -min 0 [get_ports {parasite_d[*]}]
# FPGA->PARA data : 10 setup, 10 hold. 3? delay 10+3 & -10+3
set_output_delay -clock { parasite_phi0_ext } -clock_fall -max 15 [get_ports {parasite_d[*]}]
set_output_delay -clock { parasite_phi0_ext } -clock_fall -min -5 [get_ports {parasite_d[*]}]
#
# SRAM i/o
# FPGA->SRAM wren :
set_output_delay -clock { parasite_phi0 } -clock_fall -max 10 [get_ports {mem_we}]
set_output_delay -clock { parasite_phi0 } -clock_fall -min 0 [get_ports {mem_we}]
So questions:
1) Have I correctly created the 2MHz clock(s)? (TQ places my input pin CLK_0n_p25 on unconstrained input report)
2) How do I constrain the data IO from rising egde launch & falling edge latch? (this is not right in my SDC)
3) My min parasite clock is 3MHz and max 25Mhz. How do I manage a variant since since the clock is currently derived from the PLL megafunction settings?
Any help appreciated, I am vey confused at the moment.
Thanks,
Chris