# Undefined std_logic_vector size parameter in procedure

I have written into a procedure the behavior of a simple SPI transaction that I use in my testbenches to make things easier to write and read. Is there a way to make this procedure as generic as possible by not mentioning the size of the vector data given as a parameter? Or maybe add a size parameter as an integer?

Here's the procedure I'm using so far. For now I have one procedure declaration for each vector size I want to transfer.

procedure spi_transfer_3B(data : std_logic_vector(23 downto 0)) is
variable bitCnt : integer := data'length-1;
begin
spi_clk <= '0';
spi_mosi <= 'Z';
spi_ss <= '0';
wait until rising_edge(clk);

for i in 2*data'length-1 downto 0 loop
wait for SPI_CLK_PERIOD/2;
spi_clk <= not spi_clk;
if spi_clk = '0' then
spi_mosi <= data(bitCnt);
bitCnt := bitCnt -1;
end if;
end loop;

spi_clk <= '0';
wait until rising_edge(clk);
spi_ss <= '1';
spi_mosi <= 'Z';
end spi_transfer_3B;


What do you think?

• Have you tried removing the range specification in the first line and seeing if it works for different widths of data? – scary_jeff Aug 3 '16 at 9:45
• Yes, it is somewhat working, but not really. spi_transfer(x"45") gives me "A2" after deserializing the MOSI line. But it is probably the way to go, I'm trying to find the tweaking needed here – Fluffy Aug 3 '16 at 9:58
• Oh... 0x45 = 0b01000101 and 0xA2 = 0b10100010. It's inverted, okay – Fluffy Aug 3 '16 at 10:01

This seems to work. I was confused because not mentioning x downto x coded the vector LSB first instead of MSB first as intended in my first snippet of code. It is that easy.

procedure spi_transfer(data : std_logic_vector) is
variable bitCnt : integer := 0;
begin
spi_clk <= '0';
spi_mosi <= 'Z';
spi_ss <= '0';
wait until rising_edge(clk);

for i in data'range loop
wait for SPI_CLK_PERIOD/2;
spi_clk <= '1';
spi_mosi <= data(i);
wait for SPI_CLK_PERIOD/2;
spi_clk <= '0';
end loop;

spi_clk <= '0';
wait until rising_edge(clk);
spi_ss <= '1';
spi_mosi <= 'Z';
end spi_transfer;

• You can simplify and eliminate bitCnt to i, by reversing the range of the loop for i in data'range loop ... (or reverse_range as appropriate), and a second wait and spi_clk assignment, instead of doubling the range and using the if statement. – user_1818839 Aug 3 '16 at 10:54
• Good call, it looks better this way. I'm editing my answer with your simplification. Thanks! – Fluffy Aug 3 '16 at 12:52
• .... closer ... but now you can (and probably must!) eliminate the "if" too, and you can explicitly set spi_clk to '0' or '1' in each assignment. – user_1818839 Aug 3 '16 at 13:40
• Edited again, thanks! I didn't read your first comment carefully enough, my bad – Fluffy Aug 3 '16 at 13:49