您當前的位置:首頁 > 書法

IC設計例項解析之"Memory"

作者:由 晶片驗證工程師 發表于 書法時間:2019-05-06

//源自微信公眾號 “數字晶片實驗室”

為了

建模

memory,Verilog提供了對

二維陣列

的支援,透過宣告暫存器陣列來建模memory的

行為模型

。可以使用陣列中的索引訪問陣列中的任何資料。

例如:

reg [wordsize:0] array_name [0:arraysize]

這裡

wordsizes

是memory的寬度,

arraysize

是memory的深度:

我們可以透過:

my_memory [address] = data_in

data_out = my_memory [address]

來分別對memory進行資料儲存和讀取

有時候,可能只需要讀取或寫入

某個資料中的一位

,這是就需要進行以下操作:

data_out = my_memory [address];

data_out_it_0 = data_out [0];

我們可以使用系統任務$

readmemb

和$

readmemh

,透過從磁碟讀取

memory檔案

來初始化memory。

$ readmemb用於讀取二進位制表示的memory,$ readmemh用於讀取十六進位制表示的memory。

$ readmemh(“FILE_NAME”,mem_array,start_addr,stop_addr),其中start_addr和stop_addr是可選的。

示例 - 簡單的memory

module memory();

reg [7:0] my_memory [0:255];

initial begin

$readmemh(“memory。list”, my_memory);

end

endmodule

其中memory.list中內容為:

1 //Comments are allowed

2 1100_1100 // This is first address i。e 8‘h00

3 1010_1010 // This is second address i。e 8’h01

4 @ 55 // Jump to new address 8‘h55

5 0101_1010 // This is address 8’h55

6 0110_1001 // This is address 8‘h56

IC設計例項解析之"Memory"

上圖是同步SRAM的Verilog模組。該同步SRAM可儲存8個8位資料。同步SRAM模組由8位資料輸入dataIn和8位資料輸出dataOut組成。該模組使用8位地址線Addr來定位

memory

陣列中資料位元組的位置。利用8位地址線,可以定址深度為256的SRAM。但在本例中,為了簡單起見,設計了一個深度為8的SRAM。該模組使用1位輸入時鐘線Clk進行時鐘控制。該模組還具有1位片選線CS。

1位RD訊號用於指示同步SRAM上的資料讀操作,1位WE訊號用於指示同步SRAM上的資料寫操作。 RD和WE線均為

高電平

有效。

module syncRAM( dataIn,

dataOut,

Addr,

CS,

WE,

RD,

Clk

);

// parameters for the width

parameter ADR = 8;

parameter DAT = 8;

parameter DPTH = 8;

//ports

input [DAT-1:0] dataIn;

output reg [DAT-1:0] dataOut;

input [ADR-1:0] Addr;

input CS,

WE,

RD,

Clk;

//internal variables

reg [DAT-1:0] SRAM [DPTH-1:0];

always @ (posedge Clk)

begin

if (CS == 1’b1) begin

if (WE == 1‘b1 && RD == 1’b0) begin

SRAM [Addr] = dataIn;

end

else if (RD == 1‘b1 && WE == 1’b0) begin

dataOut = SRAM [Addr];

end

else;

end

else;

end

endmodule

下面是例項SRAM的Testbench:

`timescale 1ns / 1ps

module syncRAM_tb;

// Inputs

reg [7:0] dataIn;

reg [7:0] Addr;

reg CS;

reg WE;

reg RD;

reg Clk;

// Outputs

wire [7:0] dataOut;

// Instantiate the Unit Under Test (UUT)

syncRAM uut (

。dataIn(dataIn),

。dataOut(dataOut),

。Addr(Addr),

。CS(CS),

。WE(WE),

。RD(RD),

。Clk(Clk)

);

initial begin

// Initialize Inputs

dataIn = 8‘h0;

Addr = 8’h0;

CS = 1‘b0;

WE = 1’b0;

RD = 1‘b0;

Clk = 1’b0;

// Wait 100 ns for global reset to finish

#100;

// Add

stimulus here

dataIn = 8‘h0;

Addr = 8’h0;

CS = 1‘b1;

WE = 1’b1;

RD = 1‘b0;

#20;

dataIn = 8’h0;

Addr = 8‘h0;

#20;

dataIn = 8’h1;

Addr = 8‘h1;

#20;

dataIn = 8’h10;

Addr = 8‘h2;

#20;

dataIn = 8’h6;

Addr = 8‘h3;

#20;

dataIn = 8’h12;

Addr = 8‘h4;

#40;

Addr = 8’h0;

WE = 1‘b0;

RD = 1’b1;

#20;

Addr = 8‘h1;

#20;

Addr = 8’h2;

#20;

Addr = 8‘h3;

#20;

Addr = 8’h4;

end

always #10 Clk = ~Clk;

endmodule

IC設計例項解析之"Memory"

在FPGA和ASIC中,通常會設計中例項化RAM,但是這樣你的HDL程式碼就無法移植和可重用。

FPGA相關工具提供自動識別RAM的功能,可以根據需要綜合出可以推斷

distributed RAM或者Block RAM

。涵蓋了RAM的同步寫入、使能、非同步或同步讀取、資料輸出鎖存、復位、單埠,雙埠讀寫等型別

綜合出的RAM型別取決於其RTL描述。

以下是綜合出各種型別RAM的Verilog模板:

具有非同步讀取的單埠RAM:

IC設計例項解析之"Memory"

module raminfr (clk, we, a, di, do);

input clk

input we;

input [4:0] a;

input [3:0] di;

output [3:0] do;

reg [3:0] ram [31:0];

always @(posedge clk) begin

if (we)

ram[a] <= di;

end

assign do = ram[a];

endmodule

具有“虛假”同步讀取的單埠RAM

IC設計例項解析之"Memory"

module raminfr (clk, we, a, di, do);

input clk;

input we;

input [4:0] a;

input [3:0] di;

output [3:0] do;

reg [3:0] ram [31:0];

reg [3:0] do;

always @(posedge clk) begin

if (we)

ram[a] <= di;

do <= ram[a];

end

endmodule

具有同步讀取的單埠RAM

IC設計例項解析之"Memory"

module raminfr (clk, we, a, di, do);

input clk;

input we;

input [4:0] a;

input [3:0] di;

output [3:0] do;

reg [3:0] ram [31:0];

reg [4:0] read_a;

always @(posedge clk) begin

if (we)

ram[a] <= di;

read_a <= a;

end

assign do = ram[read_a];

endmodule

具有使能功能的單埠RAM

IC設計例項解析之"Memory"

module raminfr (clk, en, we, a, di, do);

input clk;

input en;

input we;

input [4:0] a;

input [3:0] di;

output [3:0] do;

reg [3:0] ram [31:0];

reg [4:0] read_a;

always @(posedge clk) begin

if (en)

begin

if (we)

ram[a] <= di;

read_a <= a;

end

end

assign do = ram[read_a];

endmodule

具有非同步讀取功能的雙埠RAM

IC設計例項解析之"Memory"

module raminfr

(clk, we, a, dpra, di, spo, dpo);

input clk;

input we;

input [4:0] a;

input [4:0] dpra;

input [3:0] di;

output [3:0] spo;

output [3:0] dpo;

reg [3:0] ram [31:0];

always @(posedge clk) begin

if (we)

ram[a] <= di;

end

assign spo = ram[a];

assign dpo = ram[dpra];

endmodule

一個使能控制兩個讀埠的雙埠RAM

IC設計例項解析之"Memory"

Verilog

module raminfr

(clk, en, we, addra, addrb, di, doa, dob);

input clk;

input en;

input we;

input [4:0] addra;

input [4:0] addrb;

input [3:0] di;

output [3:0] doa;

output [3:0] dob;

reg [3:0] ram [31:0];

reg [4:0] read_addra;

reg [4:0] read_addrb;

always @(posedge clk) begin

if (ena)

begin

if (wea)

ram[addra] <= di;

read_aaddra <= addra;

read_aaddrb <= addrb;

end

end

assign doa = ram[read_addra];

assign dob = ram[read_addrb];

endmodule

雙埠RAM,使能控制每個埠

IC設計例項解析之"Memory"

module raminfr

(clk,ena,enb,wea,addra,addrb,dia,doa,dob);

input clk;

input ena;

input enb;

input wea;

input [4:0] addra;

input [4:0] addrb;

input [3:0] dia;

output [3:0] doa;

output [3:0] dob;

reg [3:0] ram [31:0];

reg [4:0] read_addra;

reg [4:0] read_addrb;

always @(posedge clk) begin

if (ena)

begin

if (wea)

ram[addra] <= dia;

read_addra <= addra;

end

if (enb)

read_addrb <= addrb;

end

assign doa = ram[read_addra];

assign dob = ram[read_addrb];

endmodule

多埠RAM

多埠RAM的不同讀埠訪問不同地址的RAM內容。 但是,只能有一個寫埠。

IC設計例項解析之"Memory"

Verilog

module raminfr

(clk, we, wa, ra1, ra2, di, do1, do2);

input clk;

input we;

input [4:0] wa;

input [4:0] ra1;

input [4:0] ra2;

input [3:0] di;

output [3:0] do1;

output [3:0] do2;

reg [3:0] ram [31:0];

always @(posedge clk) begin

if (we)

ram[wa] <= di;

end

assign do1 = ram[ra1];

assign do2 = ram[ra2];

endmodule

我們可以對FPGA進行屬性約束,以便綜合出distributed RAM或者Block RAM。

標簽: input  RAM  CLK  REG  di