2014-02-24 53 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