E203 itcm是64Kb,所以地址总线为16位,2^16=64Kb, 数据线宽度为64 bits(8 bytes),所以address width是16-3=13bit,ram depth 是2^16/8=2^13。
itcm的基地址默认是0x8000_0000。
在目录e200_opensource/riscv-tools/riscv-tests/isa/generated,这儿有很多生成好的test文件。比如test rv32ui-p-andi
文件rv32ui-p-andi是riscv的可执行elf文件, rv32ui-p-andi.dump是对应的汇编文件,rv32ui-p-andi.verilog是对于的机器码文件,可以在verilog中用下面的代码把要执行的机器码装入itcm中。
//default itcm size is 64Kb, so E203\_ITCM\_RAM\_DP=13
reg \[7:0\] itcm\_mem \[0:(\`E203\_ITCM\_RAM\_DP\*8)-1\];
initial begin
$readmemh({testcase, ".verilog"}, itcm\_mem);
for (i=0;i<(\`E203\_ITCM\_RAM\_DP);i=i+1) begin
\`ITCM.mem\_r\[i\]\[00+7:00\] = itcm\_mem\[i\*8+0\];
\`ITCM.mem\_r\[i\]\[08+7:08\] = itcm\_mem\[i\*8+1\];
\`ITCM.mem\_r\[i\]\[16+7:16\] = itcm\_mem\[i\*8+2\];
\`ITCM.mem\_r\[i\]\[24+7:24\] = itcm\_mem\[i\*8+3\];
\`ITCM.mem\_r\[i\]\[32+7:32\] = itcm\_mem\[i\*8+4\];
\`ITCM.mem\_r\[i\]\[40+7:40\] = itcm\_mem\[i\*8+5\];
\`ITCM.mem\_r\[i\]\[48+7:48\] = itcm\_mem\[i\*8+6\];
\`ITCM.mem\_r\[i\]\[56+7:56\] = itcm\_mem\[i\*8+7\];
end
itcm实际上就是一块sram,对itcm的读写如下,读写数据宽度都是按32bit进行的,对于写可以通过write mask只写某个byte。
module sirv_sim_ram
#(parameter DP = 512,
parameter FORCE_X2ZERO = 0,
parameter DW = 32,
parameter MW = 4,
parameter AW = 32
)
(
input clk,
input [DW-1 :0] din,//input data
input [AW-1 :0] addr,//input address
input cs, //chip select
input we, //write enable
input [MW-1:0] wem,//write enable mask
output [DW-1:0] dout //write data out
);
reg \[DW-1:0\] mem\_r \[0:DP-1\];
reg \[AW-1:0\] addr\_r;
wire \[MW-1:0\] wen;
wire ren;
assign ren = cs & (~we);
//it is 4 bits, and every bit mask a byte write
assign wen = ({MW{cs & we}} & wem);
genvar i;
always @(posedge clk)
begin
if (ren) begin
addr\_r <= addr;
end
end
generate
for (i = 0; i < MW; i = i+1) begin :mem
if((8\*i+8) > DW ) begin: last
always @(posedge clk) begin
if (wen\[i\]) begin
mem\_r\[addr\]\[DW-1:8\*i\] <= din\[DW-1:8\*i\];
end
end
end
else begin: non\_last
always @(posedge clk) begin
if (wen\[i\]) begin
mem\_r\[addr\]\[8\*i+7:8\*i\] <= din\[8\*i+7:8\*i\];
end
end
end
end
endgenerate
wire [DW-1:0] dout_pre;
assign dout_pre = mem_r[addr_r];
generate
if(FORCE_X2ZERO == 1) begin: force_x_to_zero
for (i = 0; i < DW; i = i+1) begin:force_x_gen
`ifndef SYNTHESIS//{
assign dout[i] = (dout_pre[i] === 1'bx) ? 1'b0 : dout_pre[i];
`else//}{
assign dout[i] = dout_pre[i];
`endif//}
end
end
else begin:no_force_x_to_zero
assign dout = dout_pre;
end
endgenerate
endmodule
testbench文件
module sirv_sim_ram_tb;
reg clk=0;
reg cs=1;
reg we=1;
reg[3:0] wem=4'b1111;
reg[31:0] addr;
reg[31:0] din;
wire[31:0] dout;
integer i,j;
sirv_sim_ram #(
.FORCE_X2ZERO (1),
.DP (64),
.AW (6),
.MW (4),
.DW (32)
)u_sirv_sim_ram (
.clk (clk),
.din (din),
.addr (addr),
.cs (cs),
.we (we),
.wem (wem),
.dout (dout)
);
always #10 clk = ~clk;
initial
begin
for(i=0; i<16; i=i+1)
#20 addr=i;
#20
#20 we = 0;
addr = 0;
#20 addr = 1;
#20 addr = 2;
#20 addr = 3;
#20 addr = 4;
#20 addr = 5;
#20 addr = 6;
end
initial
begin
for(j=0; j<16; j=j+1)
#20 din=j;
end
initial
begin
//$dumpfile("dump.vcd");
//$dumpvars;
$fsdbDumpfile("dump.fsdb");
$fsdbDumpvars("+all");
end
initial
begin
$monitor($time,,,"%d,%d,%d,%d,%d,%d)",cs,din,addr,we,wem,dout);
#1000 $finish;
end
endmodule
手机扫一扫
移动阅读更方便
你可能感兴趣的文章