outputer 2022-03-31 23:10 采纳率: 90%
浏览 81
已结题

关于verilog设计单口同步RAM的问题

一.这是我的实现代码:


`timescale 1ns / 1ps

module single_port_synrdwr#(
    parameter DATA_WIDTH = 8,
    parameter ADDR_WIDTH = 4,
    parameter ADDR_DEPTH = 2**ADDR_WIDTH
    )
(
    input                  sys_clk,
    input                  spsy_oe,   //output enable
    input                  spsy_wr,   //1 for write and 0 for read
    input                  spsy_cs,    //chip slect
    input [ADDR_WIDTH-1:0] spsy_addr,
    inout [DATA_WIDTH-1:0] spsy_data
    );
    
reg [DATA_WIDTH-1:0] spsy_mem [0:ADDR_DEPTH-1];
reg [DATA_WIDTH-1:0] spsy_mid_data;
 
//initialization for spsy_mem    
integer i;
initial begin
    for(i=0;i<ADDR_DEPTH;i=i+1)
    spsy_mem[i] = 8'b0;
end

//out data(ram is reading for now)
//now inout port is a output port
assign spsy_data = (spsy_cs & !spsy_wr & spsy_oe) ? spsy_mid_data : 8'bz;    

//write port
 always@(posedge sys_clk)begin
    if(spsy_cs & spsy_wr)
        spsy_mem[spsy_addr] <= spsy_mid_data;
    else
        spsy_mem[spsy_addr] <= spsy_mem[spsy_addr];
end 

//read port
always@(posedge sys_clk)begin
    if(spsy_cs & !spsy_wr)
        spsy_mid_data <= spsy_mem[spsy_addr];
    else
        spsy_mem[spsy_addr] <= spsy_mem[spsy_addr];
end   
     
endmodule

二.这是我的仿真代码:

`timescale 1ns / 1ps

module tb_ip_ram_practice_02();

parameter DATA_WIDTH = 8;
parameter ADDR_WIDTH = 4;
parameter ADDR_DEPTH = 2**ADDR_WIDTH;//if unuseful_delete

reg                   sys_clk;
reg                   spsy_oe;
reg                   spsy_wr;
reg                   spsy_cs;
reg  [ADDR_WIDTH-1:0] spsy_addr;
wire [DATA_WIDTH-1:0] spsy_data;//wire for inout port
reg  [DATA_WIDTH-1:0] spsy_mid_data;

//in data
//now inout port is a input port
assign spsy_data  =  (spsy_cs & spsy_wr & !spsy_oe ) ? spsy_mid_data : 7'bz ;

initial begin
    sys_clk = 1'b0;
    forever 
        #10 sys_clk = ~sys_clk;
end

initial begin
    spsy_oe   = 1'b0; 
    spsy_wr   = 1'b0; 
    spsy_cs   = 1'b0; 
    spsy_addr = 4'b0;
    spsy_mid_data = 8'b0;
    
    //read
    #20
    @(posedge sys_clk) begin
        spsy_oe   = 1'b1;
        spsy_cs   = 1'b1;
    end
    repeat(15) #20 spsy_addr = spsy_addr + 4'b1;//read off 16 address's data
    
    //write
    #20
    @(posedge sys_clk) begin
        spsy_cs   = 1'b1;
        spsy_wr   = 1'b1;
    end
    repeat(15) #20 begin
        spsy_addr     = spsy_addr     + 4'b1;
        spsy_mid_data = spsy_mid_data + 4'b1;
    end

 //read agin
    #20
    @(posedge sys_clk) begin
        spsy_oe   = 1'b1;
        spsy_cs   = 1'b1;
    end
    repeat(15) #20 spsy_addr = spsy_addr + 4'b1;//read off 16 address's data
    
    @(posedge sys_clk)
    spsy_cs = 1'b0;
    #20
    $stop ;
    
end

single_port_synrdwr u(
    .sys_clk   (sys_clk),
    .spsy_oe   (spsy_oe),
    .spsy_wr   (spsy_wr),
    .spsy_cs   (spsy_cs),
    .spsy_addr (spsy_addr),
    .spsy_data (spsy_data)
);

endmodule

三.这是仿真之后的电路图
想请教大家的问题是:在wr拉高之后为什么mem里存的数据仍然是0,此时的spsy_mid_data已经开始递增了,为什么mem中存入的数据不随之递增?

img

*四.我改变了mem初始值
mem初始值全部赋1之后发现,最终的输出spsy_data是正确的,但是中间的spsy_mid_data和mem存储的数据是错误的。

img

  • 写回答

3条回答 默认 最新

  • 老皮芽子 2022-04-01 09:20
    关注

    代码,仿真都有问题
    代码这么改

    `timescale 1ns / 1ps
     
    module single_port_synrdwr#(
        parameter DATA_WIDTH = 8,
        parameter ADDR_WIDTH = 4,
        parameter ADDR_DEPTH = 2**ADDR_WIDTH
        )
    (
        input                  sys_clk,
        input                  spsy_oe,   //output enable
        input                  spsy_wr,   //1 for write and 0 for read
        input                  spsy_cs,    //chip slect
        input [ADDR_WIDTH-1:0] spsy_addr,
        inout [DATA_WIDTH-1:0] spsy_data
        );
        
    reg [DATA_WIDTH-1:0] spsy_mem [0:ADDR_DEPTH-1];
    reg [DATA_WIDTH-1:0] spsy_mid_data;
     
    //initialization for spsy_mem    
    integer i;
    initial begin
        for(i=0;i<ADDR_DEPTH;i=i+1)
        spsy_mem[i] = 8'b0;
    end
     
    //out data(ram is reading for now)
    //now inout port is a output port
    assign spsy_data = (spsy_cs & !spsy_wr & spsy_oe) ? spsy_mid_data : 8'bz;    
    
    //write port
    always@(posedge sys_clk)begin
        if(spsy_cs & spsy_wr)
            spsy_mem[spsy_addr] <= spsy_data;
    //    else
    //        spsy_mem[spsy_addr] <= spsy_mem[spsy_addr];
    end 
     
    //read port
    always@(posedge sys_clk)begin
        if(spsy_cs & !spsy_wr)
            spsy_mid_data <= spsy_mem[spsy_addr];
    //    else
    //        spsy_mem[spsy_addr] <= spsy_mem[spsy_addr];
    end   
    
    endmodule
     
    

    仿真这么改

    assign spsy_data  =  (spsy_cs & spsy_wr ) ? spsy_mid_data : 7'bz ;
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 4月10日
  • 已采纳回答 4月2日
  • 修改了问题 4月1日
  • 创建了问题 3月31日

悬赏问题

  • ¥15 esp8266控制共阳极wrgb灯板无法关闭所有led灯
  • ¥100 python读取速度问题
  • ¥15 stm32f407使用DMA问题
  • ¥15 您好 这个API接口该怎么弄 网站搭建好了 API也有 现在就不知道该怎么填写API 不知道怎么用
  • ¥88 用uniapp写一个多端的程序,用到高德地图,用高德的JSAPI吗?
  • ¥20 关于#c++#的问题:水果店管理系统
  • ¥30 dbLinq最新版linq sqlite
  • ¥20 对D盘进行分盘之前没有将visual studio2022卸载掉,现在该如何下载回来
  • ¥15 完成虚拟机环境配置,还有安装kettle
  • ¥15 有人会搭建生鲜配送自营+平台的管理系统吗