Is there an easy way to implement the following line:
DataTX(255-index*8 downto 248-index*8) <= encoded;
index is an integer that could be in the range 0 to 31.
DataTx is a STD_LOCIC_VECTOR(263 downto 0).
Now it currently throws an error saying there are multiple drivers for DataTx(263) and DataTx(260), which isn't actually occurring in this line.
Is there any way to write this line or implement it without have to do a massive if statement or case statement.
Thanks in the advance.
Edit: The line above is placed in a process. Meanwhile the other parts of DataTx are set outside the process as follows
DataTX(263 downto 261) <= "000" when spi_mode=reading else "001" when spi_mode=writing
else "011" when spi_mode=rxMode else "101" when spi_mode=txMode;
DataTX(260 downto 256) <= SPI_register;
Edit2:
DataTX(263 downto 261) <= "000" when spi_mode=reading else "001" when spi_mode=writing
else "011" when spi_mode=rxMode else "101" when spi_mode=txMode;
DataTX(260 downto 256) <= SPI_register;
-- Set the RF Chan based on input
rf_chan <= RfChans(0) when base_selection="00" else RfChans(1) when base_selection="01" else
RfChans(2) when base_selection="10" else RfChans(3) when base_selection="11";
-- Set the Base Address based on input
base_addr <= Bases(0) when base_selection="00" else Bases(1) when base_selection="01" else
Bases(2) when base_selection="10" else Bases(3) when base_selection="11";
process(clk)
variable s_index : integer range 0 to 31 := 0;
variable e_index : integer range 0 to 31 := 0;
variable r_index : integer range 0 to 31 := 0;
variable counter : integer range 0 to 7 := 0;
begin
if (rst = '1') then
...
elsif (clk'event and clk='1') then
case state is
when setup =>
case setup_state is
-- Some code like this is set here
spi_mode <= writing;
spi_register <= "10000";
DataTX(255 downto 224) <= base_addr;
DataTX(223 downto 0) <= (others => '1'); -- Fill with FF
when idle =>
... -- nothing here of relevance
-- Moves to E_setup
when E_setup =>
-- DataTx set here
spi_mode <= writing;
spi_register <= "00000";
SPI_trigger <= '1';
state <= E_setupd;
when E_setupd => -- one cycle delay
SPI_Trigger <= '0';
if ((counter = 7) and SS='1') then
-- Signals that SPI module has finished
state <= E_encode;
counter := 0;
elsif (counter < 7) then -- Give it some time to start
counter := counter +1;
end if;
when E_encode =>
encode_input <= SEQUENCE(e_index);
e_index := e_index +1;
state <= E_done;
when E_done =>
spi_register <= "00000";
-- Error here
DataTX(255-index*8 downto 248-index*8) <= encoded;
if (e_index = 31) then
e_index := 0;
state <= E_send;
else
e_index := e_index +1;
state <= E_encode;
end if;
end case;
end if;
end process;
The updated question gives enough information to attempt an answer. It comes down to what is "locally static" i.e. computable without actually executing the process, so that hardware can be synthesised to meet the specification.
Now it might be obvious to you that
DataTX(<arbitrary range expression>) <= encoded;
only drives selected parts of DataTX
leaving others undriven, without evaluating <arbitrary range expression>
, but the synthesis tool isn't quite that smart. So the language places a restriction on the process, that the "locally static" expression is ALL of DataTX
and so the process drives all of DataTX
.
(NOTE: had the range expression been purely in terms of constants or numeric literals,this restriction would not apply)
The external assignments then form your additional drivers giving rise to "multiple drivers" errors.
Two fixes :
1) Drive the entirety of DataTX
within the process, i.e. move the other slice assignments within the process ... this looks like unclean design to me
2) Assign a new signal e.g. EncodedTX
within the process, and externally assign it to the correct slice of DataTX
DataTX(255 downto 0) <= EncodedTX;
or better (clearer design intent)
DataTX <= SPI_Mode_Bits & SPI_Register & Encoded_TX;
with a suitable declaration and assignment for the SPI_Mode_Bits
signal.
Possibly there are other fixes too, but the second of these would probably be my first choice...
Given Edit2 I now believe option (1) is cleaner : e.g. assigning the extra bits in the main state machine process, which is where you set up SPI_Mode and SPI_Register anyway. You can even make SPI_Register an alias for the relevant slice of Data_TX. Then you don't need to cross reference between the SM and the external cruft needed to support it.
For example, consider the following declarations :
alias SPI_Register : std_logic_vector(4 downto 0) is DataTX(260 downto 256);
subtype SPI_Mode_Type is std_logic_vector(2 downto 0);
alias SPI_Mode : SPI_Mode_Type is DataTX(263 downto 261);
constant writing : SPI_Mode_Type := "001"; -- and a few more of these
The state machine, without change, will now perform all the assignments to Datatx and the external assignments can simply be deleted.