E203 itcm
阅读原文时间:2023年07月11日阅读:1

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

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章