【问题标题】:VHDL Dynamic slicing using mathematical expression使用数学表达式的 VHDL 动态切片
【发布时间】:2014-12-07 01:44:05
【问题描述】:

是否有一种简单的方法来实现以下行:

DataTX(255-index*8 downto 248-index*8)  <= encoded;

index 是一个整数,可以在 0 到 31 的范围内。

DataTx 是一个 STD_LOCIC_VECTOR(263 down to 0)。

现在它当前抛出一个错误,指出 DataTx(263) 和 DataTx(260) 有多个驱动程序,这实际上并没有发生在这一行中。

有没有什么方法可以编写或实现它而不必做大量的 if 语句或 case 语句。

在此先感谢。

编辑: 上面的行放在一个进程中。 同时DataTx的其他部分在进程外设置如下

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;

编辑2:

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;

【问题讨论】:

  • 在适当的上下文中,您给出的行将适用于 index 等适当的值。如果没有更多代码,我们只能猜测多个驱动程序的来源。请使用您可以制作的最小的独立示例来更新 Q 以说明问题。
  • 看来错误不在于切片,而在于分配给DataTX(263 和DataTX(260)。更多代码(可能还有错误日志)将有助于确定问题。

标签: hardware vhdl slice


【解决方案1】:

更新后的问题提供了足够的信息来尝试回答。 它归结为“本地静态”,即无需实际执行过程即可计算,因此可以合成硬件以满足规范。

现在对你来说可能很明显

DataTX(<arbitrary range expression>)  <= encoded;

只驱动DataTX 的选定部分,不驱动其他部分,不评估&lt;arbitrary range expression&gt;,但综合工具并不那么智能。因此语言对进程施加了限制,“本地静态”表达式是DataTX 的全部,因此进程驱动DataTX 的全部。

(注意:如果范围表达式纯粹是常量或数字文字,则此限制不适用)

然后,外部分配会形成您的额外驱动程序,从而导致“多个驱动程序”错误。

两个修复:

1) 在进程中驱动整个DataTX,即在进程中移动其他切片分配......这对我来说看起来像是不干净的设计

2) 分配一个新信号,例如EncodedTX 进程内,并在外部将其分配给正确的 DataTX 切片

DataTX(255 downto 0) <= EncodedTX;

或更好(更清晰的设计意图)

DataTX <= SPI_Mode_Bits & SPI_Register & Encoded_TX;

为SPI_Mode_Bits 信号提供合适的声明和赋值。

可能还有其他修复,但其中的第二个可能是我的首选...

鉴于 Edit2,我现在认为选项 (1) 更简洁:例如在主状态机进程中分配额外的位,这是您设置 SPI_Mode 和 SPI_Register 的地方。您甚至可以将 SPI_Register 设为 Data_TX 相关切片的别名。然后,您无需在 SM 和支持它所需的外部 cruft 之间进行交叉引用。

例如,考虑以下声明:

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

状态机现在将执行所有对 Datatx 的分配,并且可以简单地删除外部分配。

【讨论】:

  • 有道理!谢谢!决定听从你的第二个建议!谢谢!
  • 鉴于 Edit2 我相信 (1) 更干净:例如在 Setup_State 中分配额外的位,这是您设置 SPI_Mode 和 SPI_Register 的地方。您甚至可以将 SPI_Register 设为 Data_TX 相关切片的别名。那么你就不需要在 SM 和支持它所需的外部 cruft 之间进行交叉引用了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-10
  • 2010-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多