module memory_3(dout,err,addr,size,we,din,clk);
input [31:0] addr;
input [1:0] size;
input we;
input [31:0] din;
input clk;
output [31:0] dout;
output [2:0] err;
reg [31:0] dout;
reg [2:0] err;
parameter text_base = 'h400000;
parameter text_size = 'h100;
parameter data_base = 'h10010000;
parameter data_size = 'h100;
parameter err_none = 0;
parameter err_bus = 1; // Bad alignment.
parameter err_seg = 2; // Bad address.
reg [31:0] storage [0:(text_size+data_size)>>2];
reg [31:0] saddr, mask, rd;
reg [4:0] amt;
function [31:0] addr_to_saddr;
input [31:0] a;
if( a >= text_base && a < text_base + text_size ) begin
addr_to_saddr = a - text_base >> 2;
end else if( a >= data_base && a < data_base + data_size ) begin
addr_to_saddr = a - data_base + text_size >> 2;
end else begin
addr_to_saddr = -1;
end
endfunction
reg [2:0] access_mem_err;
function [31:0] access_mem;
input [31:0] addr;
input [1:0] size;
input we;
input [31:0] din;
begin
saddr = addr_to_saddr(addr);
if( !size ) begin
access_mem_err = err_none;
access_mem = 0;
end else if( saddr == -1 ) begin
access_mem_err = err_seg;
access_mem = 32'bz;
end else begin
access_mem_err = addr << 3 - size & 3 ? err_bus : err_none;
amt = 3 - addr[1:0] - { &size, size[1] } << 3;
mask = ( ( 1 << ( 8 << (size-1) ) ) - 1 ) << amt;
rd = storage[ saddr ];
access_mem = err == err_bus ? 32'bzx : ( rd & mask ) >> amt;
if( we ) storage[ saddr ] = ( rd & ~mask ) | ( (din<<amt ) & mask );
end
end
endfunction
function [31:0] peek_word;
input [31:0] peek_addr;
peek_word = access_mem(peek_addr,3,0,0);
endfunction
function [2:0] poke_word;
input [31:0] poke_addr;
input [31:0] poke_data;
reg [31:0] dummy;
begin
dummy = access_mem(poke_addr,3,1,poke_data);
poke_word = access_mem_err;
end
endfunction
always @( negedge clk ) begin
dout = access_mem(addr,size,we,din);
err = access_mem_err;
end
endmodule