2011年3月28日 星期一

out與buffer的迷思

(2) 問題2
我發現VHDL除了out還有buffer,Verilog卻只有output
請問VHDL什麼時候要用out?什麼時候要用buffer?
因為我在棋盤書看到有範例用buffer,所以很好奇他為什麼要用buffer型別?
這與FPGA的output buffer有關嗎?
//========== 以上蕭兄的問題2結束 ==========

首先介紹一本VHDL的入門書
將將----棋盤書

large_cover.jpg

這本書呢, 是我大學時上VHDL時的用書
(但我的封面並不是這樣, 難不成海外版的有差???)
這是本對於初學者學習VHDL的好教材
不僅深入淺出, 還搭配許多圖文並茂的講解
讓你能直覺性地了解VHDL與實際情況的差別
實在是居家旅行, 殺人滅口, 必備良藥
謎之音: 那麼在哪裡才能買得到呢
啊!這位仁兄運氣真好,我這裏正好有一本
(對不起, 本人太入戲了= =......)

out與buffer這兩個冤家
常常會讓Verilog designer搞不清楚
因為它們兩個實在太像了
首先, 它們兩個一定只能用在output端
因為它們都是屬於"輸出屬性"
但既然是"輸出屬性", 又為何定義兩種不同型別呢

我們先來思考一個簡單的狀況
如果您今天的設計, 是需要將output拉回到input端處理
像是計數器之類的
Verilog code將怎麼處理呢???

input clk;
input rst_n;
output [3:0] cnt;
reg [3:0] cnt;

always@(posedge clk, negedge rst_n) begin
    if (~rst_n) 
       cnt <= 4'h0;
    else
       cnt <= cnt + 1'b1;  
    end

(以上的code感謝蕭兄熱情贊助!! ^^)
那麼再看一個小弟的VHDL code

entity counter is
   port ( clk   : in std_logic;
          rst_n : in std_logic;
          cnt   : out std_logic_vector(3 downto 0));
   end counter;
   
architecture beh of counter is
   signal cnt_r : std_logic_vector(3 downto 0);
begin
    process(clk, rst_n) 
    begin
        if (rst_n = '0') then
            cnt_r <= (others => '0');
        elsif clk = '1' and clk 'event then
            cnt_r <= cnt_r + 1;
        end if;
    end process;
    cnt <= cnt_r;
end beh;

看起來是不是差不多呢(幾乎是一模一樣吧...)
很明顯地, 兩者也都有register
(VHDL的register是以signal來實現)
合成出來的RTL也是相同
那麼看倌們也許會問, buffer在哪裡
我們就來看VHDL改成buffer會如何

entity counter is
   port ( clk   : in std_logic;
          rst_n : in std_logic;
          cnt   : buffer std_logic_vector(3 downto 0));
   end counter;
   
architecture beh of counter is
begin
    process(clk, rst_n) 
    begin
        if (rst_n = '0') then
            cnt <= (others => '0');
        elsif clk = '1' and clk 'event then
            cnt <= cnt + 1;
        end if;
    end process;
end beh;

沒錯, signal不見了!!!
但是合出來的RTL確是一樣
這表示什麼呢

簡單而言
若有需要將output的訊號再拉回來做處理的
可以使用buffer來撰寫

當然也可以像第一個VHDL的例子一樣
自行開個signal當register使用

也許你會問
VHDL不會自行分辨是out還是buffer嗎
這個答案是"不會"!!!
因為VHDL很笨
你寫成out, 它就把你當成pad
(這樣就等於從外部拉到input端, 一定會與input的訊號衝突!!!)
你寫成buffer, 它就會開個reg給你
(這樣就變成是internal的訊號回授)
讓你贏莊家一百塊

但在Verilog中, 只有output的型別
是因為我們都會另行宣告reg來跟output接線
而VHDL呢
很抱歉, 你要自己加signal
不然你的十塊錢變不了兩千五百萬...

雖然好用
但在VHDL中這樣的用法
似乎也引來了一些爭議
在Xilinx的網站上也提出關於buffer的一些建議
(http://www.xilinx.com/itp/xilinx4/data/docs/sim/coding4.html)

Do not use buffers when a signal is used internally and as an output port.
In the following VHDL example, signal C is used internally and as an output port.

Entity alu is    
 port( A : in STD_LOGIC_VECTOR(3 downto 0);         
       B : in STD_LOGIC_VECTOR(3 downto 0);         
       CLK : in STD_LOGIC;         
       C : buffer STD_LOGIC_VECTOR(3 downto 0)); 
end alu; 
architecture BEHAVIORAL of alu is 
begin  
process begin      
     if (CLK'event and CLK='1') then         
         C <=   UNSIGNED(A)
+ UNSIGNED(B)
+ UNSIGNED(C); end if; end process; end BEHAVIORAL;

Because signal C is used both internally and as an output port,
every level of hierarchy in your design that connects to port C must be declared as a buffer.
However, buffer types are not commonly used in VHDL designs because they can cause problems during synthesis.
To reduce the amount of buffer coding in hierarchical designs,
you can insert a dummy signal and declare port C as an output, as shown in the following VHDL example.

Entity alu is  
     port( A : in STD_LOGIC_VECTOR(3 downto 0);         
           B : in STD_LOGIC_VECTOR(3 downto 0);         
           CLK : in STD_LOGIC;         
           C : out STD_LOGIC_VECTOR(3 downto 0));    
    end alu; 
 
architecture BEHAVIORAL of alu is 
-- dummy signal 
signal C_INT : STD_LOGIC_VECTOR(3 downto 0); 
begin  
    C <= C_INT;    
    process begin      
         if (CLK'event and CLK='1') then       
           C_INT < =   UNSIGNED(A)
+ UNSIGNED(B)
+ UNSIGNED(C_INT); end if; end process; end BEHAVIORAL;

看到沒, Xilinx是不建議用buffer型別的
(雖然我覺得沒差, 反正我知道怎麼用就好...)
這也是為什麼在ISE中新增source file的時候
GUI的template中沒有buffer的選項

如此, 對於out與buffer在VHDL中的差別
是否更了解了呢???

(還有問題3...待續...)

沒有留言: