UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Observer teldeeb
Observer
178 Views
Registered: ‎09-11-2015

Inferring Dual port from incomplete Record Range

I have a package with a defined record as:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

package TestPkg is
 constant regfile_length	: integer:=(4*32);
 type t_regfile is record
	PID0                  : STD_LOGIC_VECTOR(63 downto 0); 
	PID1                  : STD_LOGIC_VECTOR(regfile_length-1 downto 66); --NOTE THE UNASSIGNED RANGE 65-64 !!
  end record t_regfile;
  function t_regfile_to_slv(L: t_regfile) return std_logic_vector;
  function slv_to_t_regfile(L: std_logic_vector(regfile_length-1 downto 0) ) return t_regfile;
end package;

package body TestPkg is
  function t_regfile_to_slv(L: t_regfile) return std_logic_vector is 
    variable RetVal:    std_logic_vector(regfile_length-1 downto 0):=(others=>'0'); 
    begin
        RetVal(L.PID0'range)	:= L.PID0;
        RetVal(L.PID1'range)  := L.PID1; 
        return(RetVal); 
  end function t_regfile_to_slv; 
  function slv_to_t_regfile(L: std_logic_vector(regfile_length-1 downto 0) ) return t_regfile is 
    variable RetVal:    t_regfile; 
    begin 
        RetVal := 
        ( 
            PID0   	=> L(RetVal.PID0'range),
	    PID1		=> L(RetVal.PID1'range)
        ); 
        return(RetVal); 
  end function slv_to_t_regfile; 
end TestPkg;

Then I define a RAM of such records as:

 

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use work.TestPkg.all;
entity testmem is
    Port ( 
		Clock: in std_logic;
		axi_sensor_id: in std_logic_vector(3 downto 0);
		sensor_id: in std_logic_vector(3 downto 0);
		axi_write_en : in  STD_LOGIC;
		axi_RegFilein	: in t_regfile;
		to_mc_RegFile	: out t_regfile;
	        axi_RegFile : out t_regfile
		);
end testmem;

architecture Behavioral of testmem is
  type tRegfileArray is array (natural range <>) of std_logic_vector(regfile_length-1 downto 0);
  signal regfileMem			: tRegfileArray(0 to 15); 
begin

MC_SELECT_REGFILE: process(  Clock )
begin
  if rising_edge(Clock) then
	 if (axi_write_en = '1' ) then
		regfileMem(conv_integer(axi_sensor_id))	<= t_regfile_to_slv(axi_RegFilein);
	 End if;
	 to_mc_RegFile	<= slv_to_t_regfile(regfileMem(conv_integer(sensor_id)));
	 axi_RegFile   <= slv_to_t_regfile(regfileMem(conv_integer(axi_sensor_id)));
  end if;
end process;
end Behavioral;

 

 

This does not infer a block RAM, but gives the synthesis info:

 

INFO:Xst:3218 - HDL ADVISOR - The RAM <Mram_regfileMem> will be implemented on LUTs either because you have described an asynchronous read or because of currently unsupported block RAM features. If you have described an asynchronous read, making it synchronous would allow you to take advantage of available block RAM resources, for optimized device usage and improved timings. Please refer to your documentation for coding guidelines.

But when I re-define the record with 

PID1                  : STD_LOGIC_VECTOR(regfile_length-1 downto 64);

A block is inferred as expected.

In real life my record has many such unused fields, blocking the RAM inference. How can I direct the synthesizer to ignore those unused ranges and continue with RAM inferring?

A dirty workaround is declaring new fields for each unused range, but this degrade readability and enlarges the code with no value.

 

0 Kudos
3 Replies
Scholar richardhead
Scholar
162 Views
Registered: ‎08-01-2012

Re: Inferring Dual port from incomplete Record Range

You have a memory with unconnected bits. Vivado isn't the best with inference,  so you're best off using a continuous array with no gaps. 

Any reason you're using ranges and simply not simply concatenating the  record elements? 

0 Kudos
Observer teldeeb
Observer
123 Views
Registered: ‎09-11-2015

Re: Inferring Dual port from incomplete Record Range

Concatenation is not an option, it's a memory map with predefined fields. Many bit ranges are preserved for future.

The problem statement is clear, but I need a clean implementation rather than the dirty workaround mentioned above.

0 Kudos
Scholar richardhead
Scholar
114 Views
Registered: ‎08-01-2012

Re: Inferring Dual port from incomplete Record Range

This does look like a defect with synthesis, as the "holes" should be assigned to '0' by the variable initialisation in the to_slv function. But you're also using XST, so this will not get fixed, so you're going to have to work around it. Vivado might work, but I assume you're using an unsupported chip for vivado.

I think you need to think around the problem a little. Rather than mapping the record directly to your memory map, why not just have the record as an abstract collection of data? That way, the memory map is separated from the data storage and you avoid the problem you are getting by mixing the two. This way you only store the data actually in use, and the holes can be inserted directly at the mapping stage, rather than the ram.

Mixing the mapping into the data types may make it harder in future if you need to expand or move bit around the register map, as one change may affect several type declarations, which may have knock on effects in many places. Having the types as abstract, then these can be left alone and only the mapping needs changing, and it's easy to add fields to the record without affecting any types.

 

0 Kudos