E203 itcm

      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



image










posted on 2019-09-02 14:04  迈克老狼2012  阅读(1395)  评论(1编辑  收藏  举报

导航