用 Verilog 撰寫記憶體

Verilog

基本語法

型態

全域變數

基本元件

多樣的寫法

指定

assign

always

initial

運算式

分枝

迴圈

模組

函數

Task

陣列

輸出入

觀察

真值表

測試程式

訊息顯示

注意事項

模擬程序

硬體工程

程式範例

Xor

Xor3

全加器

加法器

加減器

快速加法器

乘法器

ALU

閂鎖器

脈衝偵測

計數器

多工器

暫存器群

記憶體

延遲問題

浮點數

狀態機

程式計數器

CPU0-Mini

CPU0

pipeline

工具

QuartusII

Icarus

Veritek

訊息

相關網站

參考文獻

最新修改

簡體版

English

設計方案

記憶體模組:memory.v

module memory(input clock, reset, en, r_w, 
 input [7:0] abus, input [7:0] dbus_in, output [7:0] dbus_out);
reg [7:0] m [0:128];
reg [7:0] data;
reg [7:0] i;

    always @(posedge clock) 
    begin
        if (reset == 1)
        begin
            m[0] <= 8'h00;
            m[1] <= 8'h01;
            m[2] <= 8'h02;
            m[3] <= 8'h03;
            m[4] <= 8'h04;
            data = 8'h00;
        end
        else if (en == 1 && r_w == 0) // r_w==0:write
        begin
            data = dbus_in;
            m[abus] = dbus_in;
        end
        else if (en == 1 && r_w == 1) // r_w==1:read
            data = m[abus];
        else
            data = 8'hZZ;
    end
    assign dbus_out = data;
endmodule

記憶體測試程式:memoryTest.v

`timescale 1ns/10ps

module memoryTest;
reg clock, reset, en, r_w;
reg [7:0] addr;
reg [7:0] data_in;
wire [7:0] dbus_out;

memory DUT (.clock(clock), .reset(reset), .en(en), .r_w(r_w), 
   .abus(addr), .dbus_in(data_in), .dbus_out(dbus_out));

initial // reset:設定 memory 內容為 0,1,2,....,127
begin
  clock = 0;
  reset = 1;
  en = 0;
  r_w = 1; // r_w=1:讀取模式
  #75;
  en = 1;
  reset = 0;
  addr = 0;
  #500;
  addr = 1;
  r_w = 0; // 寫入模式
  data_in = 8'h3A;
  #100;
  addr = 0;
  r_w = 1; // 讀取模式
  data_in = 0;
end

always #50 clock = clock + 1; 

always #200 
begin
 addr=addr+1;
end

endmodule

執行結果:memoryTest 測試程式的結果

memoryTestRun.jpg

參考方案:

方案一

module ram(input clock, reset, en, r_w, 
                input [7:0] abus, inout [7:0] dbus);
reg [7:0] m [0:128];
reg [7:0] data;
reg [7:0] i;

    always @(posedge clock) 
    begin
        if (reset == 1)
        begin
            m[0] <= 8'h00;
            m[1] <= 8'h01;
            m[2] <= 8'h02;
            m[3] <= 8'h03;
            m[4] <= 8'h04;
            data = 8'hZZ;
        end
        else if (en == 1 && r_w == 0) // r_w==0:write
        begin
            data = dbus;
            m[abus] = dbus;
        end
        else if (en == 1 && r_w == 1) // r_w==1:read
            data = m[abus];
        else
            data = 8'hZZ;
    end
    assign dbus = data;
endmodule

測試程式:

`timescale 1ns/10ps

module ramTest;
reg clock, reset, en, r_w;
reg [7:0] addr;
wire [7:0] dbus;

ram DUT (.clock(clock), .reset(reset), 
.en(en), .r_w(r_w), .abus(addr), .dbus(dbus));

initial // reset:設定 memory 內容為 0,1,2,....,127
begin
  $display ("ramTest:initial");
  clock = 0;
  reset = 1;
  en = 0;
  r_w = 1; // r_w=1:讀取模式
  #100;
  en = 1;
  reset = 0;
  addr = 0;
end

always #50 clock = clock + 1; 

always #200 
begin
 addr=addr+1;
end

endmodule

方案二:

module mema (r_wb,addr,d_q);
input r_wb; input [7:0] addr;
inout [7:0] d_q;
reg [7:0] data [0:255];
assign d_q = (r_wb) ? data[addr] : 8'hz ;
always @(r_wb)
    if (!r_wb) data[addr] = d_q ;
always @(addr)
    if (!r_wb) data[addr] = d_q ;
endmodule

方案三:

module i2c_sp_ram( 
                      //Inputs 
                      clk,    //clock 
                      wr_en,  //write enable 
                      rd_en,  //read enable 
                      addr,   //address 
                      data_in,//data in 

                      //Output 
                      data_out//data out 
                   ); 

  //Parameter Declaration 
  parameter DEPTH = 8; //depth of FIFO 
  parameter  ADDR_BUS_WD = 1>>DEPTH; //Address bus width 
  parameter  DATA_BUS_WD = 8; //data bus width 

  //Inputs Declarations 
  input  clk;                         //Clock 
  input  wr_en;                       //Write Enable 
  input  rd_en;                       //Read Enable 
  input  [ADDR_BUS_WD-1:0] addr;      //Address Width 
  input  [DATA_BUS_WD-1:0] data_in;   //Data Input 

  //output Declarations 
  output [DATA_BUS_WD-1:0] data_out;  //Data Output 

  //reg Declarations 
  reg [DATA_BUS_WD-1:0] mem [DEPTH-1:0];//Memory 
  reg [DATA_BUS_WD-1:0] data_out;      //Data Output 

  //Generation of data_out 
  always @(posedge clk) 
    begin : READ_GEN 
      if(rd_en)  data_out <= mem[addr]; 
    end 
       //Generation Writing data into memory 
  always @(posedge clk) 
    begin: WRITE_GEN   
      if(wr_en)  mem[addr] <= data_in; 
    end 

  endmodule

方案四:

module RamChip (Address, Data, CS, WE, OE);

parameter AddressSize = 1;
parameter WordSize = 1;

input [AddressSize-1:0] Address;
inout [WordSize-1:0] Data;
input CS, WE, OE;

reg [WordSize-1:0] Mem [0:1<<AddressSize];

assign Data = (!CS && !OE) ? Mem[Address] : {WordSize{1'bz}};

always @(CS or WE)
  if (!CS && !WE)
    Mem[Address] = Data;

always @(WE or OE)
  if (!WE && !OE)
    $display("Operational error in RamChip: OE and WE both active");

endmodule

參考文獻

  1. Technical Tidbits: Ram Modelling in Verilog — http://www.angelfire.com/in/rajesh52/tip2.html
  2. TOPIC: verilog code for RAM and FIFO — http://www.vlsibank.com/sessionspage.asp?titl_id=8240
  3. The following are some of useful verilog examples. — http://asic.co.in/Index_files/verilogexamples.htm#link49

Facebook

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License