I'm trying to write data into an instance of the Xilinx Memory Interface Generator that I receive from a UART. I'm using VHDL in Vivado.
The UART presents data 8 bits at a time, with quite a few clock cycles between each fresh data. The MIG data input is a 512-bit vector.
signal s_app_wdf_data : STD_LOGIC_VECTOR(511 downto 0); -- Output to MIG
signal s_uart_data : STD_LOGIC_VECTOR(7 downto 0); -- input from UART
I wish to populate the vector with data received from the UART. I will update each part of the vector and then when I get the last byte from the UART I will enable the write signals to the MIG.
I created a counter to keep track of what position in the vector was the relevant position for UART data to be written to, so every time there is fresh data on the UART do something like this:
s_app_wdf_data(v_position downto v_position - 7) <= s_uart_data;
v_position := v_position - 8;
However, this took about an hour to do route_design, and gave timing errors (negative slack).
I was thinking that in order for that to work then the tools would have to synthesise something that essentially allows random access to any part of the vector, so maybe I could help clarify to the tools that only certain parts of the vector would ever be accessed since the position only ever changes in decrements of 8. I wrote out
if (v_position = 511) then
s_app_wdf_data(511 downto 504) <= s_uart_data;
elsif (v_position = 503) then
s_app_wdf_data(503 downto 496) <= s_uart_data;
elsif (v_position = 495) then
s_app_wdf_data(495 downto 488) <= s_uart_data;
etc, etc
It was laborious to type out (a clear sign something is wrong), and in the end had even worse timing errors.
Next I tried to avoid code that would access arbitrary places in the vector, I tried using shifting and updating just the lowest byte.
s_app_wdf_data(511 downto 8) <= s_app_wdf_data(503 downto 0);
s_app_wdf_data(7 downto 0) <= s_uart_data;
This one had the worst Total Negative Slack of the lot.
What is the correct approach here? Or what techniques should I be researching?