I have some code that takes in 2^X samples and outputs 2^Y samples, where X and Y are integers and Y is less than X. So for example X=6,Y=4, I ingest 64 samples and output 16 samples.
As of right now, X and Y are generics, but I would like to make them, or the ratio between then, or the log2 of that ratio a signal, so that I might change my operation at runtime via a register write or something.
In my internal processing, using the example values of 64 and 16, I have to do some addressing and counting, and to generate some of the addresses I have to do soemthing like this:
constant pkt_addr_pad : std_logic_vector(15 -Y downto 0) := (others=>'0'); -- In this example is is 12 bits of 0 . . . raddr_short <= pkt_addr_pad & raddr (Y-1 downto 0);
to convert raddr which can contain values from 0 to 63, to raddr_short which only contains values of 0 to 15; effectively discarding bits 4 and 5, masking them to 0, whatever you want to call it.
I'm looking for the best way to be able to have Y change at runtime. obviously the timing for Y is relaxed, as it changes unimaginably less frequently relative to the actual address, and when it does change, the rest of my logic will be in an idle state such that raddr/raddr short won't be changing
I'd really rather avoid the whole:
raddr_short <= x"00" & "00" & raddr(5 downto 0) when Y = 6 else x"00" & "000" & raddr(4 downto 0) when Y = 5 else .... x"00" & "000000" & raddr(1 downto 0) when Y = 2 else x"0000";
as I've actually 4 of these things running at once, and as such have arrays of slv16 for each of the raddr/raddr_shorts, as well as waddrs, and...
Although I guess I could put the MUX in a function to clean up the code, but there has to be a better way. maybe some thing liek:
constant zeros16 : std_logic_vector(15 downto 0) := (others=>'0'); . . . raddr_short <= zeros(15 downto Y) & raddr (Y-1 downto 0);