如何通过消除嵌套的 if-else 语句来简化时序逻辑设计

How to simplify sequential logic design by eliminating nested if-else statements

我有一个使用 vhdl 实现的设计,该设计基于时钟触发,该时钟将输入信号发送到基于 sel 输入和另一个 2 位输入的 8 个输出通道之一。由于许多 if-else 语句,精心设计显示出大量嵌套。所以,我很好奇是否有办法使用 case 语句或其他方法来减少嵌套。我不熟悉使用 case 语句执行此操作,因为我有两个确定输出通道的输入。我目前拥有的代码如下所示。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;


--Inputs and outputs to entity 
entity DSA_Worker is
    Port ( DB_Select : in STD_LOGIC;
           Atten : in STD_LOGIC_VECTOR ( 7 downto 0);
           enable : in STD_LOGIC;
           clk: in STD_LOGIC;
           reset: in STD_LOGIC;
           chip_select : in STD_LOGIC_VECTOR (1 downto 0);
           DBA_TX1_DSA : out STD_LOGIC_VECTOR (7 downto 0);
           DBA_TX2_DSA : out STD_LOGIC_VECTOR (7 downto 0);
           DBA_RX1_DSA : out STD_LOGIC_VECTOR (7 downto 0);
           DBA_RX2_DSA : out STD_LOGIC_VECTOR (7 downto 0);
           DBB_TX1_DSA : out STD_LOGIC_VECTOR (7 downto 0);
           DBB_TX2_DSA : out STD_LOGIC_VECTOR (7 downto 0);
           DBB_RX1_DSA : out STD_LOGIC_VECTOR (7 downto 0);
           DBB_RX2_DSA : out STD_LOGIC_VECTOR (7 downto 0));
end DSA_Worker;

architecture Behavioral of DSA_Worker is

begin
process(clk)
begin
  if rising_edge(clk) then
  --if reset is high, all outputs go to 0
     if reset = '1'then
       DBA_TX1_DSA <= (others =>'0');
       DBA_TX2_DSA <= (others =>'0');
       DBA_RX1_DSA <= (others =>'0');
       DBA_RX2_DSA <= (others =>'0');
       DBB_TX1_DSA <= (others =>'0');
       DBB_TX2_DSA <= (others =>'0');
       DBB_RX1_DSA <= (others =>'0');
       DBB_RX2_DSA <= (others =>'0');
        
          
      -- attenuation values sent to channels based on DB_select value(0/1) and chip select value
       --DB_select - 0 is for DB-A and 1 for DB- B and chip_select determines the channel 
       elsif enable = '1'then
             if(DB_Select='0' and chip_select = "00") then -- attenuation value sent to first channel
             DBA_TX1_DSA(0) <= Atten(0);
             DBA_TX1_DSA(1) <= Atten(1);
             DBA_TX1_DSA(2) <= Atten(2);
             DBA_TX1_DSA(3) <= Atten(3);
             DBA_TX1_DSA(4) <= Atten(4);
             DBA_TX1_DSA(5) <= Atten(5);

             elsif (DB_Select='0' and chip_select = "01") then 
             DBA_TX2_DSA(0) <= Atten(0);
             DBA_TX2_DSA(1) <= Atten(1);
             DBA_TX2_DSA(2) <= Atten(2);
             DBA_TX2_DSA(3) <= Atten(3);
             DBA_TX2_DSA(4) <= Atten(4);
             DBA_TX2_DSA(5) <= Atten(5);
        
             elsif (DB_Select='0' and chip_select = "10") then
             DBA_RX1_DSA(0) <= Atten(0);
             DBA_RX1_DSA(1) <= Atten(1);
             DBA_RX1_DSA(2) <= Atten(2);
             DBA_RX1_DSA(3) <= Atten(3);
             DBA_RX1_DSA(4) <= Atten(4);
             DBA_RX1_DSA(5) <= Atten(5);
  
            elsif (DB_Select='0' and chip_select = "11") then
            DBA_RX2_DSA(0) <= Atten(0);
            DBA_RX2_DSA(1) <= Atten(1);
            DBA_RX2_DSA(2) <= Atten(2);
            DBA_RX2_DSA(3) <= Atten(3);
            DBA_RX2_DSA(4) <= Atten(4);
            DBA_RX2_DSA(5) <= Atten(5);
      
            -- Attenuation values being set for DB-B
            elsif (DB_Select='1' and chip_select = "00") then 
            DBB_TX1_DSA(0) <= Atten(0);
            DBB_TX1_DSA(1) <= Atten(1);
            DBB_TX1_DSA(2) <= Atten(2);
            DBB_TX1_DSA(3) <= Atten(3);
            DBB_TX1_DSA(4) <= Atten(4);
            DBB_TX1_DSA(5) <= Atten(5);
       
            elsif (DB_Select='1' and chip_select = "01") then 
            DBB_TX2_DSA(0) <= Atten(0);
            DBB_TX2_DSA(1) <= Atten(1);
            DBB_TX2_DSA(2) <= Atten(2);
            DBB_TX2_DSA(3) <= Atten(3);
            DBB_TX2_DSA(4) <= Atten(4);
            DBB_TX2_DSA(5) <= Atten(5);
 
            elsif (DB_Select='1' and chip_select = "10") then 
            DBB_RX1_DSA(0) <= Atten(0);
            DBB_RX1_DSA(1) <= Atten(1);
            DBB_RX1_DSA(2) <= Atten(2);
            DBB_RX1_DSA(3) <= Atten(3);
            DBB_RX1_DSA(4) <= Atten(4);
            DBB_RX1_DSA(5) <= Atten(5);
       
         else 
         DBB_RX2_DSA(0) <= Atten(0);
         DBB_RX2_DSA(1) <= Atten(1);
         DBB_RX2_DSA(2) <= Atten(2);
         DBB_RX2_DSA(3) <= Atten(3);
         DBB_RX2_DSA(4) <= Atten(4);
         DBB_RX2_DSA(5) <= Atten(5);
            
            end if; 
        end if;
     end if;

end process;

end Behavioral;

我确实尝试使用案例语句生成简化设计,如下图所示

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity dsa_case is
   Port ( 
           DB_Select : in STD_LOGIC;
           Atten : in STD_LOGIC_VECTOR ( 7 downto 0);
           enable : in STD_LOGIC;
           clk: in STD_LOGIC;
           reset: in STD_LOGIC;
           chip_select : in STD_LOGIC_VECTOR (1 downto 0);
           DBA_TX1_DSA : out STD_LOGIC_VECTOR (7 downto 0);
           DBA_TX2_DSA : out STD_LOGIC_VECTOR (7 downto 0);
           DBA_RX1_DSA : out STD_LOGIC_VECTOR (7 downto 0);
           DBA_RX2_DSA : out STD_LOGIC_VECTOR (7 downto 0);
           DBB_TX1_DSA : out STD_LOGIC_VECTOR (7 downto 0);
           DBB_TX2_DSA : out STD_LOGIC_VECTOR (7 downto 0);
           DBB_RX1_DSA : out STD_LOGIC_VECTOR (7 downto 0);
           DBB_RX2_DSA : out STD_LOGIC_VECTOR (7 downto 0));
end dsa_case;

architecture Behavioral of dsa_case is

begin

process(clk)
begin

    if rising_edge(clk) then
       if reset = '1' then
        DBA_TX1_DSA <= (others =>'0');
        DBA_TX2_DSA <= (others =>'0');
        DBA_RX1_DSA <= (others =>'0');
        DBA_RX2_DSA <= (others =>'0');
        DBB_TX1_DSA <= (others =>'0');
        DBB_TX2_DSA <= (others =>'0');
        DBB_RX1_DSA <= (others =>'0');
        DBB_RX2_DSA <= (others =>'0');
       
       
     elsif enable = '1'then
        --    DB_Select <='0';
            case chip_select is
             when "00"=>   -- attenuation value sent to first channel
             DBA_TX1_DSA(0) <= Atten(0);
             DBA_TX1_DSA(1) <= Atten(1);
             DBA_TX1_DSA(2) <= Atten(2);
             DBA_TX1_DSA(3) <= Atten(3);
             DBA_TX1_DSA(4) <= Atten(4);
             DBA_TX1_DSA(5) <= Atten(5);

             when "01"=>
             DBA_TX2_DSA(0) <= Atten(0);
             DBA_TX2_DSA(1) <= Atten(1);
             DBA_TX2_DSA(2) <= Atten(2);
             DBA_TX2_DSA(3) <= Atten(3);
             DBA_TX2_DSA(4) <= Atten(4);
             DBA_TX2_DSA(5) <= Atten(5);
        
            when "10"=>
             DBA_RX1_DSA(0) <= Atten(0);
             DBA_RX1_DSA(1) <= Atten(1);
             DBA_RX1_DSA(2) <= Atten(2);
             DBA_RX1_DSA(3) <= Atten(3);
             DBA_RX1_DSA(4) <= Atten(4);
             DBA_RX1_DSA(5) <= Atten(5);
  
            when "11"=>
            DBA_RX2_DSA(0) <= Atten(0);
            DBA_RX2_DSA(1) <= Atten(1);
            DBA_RX2_DSA(2) <= Atten(2);
            DBA_RX2_DSA(3) <= Atten(3);
            DBA_RX2_DSA(4) <= Atten(4);
            DBA_RX2_DSA(5) <= Atten(5);
      
            -- Attenuation values being set for DB-B
      --      DB_Select <= '1';
            when "00"=>
            DBB_TX1_DSA(0) <= Atten(0);
            DBB_TX1_DSA(1) <= Atten(1);
            DBB_TX1_DSA(2) <= Atten(2);
            DBB_TX1_DSA(3) <= Atten(3);
            DBB_TX1_DSA(4) <= Atten(4);
            DBB_TX1_DSA(5) <= Atten(5);
       
      --      DB_Select <= '1';
            when "01" =>
            DBB_TX2_DSA(0) <= Atten(0);
            DBB_TX2_DSA(1) <= Atten(1);
            DBB_TX2_DSA(2) <= Atten(2);
            DBB_TX2_DSA(3) <= Atten(3);
            DBB_TX2_DSA(4) <= Atten(4);
            DBB_TX2_DSA(5) <= Atten(5);
 
     --       DB_Select <= '1';
            when "10"=> 
            DBB_RX1_DSA(0) <= Atten(0);
            DBB_RX1_DSA(1) <= Atten(1);
            DBB_RX1_DSA(2) <= Atten(2);
            DBB_RX1_DSA(3) <= Atten(3);
            DBB_RX1_DSA(4) <= Atten(4);
            DBB_RX1_DSA(5) <= Atten(5);
       
         when others=>
         DBB_RX2_DSA(0) <= Atten(0);
         DBB_RX2_DSA(1) <= Atten(1);
         DBB_RX2_DSA(2) <= Atten(2);
         DBB_RX2_DSA(3) <= Atten(3);
         DBB_RX2_DSA(4) <= Atten(4);
         DBB_RX2_DSA(5) <= Atten(5);
         
        end case;
        
      end if;
    end if; 
 end process;


end Behavioral;

然而,由于5个错误,它确实未能制作出精巧的设计,都是这样

[Synth 8-517] overlapping choice 2'b00 in case statement ["/home/n310-osp/case_statement_design/case_statement_design.srcs/sources_1/new/dsa_case.vhd":108]

就我个人而言,我不介意您的 if-else 结构。我认为你主要有一个可读性问题,有很多冗余(在这种情况下检查每个案例中的 DB_Select )和不一致的缩进。

这就是我如何改进 process:

中的代码
process(clk)
begin
  if rising_edge(clk) then
    --if reset is high, all outputs go to 0
    if reset = '1' then
      DBA_TX1_DSA <= (others=>'0');
      DBA_TX2_DSA <= (others=>'0');
      DBA_RX1_DSA <= (others=>'0');
      DBA_RX2_DSA <= (others=>'0');
      DBB_TX1_DSA <= (others=>'0');
      DBB_TX2_DSA <= (others=>'0');
      DBB_RX1_DSA <= (others=>'0');
      DBB_RX2_DSA <= (others=>'0');
         
    -- attenuation values sent to channels based on DB_select value(0/1) and chip select value
    -- DB_select - 0 is for DB-A and 1 for DB- B and chip_select determines the channel 
    elsif enable = '1'then
      if DB_Select = '0' then
        if chip_select = "00" then -- attenuation value sent to first channel
          DBA_TX1_DSA(5 downto 0) <= Atten(5 downto 0);
        elsif chip_select = "01" then 
          DBA_TX2_DSA(5 downto 0) <= Atten(5 downto 0);
        elsif chip_select = "10" then
          DBA_RX1_DSA(5 downto 0) <= Atten(5 downto 0);
        else
          DBA_RX2_DSA(5 downto 0) <= Atten(5 downto 0);
        end if;
      else -- Attenuation values being set for DB-B
        if chip_select = "00" then 
          DBB_TX1_DSA(5 downto 0) <= Atten(5 downto 0);
        elsif chip_select = "01" then 
          DBB_TX2_DSA(5 downto 0) <= Atten(5 downto 0);
        elsif chip_select = "10" then 
          DBB_RX1_DSA(5 downto 0) <= Atten(5 downto 0);
        else 
          DBB_RX2_DSA(5 downto 0) <= Atten(5 downto 0);
        end if;
      end if;
    end if;
  end if;
end process;

end Behavioral;

您可以将 if-else 结构替换为 when-else,但这只是偏好问题。