Has anyone successfully achieved this? I am inferring a simple dual-port memory using HDL:
I have designed a circuit where I hold the port A write address and data for multiple cycles. I pulse the port A write enable on the last cycle.
-- These are stable for at least 2 cycles....more like 4+
port_a_wr_addr <= port_a_wr_addr_reg when rising_edge(clk);
port_a_wr_data <= port_a_wr_data_reg when rising_edge(clk);
-- port_a_wr_en_reg is a pulse that's asserted synchronously with the addr and data buses.
port_a_wr_en_d1 <= port_a_wr_en_reg when rising_edge(clk);
port_a_wr_en_d2 <= port_a_wr_en_d1 when rising_edge(clk);
port_a_wr_en <= port_a_wr_en_d2 when rising_edge(clk);
I use Vivado tcl to set 2 pairs of setup and hold multicycle path constraints.
One pair of constraints defines setup and hold for all paths "FROM" the port_a_wr_addr_reg register.
One pair of constraints define setup and hold for all paths "FROM" the port_a_wr_data_reg register.
I've verified in the Vivado GUI that the TO cells are all BlockRam ADDR, DATA, and ENA pins.
When I build WITH the multicycle constraints, the resulting bitstream is functionally INCORRECT.
When I build WITHOUT the multicycle constraints, the resulting bitstream is functionally CORRECT.
When I build WITH the multicycle constraints, but I add a register stage between the port_a_wr_addr_reg and the Block Memory pin, the resulting bitstream is functionally CORRECT.
- Has anyone else tried doing this? Does it work? Is it valid to define multicycle paths with endpoints being Block Memory pins?
- Could my problems have anything to do with the fact that these memories are fairly deep, and the MSb of the address could be used to gate the ENA on particular ranks of the write?