OpenCores
no use no use 1/1 no use no use
ram-on-chip timing
by strug on Nov 18, 2011
strug
Posts: 25
Joined: Dec 31, 2009
Last seen: May 9, 2012
In module wb_ram_b3 of orpsocv2, the memory is simulated by the array reg [dw-1:0] mem [ 0 : mem_words-1 ].
I now simulate the memory by the core generator of ISE.
There is the difference of timing in the two ways. The adr and wb_dat_o are simultaneous in the former way . In the latter way, There is a clock cycle delay between adr and wb_dat_o,which results in the system crash.
RE: ram-on-chip timing
by strug on Nov 18, 2011
strug
Posts: 25
Joined: Dec 31, 2009
Last seen: May 9, 2012
I modified the module ram_wb_b3 as following:"
module ram_wb_b3(
wb_adr_i, wb_bte_i, wb_cti_i, wb_cyc_i, wb_dat_i, wb_sel_i,
wb_stb_i, wb_we_i,

wb_ack_o, wb_err_o, wb_rty_o, wb_dat_o,

wb_clk_i, wb_rst_i);

parameter dw = 32;
parameter aw = 32;

input [aw-1:0] wb_adr_i;
input [1:0] wb_bte_i;
input [2:0] wb_cti_i;
input wb_cyc_i;
input [dw-1:0] wb_dat_i;
input [3:0] wb_sel_i;
input wb_stb_i;
input wb_we_i;

output wb_ack_o;
output wb_err_o;
output wb_rty_o;
output [dw-1:0] wb_dat_o;

input wb_clk_i;
input wb_rst_i;

wire ram_we;
// Register to address internal memory array
// Memory parameters
parameter mem_size_bytes = 32'h0000_5000; // 20KBytes
parameter mem_adr_width = 15; //(log2(mem_size_bytes));

parameter bytes_per_dw = (dw/8);
parameter adr_width_for_num_word_bytes = 2; //(log2(bytes_per_dw))
parameter mem_words = (mem_size_bytes/bytes_per_dw);

// synthesis attribute ram_style of mem is block
reg [dw-1:0] mem [ 0 : mem_words-1 ] /* verilator public */ /* synthesis ram_style = no_rw_check */;

// Register to address internal memory array
reg [(mem_adr_width-adr_width_for_num_word_bytes)-1:0] adr;

reg wb_ack_o;

assign ram_we = wb_we_i & wb_ack_o;

ram_wb_b ram_wb_b_0(
.addr (adr),
.clk (wb_clk_i),
.din (wb_dat_i),
.dout (wb_dat_o),
.we (ram_we)
);

// Address registering logic
always@(posedge wb_clk_i)
if(wb_rst_i)
adr else if (wb_cyc_i & wb_stb_i)
adr
always @(posedge wb_clk_i)
if (wb_cyc_i & wb_stb_i & !wb_ack_o)
wb_ack_o else
wb_ack_o
// Function to access RAM (for use by Verilator).
function [31:0] get_mem32;
// verilator public
input [aw-1:0] addr;
get_mem32 = mem[addr];
endfunction // get_mem32


endmodule
"

The module ram_wb_b is generated by the ISE core generator.

However, there is a wrong simulation wave in the attachment.
ram_ip.jpg (82 kb)
RE: ram-on-chip timing
by strug on Nov 18, 2011
strug
Posts: 25
Joined: Dec 31, 2009
Last seen: May 9, 2012
module ram_wb_b(
addr,
clk,
din,
dout,
we);


input [12 : 0] addr;
input clk;
input [31 : 0] din;
output [31 : 0] dout;
input we;

// synthesis translate_off

BLKMEMSP_V6_2 #(
.c_addr_width(13),
.c_default_data("0"),
.c_depth(6400),
.c_enable_rlocs(0),
.c_has_default_data(0),
.c_has_din(1),
.c_has_en(0),
.c_has_limit_data_pitch(0),
.c_has_nd(0),
.c_has_rdy(0),
.c_has_rfd(0),
.c_has_sinit(0),
.c_has_we(1),
.c_limit_data_pitch(18),
.c_mem_init_file("ram_wb_b.mif"),
.c_pipe_stages(0),
.c_reg_inputs(0),
.c_sinit_value("0"),
.c_width(32),
.c_write_mode(0),
.c_ybottom_addr("0"),
.c_yclk_is_rising(1),
.c_yen_is_high(1),
.c_yhierarchy("hierarchy1"),
.c_ymake_bmm(0),
.c_yprimitive_type("32kx1"),
.c_ysinit_is_high(1),
.c_ytop_addr("1024"),
.c_yuse_single_primitive(0),
.c_ywe_is_high(1),
.c_yydisable_warnings(1))
inst (
.ADDR(addr),
.CLK(clk),
.DIN(din),
.DOUT(dout),
.WE(we),
.EN(),
.ND(),
.RFD(),
.RDY(),
.SINIT());


// synthesis translate_on

// XST black box declaration
// box_type "black_box"
// synthesis attribute box_type of ram_wb_b is "black_box"

endmodule
RE: ram-on-chip timing
by strug on Nov 18, 2011
strug
Posts: 25
Joined: Dec 31, 2009
Last seen: May 9, 2012
module ram_wb_b3(
wb_adr_i, wb_bte_i, wb_cti_i, wb_cyc_i, wb_dat_i, wb_sel_i,
wb_stb_i, wb_we_i,

wb_ack_o, wb_err_o, wb_rty_o, wb_dat_o,

wb_clk_i, wb_rst_i);

parameter dw = 32;
parameter aw = 32;

input [aw-1:0] wb_adr_i;
input [1:0] wb_bte_i;
input [2:0] wb_cti_i;
input wb_cyc_i;
input [dw-1:0] wb_dat_i;
input [3:0] wb_sel_i;
input wb_stb_i;
input wb_we_i;

output wb_ack_o;
output wb_err_o;
output wb_rty_o;
output [dw-1:0] wb_dat_o;

input wb_clk_i;
input wb_rst_i;

wire ram_we;
// Register to address internal memory array
// Memory parameters
parameter mem_size_bytes = 32'h0000_5000; // 20KBytes
parameter mem_adr_width = 15; //(log2(mem_size_bytes));

parameter bytes_per_dw = (dw/8);
parameter adr_width_for_num_word_bytes = 2; //(log2(bytes_per_dw))
parameter mem_words = (mem_size_bytes/bytes_per_dw);

// synthesis attribute ram_style of mem is block
reg [dw-1:0] mem [ 0 : mem_words-1 ] /* verilator public */ /* synthesis ram_style = no_rw_check */;

// Register to address internal memory array
reg [(mem_adr_width-adr_width_for_num_word_bytes)-1:0] adr;

reg wb_ack_o;

assign ram_we = wb_we_i & wb_ack_o;

ram_wb_b ram_wb_b_0(
.addr (adr),
.clk (wb_clk_i),
.din (wb_dat_i),
.dout (wb_dat_o),
.we (ram_we)
);

// Address registering logic
always@(posedge wb_clk_i)
if(wb_rst_i)
adr else if (wb_cyc_i & wb_stb_i)
adr

always @(posedge wb_clk_i)
if (wb_cyc_i & wb_stb_i & !wb_ack_o)
wb_ack_o else
wb_ack_o
endmodule
RE: ram-on-chip timing
by rfajardo on Nov 18, 2011
rfajardo
Posts: 306
Joined: Jun 12, 2008
Last seen: Jan 6, 2020
Hi Strug,

You have to register the acknowledge signal:

assign wb_ack_o = ack_re | ack_we;

//
// Write acknowledge
//
always @ (negedge wb_clk_i or posedge wb_rst_i)
begin
if (wb_rst_i)
ack_we else
if (wb_cyc_i & wb_stb_i & wb_we_i & ~ack_we)
ack_we else
ack_we end

//
// read acknowledge
//
always @ (posedge wb_clk_i or posedge wb_rst_i)
begin
if (wb_rst_i)
ack_re else
if (wb_cyc_i & wb_stb_i & ~wb_err_o & ~wb_we_i & ~ack_re)
ack_re else
ack_re end
no use no use 1/1 no use no use
© copyright 1999-2026 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.