处理复杂的范围选择逻辑。
选择信号的组合太多,选择和连接的范围太多。
我正在寻找一种更好的方法来使其可读,使用由预定义常量和动态输入生成的有意义的变量。
以下简化示例,不确定它是否可合成。
library ieee;
use ieee.std_logic_1164.all;
entity fum is
end entity;
architecture foo of fum is
signal sel: std_logic_vector (1 downto 0);
signal selected_range: std_logic_vector (5 downto 0);
signal counter: std_logic_vector (7 downto 0);
constant BASE_ADDR_LOW: integer := 2;
constant RANGE1_BITS : integer := 2;
-- this is simplified
-- dozens of constants involved, and their values can be configured before compiling.
begin
some_process:
process (sel, counter)
variable range0_high : integer := BASE_ADDR_LOW;
variable range1_low : integer := 0;
variable range1_high : integer := 0;
begin
if (sel = "00") then
-- this is simpilfied as well
-- dozens of inputs as sel involved, for 50+ combinations via nested if and case
range0_high := BASE_ADDR_LOW+1; -- 3
range1_low := range0_high+2; -- 5
range1_high := range1_low+RANGE1_BITS-1; -- 6
-- the following elsif will not work as the range1 has 0 bit.
-- not sure if there is a better way to do this
-- elsif (sel = "01" ) then
-- range0_high := BASE_ADDR_LOW+1; -- 5
-- range1_low := range0_high+2; -- N/A
-- range1_high := range1_low+RANGE1_BITS; --N/A
else
range0_high := BASE_ADDR_LOW; -- 2
range1_low := range0_high+2; -- 4
range1_high := range1_low+RANGE1_BITS; --6
end if;
-- using variables in range
selected_ranges <= counter(range1_high downto range1_low) & counter(range0_high downto 0);
end process;
end architecture;
如果某些字段可能是0位,有没有办法制作可综合的代码?
-- e.g. range0_high = 5, range1_* not in use
-- selected_ranges <= *nothing &* counter(5 downto 0);
答案 0 :(得分:0)
这不是Minimal, Complete, and Verifiable example。无论你是否过度思考问题。
您选择的&#39; selected_ranges&#39;是基于sel = "00"
是否具有两个可能值的多路复用器。
library ieee;
use ieee.std_logic_1164.all;
entity fum is
end entity;
architecture foo of fum is
signal sel: std_logic_vector (1 downto 0);
signal selected_range: std_logic_vector (5 downto 0);
signal counter: std_logic_vector (7 downto 0);
begin
some_process:
process (sel, counter)
begin
if sel = "00" then
selected_range <= counter (6 downto 5) & counter (3 downto 0);
else
selected_range <= counter (6 downto 4) & counter (2 downto 0);
end if;
end process;
end architecture;
此代码分析,详细说明和运行,并通过向sel
的{{1}}添加初始值并重做,表明两个备选方案的表达式长度都是正确的。
这将在综合中得到更加简化,注意上面的两个和下面的三个比特&#39;对于这两种情况,"00"
都是相同的。
所以,是的,你的代码是合成资格的,不是它没有动态范围(根据selected_range
只有一个&#39;可以是不同的,那些代表一个2:1多路复用器由两个输入门驱动,查看sel
。
您只是选择了一种难以表达代码功能的方法。 (这里的表达仍然是冗长的。)
答案 1 :(得分:0)
我将采用具有N个输入的普通多路复用器,并通过从包含多路复用器数据输入(mux_data_in
)的数组中选择结果来描述它:
type t_mux_data_in is array(natural range <>) of std_logic_vector(selected_range'range);
signal mux_data_in : t_mux_data_in(0 to N-1);
...
selected_range <= mux_data_in(to_integer(unsigned(sel)));
多路复用器数据输入使用for .. generate
循环和一些辅助函数生成,这些函数指定循环中每次迭代i
的范围。在循环中,您必须检查范围1是否为空。
完整代码如下所示,示例代码中给出了范围。我不得不修改案例sel = "01"
以得到一个空的范围1,看看我的评论。该代码在ISE 14.7中很好地合成,实际上生成了一个6位3对1多路复用器,因为情况2和3是相同的。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity fum is
generic (
SEL_BITS : positive := 2);
port (
sel : in std_logic_vector (SEL_BITS-1 downto 0);
counter : in std_logic_vector (7 downto 0);
selected_range : out std_logic_vector (5 downto 0));
end entity;
architecture foo of fum is
constant BASE_ADDR_LOW: integer := 2;
constant RANGE1_BITS : integer := 2;
-- functions defining range
function range0_high(sel : integer) return integer is
begin
case sel is
when 0 => return BASE_ADDR_LOW+1;
when 1 => return BASE_ADDR_LOW+3; -- updated to +3 to get a 5 (!)
when others => return BASE_ADDR_LOW; -- default
end case;
end function;
function range1_low(sel : integer) return integer is
begin
return range0_high(sel)+2; -- default
end function;
function range1_high(sel : integer) return integer is
begin
case sel is
when 0 => return range1_low(sel)+RANGE1_BITS-1;
when 1 => return range1_low(sel); -- updated to empty range (!)
when others => return range1_low(sel)+RANGE1_BITS; -- default
end case;
end function;
-- all multiplexer data inputs
constant N : positive := 2**SEL_BITS;
type t_mux_data_in is array(natural range <>) of std_logic_vector(selected_range'range);
signal mux_data_in : t_mux_data_in(0 to N-1);
begin
-- build multiplexer data inputs
genDataIn: for i in 0 to N-1 generate
constant r1_low : integer := range1_low(i);
constant r1_high: integer := range1_high(i);
begin
genHighEmpty: if r1_low = r1_high generate
mux_data_in(i) <= counter(range0_high(i) downto 0);
end generate;
genHigh: if r1_low /= r1_high generate
mux_data_in(i) <= counter(r1_high downto r1_low) & counter(range0_high(i) downto 0);
end generate;
end generate;
-- the multiplexer
selected_range <= mux_data_in(to_integer(unsigned(sel)));
end architecture;