2014-02-24 54 views
1

描述: 我想写一个带有4个输入和3个输出的LUT(Look Up Table)的VHDL模块。我想我的3位输出是一个二进制数,等于输入中1的个数。VHDL LUT模块的设计

我的真值表:

ABCD | XYZ
0000 | 000
0001 | 001
0010 | 001
0011 | 010
0100 | 011
0101 | 010
0110 | 010
0111 | 011
1000 | 001
1001 | 010
1010 | 010
1011 | 011
1100 | 010
1101 | 011
1110 | 011
1111 | 100

我的VHDL代码:

library IEEE; 
use IEEE.STD_LOGIC_1164.all; 

entity lut is 
Port (
a : in STD_LOGIC; 
b : in STD_LOGIC; 
c : in STD_LOGIC; 
d : in STD_LOGIC; 
x : out STD_LOGIC; 
y : out STD_LOGIC; 
z : out STD_LOGIC); 

end lut; 

architecture Behavioral of lut is 
signal s0: STD_LOGIC; 
signal s1: STD_LOGIC; 
signal s2: STD_LOGIC; 
signal s3: STD_LOGIC; 
signal s4: STD_LOGIC; 
signal s5: STD_LOGIC; 
signal s6: STD_LOGIC; 
signal s7: STD_LOGIC; 
signal s8: STD_LOGIC; 
signal s9: STD_LOGIC; 
signal s10: STD_LOGIC; 
signal s11: STD_LOGIC; 
signal s12: STD_LOGIC; 
signal s13: STD_LOGIC; 

begin 
----------MUX1----------- 
process(a,b) 
begin 
if a='0' 
then s0<=a; 
else 
s0<=b; 
end if; 
end process; 

--------MUX2---------- 
process(a,b) 
begin 
if a='0' 
then s1<=a; 
else 
s1<=b; 
end if; 
end process; 

---------MUX3----------- 
process(a,b) 
begin 
if a='0' 
then s2<=a; 
else 
s2<=b; 
end if; 
end process; 
---------MUX4----------- 
process(a,b) 
begin 
if a='0' 
then s3<=a; 
else 
s3<=b; 
end if; 
end process; 
---------MUX5----------- 
process(c,d,a) 
begin 
if a='0' 
then s4<=c; 
else 
s4<=d; 
end if; 
end process; 
---------MUX6----------- 
process(c,d,a) 
begin 
if a='0' 
then s5<=c; 
else 
s5<=d; 
end if; 
end process; 
---------MUX7----------- 
process(c,d,a) 
begin 
if a='0' 
then s6<=c; 
else 
s6<=d; 
end if; 
end process; 
---------MUX8----------- 
process(c,d,a) 
begin 
if a='0' 
then s7<=c; 
else 
s7<=d; 
end if; 
end process; 
---------MUX9----------- 
process(s0,s1,b) 
begin 
if b='0' 
then s8<=s0; 
else 
s8<=s1; 
end if; 
end process; 
---------MUX10----------- 
process(s2,s3,b) 
begin 
if b='0' 
then s9<=s2; 
else 
s9<=s3; 
end if; 
end process; 
---------MUX11----------- 
process(s4,s5,b) 
begin 
if b='0' 
then s10<=s4; 
else 
s10<=s5; 
end if; 
end process; 
---------MUX12----------- 
process(s6,s7,b) 
begin 
if b='0' 
then s11<=s6; 
else 
s11<=s7; 
end if; 
end process; 
---------MUX13----------- 
process(s8,s9,c) 
begin 
if c='0' 
then s12<=s8; 
x<= s8; 
else 
s12<=s9; 
x<= s9; 
end if; 
end process; 
---------MUX14----------- 
process(s10,s11,c) 
begin 
if c='0' 
then s13<=s10; 
z<=s10; 
else 
s13<=s11; 
z<=s11 
end if; 
end process; 
---------MUX15----------- 
process(s12,s13,d) 
begin 
if d='0' 
then y<=s12; 
else 
y<=s13; 
end if; 
end process; 
end Behavioral; 

假设: 我需要总共15个多路复用器来模拟我需要的东西。他们将被级联到一个输出。 我将总共有15个过程如上所示。

问题:
1.)我对多路复用器ABCD有什么选择?
2.)我的建模是否正确?我会从所给的信息中获得我想要的吗?
3.)如果有更好的方法或者您有不同的想法,请您提供一个例子吗?
4.)我没有得到我的xyz输出,它的结束,但我做错了什么?

我试图提供尽可能多的研究。如果您有任何问题,我会立即回复

+1

你的真值表有ABCD和XYZ。为什么你的VHDL代码没有X,Y或Z,而是有S1,F,G和H?另外,为什么你认为你需要在LUT实现中使用任何'inout'端口? – wjl

+0

你的权利我没有改变,因为我正在玩选择。无论如何,我现在改变了。我不需要在港口。那么,我正在努力去做什么,或者我会怎么做呢? – user2444074

回答

2

我打算在这边出去,告诉你让你的合成器优化它。除此之外,您可以在桌上使用最小化程序(例如espresso),然后以VHDL编码结果。

我猜这应该把目标定在FPGA时,你应该做的:

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.numeric_std.all; 

entity bit_count is 
    port (
     a,b,c,d: in std_logic; 
     x,y,z:  out std_logic  
    ); 
end entity; 

architecture lut of bit_count is 
    subtype lutin is std_logic_vector (3 downto 0); 
    subtype lutout is std_logic_vector (2 downto 0); 
    type lut is array (natural range 0 to 15) of lutout; 
    constant bitcount: lut := (
     "000", "001", "001", "010", 
     "011", "010", "010", "011", 
     "001", "010", "010", "011", 
     "010", "011", "011", "100" 
     ); 

    signal temp: std_logic_vector (2 downto 0); 

begin 

    temp <= bitcount(TO_INTEGER (unsigned (lutin'(a&b&c&d)))); 

    (x, y, z) <= lutout'(temp(2), temp(1), temp(0)); 

end architecture; 

和失败,我认为一方面优化它作为一个ROM很可能是接近门数方面:

-- 0000 0001 0010 0011 
-- "000", "001", "001", "010", 
-- 0100 0101 0110 0111 
-- "011", "010", "010", "011", 
-- 1000 1001 1010 1011 
-- "001", "010", "010", "011", 
-- 1100 1101 1110 1111 
-- "010", "011", "011", "100" 

-- output   Input 
----------------------- 
-- bit 0 is true 0001 0010 0100 0111 1000 1011 1101 1111 
-- bit 1   0011 0100 0101 0110 0111 1001 1010 1011 1100 1101 1110 
-- bit 2   1111 

architecture rom of bit_count is 

    signal t0,t1,t2: std_logic; 
    signal t4,t7,t8: std_logic; 
    signal t11,t13,t14: std_logic; 
    signal t15:   std_logic; 

begin 
-- terms 
    t0 <= not a and not b and not c and not d; 
    t1 <=  a and not b and not c and not d; 
    t2 <= not a and  b and not c and not d; 
-- t3 <=  a and  b and not c and not d; 
    t4 <= not a and not b and  c and not d; 
-- t5 <=  a and not b and  c and not d; 
-- t6 <= not a and  b and  c and not d; 
    t7 <=  a and  b and  c and not d; 
    t8 <= not a and not b and not c and  d; 
-- t9 <=  a and not b and not c and  d; 
-- t10 <= not a and  b and not c and  d; 
    t11 <=  a and  b and not c and  d; 
-- t12 <= not a and not b and  c and  d; 
    t13 <=  a and not b and  c and  d; 
    t14 <= not a and  b and  c and  d; 
    t15 <=  a and  b and  c and  d; 

-- outputs 

    x <= t15; 

    y <= not (t0 or t1 or t2 or t8 or t15); 

    Z <= t1 or t2 or t4 or t7 or t8 or t11 or t13 or t14; 

end architecture; 

它应该比你的链接多路复用器更少的门,并且有点平坦(更快)。

这两个体系结构已被分析,但没有被模拟。进行手动门级编码时很容易出错。

+0

我喜欢上面的代码,我不知道我是否全部遵守。我会更多地看看发生了什么。谢谢 – user2444074

4

除非你只是在VHDL中玩耍或学习,如果你想要一个LUT,直接把它写成一个LUT。可能没有理由将其解开为低级门和多路复用器。相反,简单介绍一下你想要的行为,并让VHDL做的工作适合你:

例如,这里是你所描述的组合逻辑LUT简单VHDL:

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.numeric_std.all; 

entity Number_of_Ones is 
    port (
     --- mapped 3=a, 2=b, 1=c, 0=d 
     abcd : in std_ulogic_vector(3 downto 0); 
     -- mapped x=2, y=1, z=0 
     xyz : out std_ulogic_vector(2 downto 0); 
    ); 
end entity; 

architecture any of Number_of_Ones is 
begin 

    process (abcd) is 
    begin 
     case abcd is  
     --abcd|xyz 
     when "0000" => xyz <= "000"; 
     when "0001" => xyz <= "001"; 
     when "0010" => xyz <= "001"; 
     when "0011" => xyz <= "010"; 
     when "0100" => xyz <= "011"; 
     when "0101" => xyz <= "010"; 
     when "0110" => xyz <= "010"; 
     when "0111" => xyz <= "011"; 
     when "1000" => xyz <= "001"; 
     when "1001" => xyz <= "010"; 
     when "1010" => xyz <= "010"; 
     when "1011" => xyz <= "011"; 
     when "1100" => xyz <= "010"; 
     when "1101" => xyz <= "011"; 
     when "1110" => xyz <= "011"; 
     when "1111" => xyz <= "100"; 
     end case; 
    end process; 
end architecture; 

正如你所看到的,这正是您复制的真值表,并且只是修改为符合VHDL语法。你当然可以用几种不同的方式写这个,你可能希望以不同的方式映射端口,但这应该让你走上正确的轨道。

+0

我非常喜欢上面的示例。我只是在学习vhdl,我认为我不得不将这个解释成较低层次的东西,但我明白了你的观点。谢谢 – user2444074

4

作为另一个“信任工具”的答案,如果你想数一数,就这么做。您的代码将更加清晰和合成器将它的一个非常好的工作:

process(clk) 
    variable count : unsigned(xyz'range) 
begin 
    if rising_edge(clk) then 
    count := (others => '0'); 
    for i in abcd'range loop 
     if abcd(i) = '1' then 
      count := count + 1; 
     end if; 
    end loop; 
    xyz <= count; 
    end if; 
end process; 

我还没有编译或模拟的这一点,但它应该给你的想法。当然,全代码 - 清晰度,您可以将count/loop方面封装在名为count_ones的函数中,并从该过程中调用该函数。

+3

+1清晰简洁。除非您发现这些工具可怕地综合了您的设计,否则功能/行为方法几乎总是更容易维护。 – Josh

+2

使用这种直接算法风格的另一个原因是原始帖子真值表中的条目:'0100 | 011'。没有人看到超过2年的错误! – wjl