顯示具有 VHDL 標籤的文章。 顯示所有文章
顯示具有 VHDL 標籤的文章。 顯示所有文章

2015年11月22日 星期日

VHDL read bmp image

Reference:
the same as in the reference, just only read

package 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

package bmp_read_package is
 
 constant cMAX_X : integer := 1300; -- 1280
 constant cMAX_Y : integer := 1300; -- 1024
 constant cBytesPerPixel : integer := 3;
 
 constant cMaxMemSize : integer := cMAX_X * cMAX_Y * cBytesPerPixel;

 subtype bmp_element is std_logic_vector(7 downto 0);
 type mem_array is array(cMaxMemSize downto 0) of bmp_element;
 type header_array is array(53 downto 0) of bmp_element;
 
 procedure ReadFile(FileName : in string);
 procedure ReadByteFromMemory(addr : in integer; variable data: out std_logic_vector(7 downto 0));
 
 function GetWidth(header        : in  header_array) return integer;
 procedure GetWidth(signal width : out integer);

 function GetHeight(header         : in  header_array) return integer;
 procedure GetHeight(signal height : out integer);
 
 procedure GetPixel(x : in integer; y : in integer; signal data : out std_logic_vector(23 downto 0));
 
end package bmp_read_package;

package body bmp_read_package is 

 shared variable memory_in : mem_array;
 shared variable memory_out : mem_array;
 shared variable header   : header_array;
 shared variable BmpSize   : integer;
 shared variable BmpWidth  : integer;
 shared variable BmpHeight  : integer;
 
 procedure ReadFile(FileName : in string) is
  variable next_vector : bit_vector(0 downto 0);
  variable actual_length : natural;
  variable index   : integer := 0;
  type bit_vector_file is file of bit_vector;
  file read_file   : bit_vector_file open read_mode is FileName;
  
 begin 
  report " Read File";
  report FileName;
  
  index := 0;
  
  report " Read Header";
  for i in 0 to 53 loop 
   read(read_file,next_vector,actual_length);
   if actual_length > next_vector'length then 
    report " vector too long";
   else 
    header(index) := conv_std_logic_vector(bit'pos(next_vector(0)),8);
    index    := index + 1 ;
   end if;
  end loop;

  BmpWidth  := GetWidth(header);
  BmpHeight  := GetHeight(header);
  BmpSize  := BmpWidth * BmpHeight;
 
  report " Read Image";
  index := 0;
  while not endfile(read_file) loop
   read(read_file,next_vector,actual_length);
   if actual_length > next_vector'length then 
    report " vector too long";
   else 
    memory_in(index) := conv_std_logic_vector(bit'pos(next_vector(0)),8);
    memory_out(index) := x"45";
    index := index + 1;
   end if;
  end loop;
  
  report "Okay";
 END ReadFile;
 
 procedure ReadByteFromMemory(addr : in integer; variable data : out std_logic_vector(7 downto 0)) is 
 begin 
  data := memory_in(addr);
 end ReadByteFromMemory;
 
 procedure GetPixel(x : in integer; y : in integer; signal data : out std_logic_vector(23 downto 0)) is
 begin 
  if( x >= 0 and x < cMAX_X ) and ( y >= 0 and y < cMAX_Y ) then 
   data(23 downto 16) <= memory_in(x*3 + 3*y*GetWidth(header));
   data(15 downto 8)  <= memory_in(x*3+1 + 3*y*GetWidth(header));
   data(7 downto 0)   <= memory_in(x*3+2 + 3*y*GetWidth(header));
     end if;
 end GetPixel;
 
    -- Get Width of Image
    function GetWidth(header : in header_array) return integer is
    begin
      return conv_integer(header(21) & header(20) & header(19) & header(18));
    end function GetWidth;
    
    procedure GetWidth(signal width : out integer) is
    begin
      width <= BmpWidth;
    end GetWidth;
    
    -- Get Height of Image
    function GetHeight(header : in header_array) return integer is
    begin
      return conv_integer(header(25) & header(24) & header(23) & header(22));
    end function GetHeight;
    
    procedure GetHeight(signal height : out integer) is
    begin
      height <= BmpHeight;
    end GetHeight;
 
end bmp_read_package;



2014年10月14日 星期二

8 Bits Sequence Detector

練習寫了一個Sequence Detector
網路上的範例大多都是四個bit
我練習寫了一個8 bit
對於每個state的轉換,其實不是百分之百的確定
只是寫了一些變化的testbench來測
如果遇到其他多元化的情形,FSM一定是需要再修改的

Sequence 10101100


VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity seq_det is
port(
clk   : in std_logic;  
reset : in std_logic;
enable : in std_logic;
seq_in   : in std_logic;    
seq_detected : out std_logic);  
end seq_det;
---- Pattern 10101100---------

architecture Behavioral of seq_det is

type state_type is (IDLE,S1,S2,S3,S4,S5,S6,S7,S8,S9);
signal cur_state, nxt_state : state_type;
signal seq_det,seq_det_w : std_logic;
begin

seq_detected <= seq_det;



process(clk)
begin
    if( reset = '1' ) then              
        cur_state <= IDLE;
 seq_det <= '0';
    elsif (clk'event and clk = '1') then
        cur_state <= nxt_state;
 seq_det <= seq_det_w;
    end if;
end process;


Process(cur_state,seq_in,enable)
    begin
        case cur_state is

            when IDLE =>                    
                seq_det_w <= '0';
 if( enable = '1') then
if ( seq_in = '1' ) then
nxt_state <= S1;
else  
nxt_state <= IDLE;
end if;
else
       nxt_state <= IDLE;
end if;

            when S1 => -- 1
                seq_det_w <= seq_det;
                if ( seq_in = '0' ) then
                    nxt_state <= S2;
                else  
                    nxt_state <= S1;
                end if;

            when S2 => -- 0
                seq_det_w <= seq_det;
                if ( seq_in = '1' ) then
                    nxt_state <= S3;
                else  
                    nxt_state <= IDLE;
                end if;
-
            when S3 => -- 1
                seq_det_w <= seq_det;
                if (seq_in = '0' ) then
                    nxt_state <= S4;
                else  
                    nxt_state <= S1;
                end if;

            when S4 => -- 0
                seq_det_w <= seq_det;
                if ( seq_in = '1' ) then
                    nxt_state <= S5;
                else  
                    nxt_state <= IDLE;
                end if;

when S5 => -- 1
                seq_det_w <= seq_det;
                if ( seq_in = '1' ) then
                    nxt_state <= S6;
                else  
                    nxt_state <= S4;
                end if;

when S6 => -- 1
                seq_det_w <= seq_det;
                if ( seq_in = '0' ) then
                    nxt_state <= S7;
                else  
                    nxt_state <= S1;
                end if;

when S7 => -- 0
                seq_det_w <= seq_det;
                if ( seq_in = '0' ) then
                    nxt_state <= S8;
                else  
                    nxt_state <= S3;
                end if;

when S8 => -- 0
                seq_det_w <= '1';
                if ( seq_in = '1' ) then
                    nxt_state <= S1;
                else  
                    nxt_state <= IDLE;
                end if;


            when others =>
                NULL;
        end case;
end process;  


end Behavioral;





2014年10月10日 星期五

VHDL 觀念釐清

hardware.html
http://www.synthworks.com/papers/vhdl_math_tricks_mapld_2003.pdf
http://www.csd.nutn.edu.tw/VHDL/CH4.pdf

RTL (Register Transfer level)
Rising_edge(clk) & clk'event and clk = '1'
如果clk正常工作的話兩個都可以正常使用,但是如果clk在低電位時為unknown,使用clk'event and clk = '1' 會造成沒有訊號,Rising_edge(clk)正常,rising_edge has a few extra checks built-in to make sure that you actually have an edge.,Use Rising_edge(clk) instead of clk'event and clk = '1'


std_logic,std_logic_vector & bit,bit_vector
bit : 只能用來代表'0' or '1'
std_logic : 可以用來代表七種資料型態,包括
U’(Uninitialized)
X’(Forcing Unknown)
0’(Forcing 0)
1’(Forcing 1)
Z’(High Impedance)
W’(Weak Unkonwn)
L’(Weak 0)
H’(Weak 1)
-‘(Don’t Care)

所以在程式中當確定訊號只會為0或是1的時候即可以用bit,在某些shift operator中無法使用
std_logic_vector,所以可以使用下列的函式來轉換,不用另外加library,已經在std_logic_1164

"To_bit"
"To_bitvector"
"To_StdLogic"
"To_StdLogicvector"
"To_StdULogic"
"To_StdULogicvector"

integer,signed,unsigned 轉換(Xilinx)

use IEEE.NUMERIC_STD.ALL;
<signed_sig> = TO_SIGNED(<int_sig>, <integer_size>); – integer to signed
<unsigned_sig> = TO_UNSIGNED(<int_sig>, <integer_size>); – integer to unsigned
<int_sig> = TO_INTEGER(<signed_sig>); – signed to integer
<int_sig> = TO_INTEGER(<unsigned_sig>); – unsigned to integer

Delay

Delta Delay
In VHDL simulations, all signal assignments occur with some infinitesimal delay, known as delta delay. Technically, delta delay is of no measurable unit, but from a hardware design perspective one should think of delta delay as being the smallest time unit one could measure, such as a femtosecond (fs).
這是每級預設的最小延遲
慣性延遲(inertial delay model)
可以用在程式當中,但是synthesis後會被optimized, Inertial delay is basically a default component delay
a <= b after 1ns;
wait for time expressions
wait on signal
wait until condition
wait;
這些都是不能合成的,最好只用在testbench裡面
傳遞延遲
通常用在testbench的輸入輸出,Transport delay basically represents a wire delay.

a <= transport b after 1ns;

Concurrent & Sequential Statements


Concurrent為共時性敘述,每個processblock之間為Concurrent
Sequential 為順序性敘述,process內的為Sequential



Signal & Variable


signal assignment statement Target物件 <= 表示式;
variable assignment statement Target物件 := 表示式;

Signal variable都可以指定初始值



Signal 不可以重複設定,可以用在package,entity,architecture,ports
Signal只有在process,procedure,function順時執行到時才會改變資料



variable可以重複設定,可以用在process,procedure,function
variable資料隨時可被更新
模擬時無法看到variablewaveform

Subtypes

次資料型別係用來表示一個資料型別的子集合 (Sub-Sets)

subtype SUBTYPE_NAME is TYPE_NAME [範圍宣告];

次資料型別的宣告,由一個關鍵字subtypeSUBTYPE來表示。之後的識別字為次資料型別
的名稱。關鍵字的後面的識別字用來表示所使用的原始資料型別。最後所宣告的範圍限制,
乃是對次資料型別所局限的範圍做一個定義

SUBTYPE First_ten IS INTEGER RANGE 0 to 9;

有兩種場合,需要使用到次資料型別:
(1)在訊號指定或Case指定的命令列中加以限制其資料的範圍,以控制電路合成的結果。
(2)建立一個解值(Resolved)的資料型別。


Function & Procedure
function可以用來做一些常用的數學運算,但是只能回傳一個值
Procedure function最大的差別在於它可以回傳一個以上的值,而且可以不同型態

array and records types

array types,一組資料物件
陣列資料物件中的元素,可以使用陣列的指標(Index) 來指定陣列中指定位置的元素
type BYTE is array (0 to 7) of bit;
陣列資料型別,通常使用在線性結構的一組資料中,也可以用來表示多維的陣列資料型別
也可以在使用的時候,不宣告其元素的方式來使用,增加程式設計上的彈性

records types,一組不同的資料物件所組合而成
記錄資料型別,係由一組不同的資料物件所組合而成的資料型別,而陣列中的每一個元素可
以是任意的資料型別。
# 在記錄型別內的每一個元素,都可以用一個名稱來加入設定或指定。
# VHDL電路設計語言中的記錄資料型別類似於C語言中的結構(Structure)。記錄資料型別
內的每一個元素,可以是任意的資料型別,也包含陣列資料型別與記錄資料型別均可用來當
作記錄資料型別內的元素。

type OPTYPE is (ADD, SUB, JMP);
type INSTRUCT is
record
OPCODE: OPTYPE;
SOURCE: integer;
DESTINATION: integer;
end record;




2014年9月5日 星期五

4 Bits Pattern detector

Pattern detector

這個例子是用casez來做判斷,verilog,casez的好處就是可以不用在乎其它bit的狀態,所以拿這個來當pattern detector,但是這只能用在FPGA,不能做成ASIC,如果要做成ASIC理論上示要寫FSM,但是如果要找的pattern 很大,那真的會令人崩潰阿阿阿阿!

因為casez只有在verilog中有,所以我在寫一層top layer來包,duplicate data表式上層收集下來的資料連接而成,因為兩個連續的資料中一定會有我們要找的pattern在中間,但是這個casez我發現在duplicate_datapattern前需要都為零才能偵測到,例如pattern1101,duplicate資料需為00011010,如果是10011010則會找不到,這點我還沒想通為什麼 T_T

ps. detect_pos是用來指出偵測到的位置在哪裡,然後取後面的資料當作detected_data,當然也可以把pattern當成id之類,後面接的是資料

pattern_detector_top.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;


entity pattern_detector_top is
Port (
t_clk : in STD_LOGIC;
t_reset : in STD_LOGIC;
t_enable : in STD_LOGIC;
t_duplicate_data : in STD_LOGIC_VECTOR (7 downto 0);
t_pattern_data : out STD_LOGIC_VECTOR (3 downto 0);
t_pattern_detect : out STD_LOGIC);
end pattern_detector_top;


architecture Behavioral of pattern_detector_top is


begin


u_pattern_detector: entity work.pattern_detector PORT MAP(
clk => t_clk,
reset => t_reset,
enable => t_enable,
duplicate_data => t_duplicate_data,
pattern_data => t_pattern_data,
pattern_detect => t_pattern_detect
);
end Behavioral;


pattern_detector.v
module pattern_detector(
input wire clk,
input wire reset,
input wire enable,
input wire[7:0] duplicate_data,
output reg [3:0] pattern_data,
output reg pattern_detect);




parameter PATTERN = 4'b1101;

reg [3:0] detect_pos;

always @ (posedge clk or posedge reset)
begin
if(reset)
begin
detect_pos <= 4'h1;
pattern_detect <= 1'b0;
end
else
begin
if(!enable)
begin
detect_pos <= 4'h1;
pattern_detect <= 1'b0;
end
else if (!pattern_detect) //
begin
casez (duplicate_data)
{PATTERN, 4'b????}:
begin
detect_pos <=#1 4'h1;
pattern_detect <=#1 1'b1;
end


{1'b?, PATTERN, 3'b???}:
begin
detect_pos <=#1 4'h1 << 1;
pattern_detect <=#1 1'b1;
end


{2'b??, PATTERN, 2'b??}:
begin
detect_pos <=#1 4'h1 << 2;
pattern_detect <=#1 1'b1;
end


{3'b???, PATTERN, 1'b?}:
begin
detect_pos <=#1 4'h1 << 3;
pattern_detect <=#1 1'b1;
end
default:
begin
detect_pos <=#1 detect_pos;
pattern_detect <=#1 pattern_detect;
end
endcase
end
end
end
always @ (posedge clk or posedge reset)
begin
if(reset)
begin
pattern_data <= 4'h0;
end
else if (pattern_detect)
begin
case (1'b1)
detect_pos[0]:
pattern_data <=#1 duplicate_data[7:4];


detect_pos[1]:
pattern_data <=#1 duplicate_data[6:3];


detect_pos[2]:
pattern_data <=#1 duplicate_data[5:2];


detect_pos[3]:
pattern_data <=#1 duplicate_data[4:1];
endcase
end
end


endmodule

pattern_detector_tb.vhd
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY pattern_detector_tb IS
END pattern_detector_tb;

ARCHITECTURE behavior OF pattern_detector_tb IS

-- Component Declaration for the Unit Under Test (UUT)

COMPONENT pattern_detector_top
PORT(
t_clk : IN std_logic;
t_reset : IN std_logic;
t_enable : IN std_logic;
t_duplicate_data : IN std_logic_vector(7 downto 0);
t_pattern_data : OUT std_logic_vector(3 downto 0);
t_pattern_detect : OUT std_logic
);
END COMPONENT;



--Inputs
signal t_clk : std_logic := '0';
signal t_reset : std_logic := '0';
signal t_enable : std_logic := '0';
signal t_duplicate_data : std_logic_vector(7 downto 0) := (others => '0');


--Outputs
signal t_pattern_data : std_logic_vector(3 downto 0);
signal t_pattern_detect : std_logic;


-- Clock period definitions
constant t_clk_period : time := 10 ns;

BEGIN

-- Instantiate the Unit Under Test (UUT)
uut: pattern_detector_top PORT MAP (
t_clk => t_clk,
t_reset => t_reset,
t_enable => t_enable,
t_duplicate_data => t_duplicate_data,
t_pattern_data => t_pattern_data,
t_pattern_detect => t_pattern_detect
);


-- Clock process definitions
t_clk_process :process
begin
t_clk <= '0';
wait for t_clk_period/2;
t_clk <= '1';
wait for t_clk_period/2;
end process;



-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
wait for 3 us;
t_reset <= '1';
wait for 30 ns;
t_reset <= '0';
wait for 3 us;
wait for 22 ns;
t_duplicate_data <= "00000000";
wait for 5 us;
t_enable <= '1';
t_duplicate_data <= "00011011";
wait for 32 ns;
t_duplicate_data <= "10111011";



wait;
end process;


END;


Waveform


Push button Debounce and Synchronization

Referecce : Design Examples ELEC 418 Advanced Digital Systems Dr. Ron Hayne


由於數位電路的動作速度非常快(常以 ns 為計算單位),所以若在電路中使用機械式
的開關(switch)時,就必須考慮開關的彈跳(bounce)問題,因為機械式的開關在轉換狀態(
某一接點投擲至另一接點)的瞬間,會產生多次的彈跳現象,造成電路的錯誤輸出。如圖
6-19 所示的電路,當開關的位置由 A 點投擲至 B (開關內部的金屬簧片撞擊 B 點的金屬
接點)時,雖然投擲後開關內部有彈簧的慣性支撐,但是在硬碰硬(金屬碰金屬)的情況下,
仍會產生多次的彈跳現象,此一過度的現象雖只有幾個毫秒(ms)而已,但對數位電路而
言,如同輸入多個脈波(pulse)的情況,所以當機械式開關的訊號要輸入數位電路時,通常
都會先經過『防彈跳(debounce)』的作用,以確保數位電路能正確獲得輸入訊號;而常見
的防彈跳方法有兩種,一為軟體方式----以延遲讀取的方法,來取得正確的輸入資料,
常用於眾多輸入按鍵的地方,例如電腦鍵盤的資料(掃描碼)讀取,另一則為硬體方式----
以防彈跳電路,來取得正確的輸入資料



將輸入的訊號延遲到下一個register,順便synchronize,在將已經沒有毛刺的訊號合成一個pulse送入電路

testbench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
library UNISIM;
use UNISIM.VComponents.all;

ENTITY PB_DEBOUNCE_SYNC_TB IS
END PB_DEBOUNCE_SYNC_TB;

ARCHITECTURE behavior OF PB_DEBOUNCE_SYNC_TB IS

-- Component Declaration for the Unit Under Test (UUT)

COMPONENT PB_DEBOUNCE_SYNC
PORT(
clk : IN std_logic;
pb_in : IN std_logic;
pb_out : OUT std_logic
);
END COMPONENT;



--Inputs
signal clk : std_logic := '0';
signal pb_in : std_logic := '0';


--Outputs
signal pb_out : std_logic;


-- Clock period definitions
constant clk_period : time := 100 ns;

BEGIN

-- Instantiate the Unit Under Test (UUT)
uut: PB_DEBOUNCE_SYNC PORT MAP (
clk => clk,
pb_in => pb_in,
pb_out => pb_out
);


-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;



-- Stimulus process
stim_proc: process
begin
wait for 48 ns;
pb_in <= '1'; wait for 1 ns;
pb_in <= '0'; wait for 1 ns;
pb_in <= '1'; wait for 1 ns;
pb_in <= '0'; wait for 1 ns;
pb_in <= '1'; wait for 1 ns;
pb_in <= '0'; wait for 1 ns;
pb_in <= '1'; wait for 1 ns;
pb_in <= '0'; wait for 1 ns;
pb_in <= '1'; wait for 1 ns;
pb_in <= '0'; wait for 1 ns;
pb_in <= '1'; wait for 1 ns;
pb_in <= '0'; wait for 1 ns;
pb_in <= '1'; wait for 485 ns;
pb_in <= '0'; wait for 1 ns;
pb_in <= '1'; wait for 1 ns;
pb_in <= '0'; wait for 1 ns;
pb_in <= '1'; wait for 1 ns;
pb_in <= '0'; wait for 1 ns;
pb_in <= '1'; wait for 1 ns;
pb_in <= '0'; wait for 1 ns;
pb_in <= '1'; wait for 1 ns;
pb_in <= '0'; wait for 1 ns;
pb_in <= '1'; wait for 1 ns;
pb_in <= '0';
wait;
end process;


END;



debounce上面還有看到很多不同的寫法,有的可以自己決定要延長多久時間才取突波,這邊也可以把sync加大延遲,然後取另外一種邏輯方式來決定pulse

2014年8月5日 星期二

ROM example VHDL

Reference
xst user guide 10.1


ROM (Read-Only Memory) : 唯讀記憶體
唯讀記憶體是一種半導體記憶體,其特性是一旦儲存資料就無法再將之改變或刪除。通常用在不需經常變更資料的電子或電腦系統中,資料並且不會因為電源關閉而消失。例如早期的個人電腦如Apple IIIBM PC XT/AT的開機程式(作業系統)或是其他各種微電腦系統中的軔體(Firmware)。
唯讀記憶體(Read-Only Memory)是一種只能讀取資料的記憶體。在製造過程中,將資料以一特製光罩(mask)燒錄於線路中,其資料內容在寫入後就不能更改,所以有時又稱為「光罩式唯讀記憶體」(mask ROM)。此記憶體的製造成本較低,常用於電腦中的開機啟動。


Xilinx的範例當中的ROM是用block ram來寫
Single Port ROM



Dual Port ROM





RAM example VHDL

Reference : http://www.altera.com/support/examples/vhdl/vhdl.html

下面的例子是在altera的範例中,在xilinx有更多的範例,如下
http://www.xilinx.com/itp/xilinx10/books/docs/xst/xst.pdf

xilinx裡面的例子跟altera有個小地方不一樣
altera第一個例子定義addressstd_logic_vector 在用兩個函式 to_integer unsigned來轉
注意要使用use IEEE.NUMERIC_STD.ALL;
其他例子定義addressnatural 所以不用另外加入library也不用轉換
xilinx的例子中address定義為std_logic_vector , 只使用函式conv_integer

注意要使用use ieee.std_logic_unsigned.all;

RAM (Random-access memory) : 隨機存取記憶體
隨機存取記憶體,或稱隨機訪問存儲器,是一種在電腦中用來暫時保存資料的元件。它可以隨時讀寫,而且速度很快,通常作為作業系統或其他正在運行中的程式之臨時資料存儲媒介。它可以令電腦的容量提升,不同隨機存取記憶體也有不同的容量。

特點
所謂「隨機存取」,指的是當存儲器中的訊息被讀取或寫入時,所需要的時間與這段資訊所在的位置無關。相對的,存取順序存取(Sequential Access)存儲設備中的資訊時,其所需要的時間與位置就會有關係(如磁帶)。
當電源關閉時RAM不能保留資料。如果需要保存資料,就必須把它們寫入一個長期的儲存設備中(例如硬碟)。RAM和ROM相比,兩者的最大區別是RAM在斷電以後保存在上面的資料會自動消失,而ROM不會。

分類RAM記憶體可以進一步分為靜態隨機存取記憶體(SRAM)和動態隨機存取記憶體(DRAM)兩大類。SRAM具有快速存取的優點,但生產成本較為昂貴,一個典型的應用是快取。而DRAM由於具有較低的單位容量價格,所以被大量的採用作為系統的主記憶體。

Single Clock Synchronous RAM
Ram 使用者寫入addressdata,再寫入要讀的位址,讀的位址可以隨機,讀寫使用相同clock

Ram的寬度為資料寬,深度為24次方(0 TO 2**ADDR_WIDTH)




Single Port RAM, 使用者寫入addressdata, 其會及時的被讀出,使用者不需要輸入讀的位址




Dual Clock Synchronous Ram 使用者寫入addressdata,再寫入要讀的位址,讀的位址可以隨機,讀寫使用不同clock




第一種ramaddress也可以改用natural 的方式,這樣就不用在函式裡面再轉integer

True Dual Port Ram with a single clock

兩個Port共用同一個ram,所以注意原本的ram signal要變成shared variable
而且輸入值的方式也不是用non blocking
xilinx isim不支援variable,所以無法看到ram的波形




更正!
上面全部例子的初始化應該要改成
signal ram_block : RAM := (others => (others => '0'));


如果是block ram 可以設定初始值,也就是說可以當ROM來使用,譬如.....
...
type ram_type is array (0 to 63) of std_logic_vector(19 downto 0);
signal RAM : ram_type :=
(
X"0200A", X"00300", X"08101", X"04000", X"08601", X"0233A",
X"00300", X"08602", X"02310", X"0203B", X"08300", X"04002",
X"08201", X"00500", X"04001", X"02500", X"00340", X"00241",
X"04002", X"08300", X"08201", X"00500", X"08101", X"00602",
X"04003", X"0241E", X"00301", X"00102", X"02122", X"02021",
X"00301", X"00102", X"02222", X"04001", X"00342", X"0232B",
X"00900", X"00302", X"00102", X"04002", X"00900", X"08201",
X"02023", X"00303", X"02433", X"00301", X"04004", X"00301",
X"00102", X"02137", X"02036", X"00301", X"00102", X"02237",
X"04004", X"00304", X"04040", X"02500", X"02500", X"02500",
X"0030D", X"02341", X"08201", X"0400D");

...

Xilinxram當中可以分成兩種Block RAM Distributed RAM,在每個系列中可以使用的大小都不一樣

Distributed RAM :
表示這種RAM是均勻散佈在FPGACLB, 通常它們的資料寬度都為1 bit,如果要應用在較大的設計上,就必須把這些分散的ram連起來(形成parallel array),這樣就會產生較大的delay因此Distributed RAM通常用在小的RAM,其對於timing的要求不高的設計當中

Block RAM :
容量較大,通常會在kbits的等級, 速度較快,但是如果只使用到一部分的bram會造成系統資源的浪費,但如果fpgabram全部被用光也會對性能造成影響,需要在PR上多下點功夫

在程式裡面可以利用attribute來指定fpga用哪種ram
attribute ram_style: string;
attribute ram_style of ram : signal is "distributed";
或是
attribute ram_style: string;
attribute ram_style of ram : signal is "block";


下例使用ditributed RAM 



Synthesis report中可以看到,如果沒有加attribute,系統會自動設為BRAM