[SystemVerilog] read/write memory

最近看到AXI slave vip memory,记录下如何backdoor读写memory.

define `MEM_MAX_DATA_WIDTH      (64)

define `MEM_MAX_ADDR_WIDTH     (20)

ps: define 记得加上括号。

========================================================================

//处理从memory读出来的数据,返回读出来的数据

//比如,读addr=7,byte_num=2,则需要读取两个memory entry(0和8),然后把addr=7对应的data(8'h12)和addr=8对应的data

//(8'h34)merge在一起后返回(16'h3412)

 function bit [`MEM_MAX_DATA_WIDTH:0] backdoor_read_mem(

               bit  [`MEM_MAX_ADDR_WIDTH-1 : 0]  addr =0,

               bit  [`MEM_MAX_DATA_WIDTH-1 : 0]  byte_num = `MEM_MAX_DATA_WIDTH/8);

               

               bit  [`MEM_MAX_DATA_WIDTH-1 : 0] data = 0;

               bit  [`MEM_MAX_DATA_WIDTH-1 : 0] data_tmp = 0;

               bit  [`MEM_MAX_ADDR_WIDTH-1 : 0] end_addr = addr + byte_num -1;

               int  dwidth_power =0;

               bit  [`MEM_MAX_ADDR_WIDTH-1 : 0] addr_lsb =0;

 

              dwidth_power = cal_data_width_power(`MEM_MAX_ADDR_WIDTH;

              addr_lsb  = addr & {dwidth_power{1'b1}};//用于计算unalign addr

             if((addr >> dwidth_power) == (end_addr >> dwidth_power)begin//同一个memory entry

                  data_tmp = slave_mem.read(addr);

                  data = data_tmp >>(addr_lsb*8);

             end

             else begin

                    data_tmp = slave_mem.read(addr);

                    data = data_tmp >>(addr_lsb*8);//移到最低位

                    data_tmp = slave_mem.read(addr);

                    data |= data_tmp <<((`MEM_MAX_DATA_WIDTH/8-addr_lsb)*8);//两次数据进行merge

            end

            if(byte_num < `MEM_MAX_DATA_WIDTH/8)//把没有用的bit置为0

                 data &= ({byte_num*8{1'b1}});

             return data;

endfunction

===================================================================

 function bit  backdoor_write_mem(

               bit  [`MEM_MAX_ADDR_WIDTH-1 : 0]  addr =0,

               bit  [`MEM_MAX_DATA_WIDTH-1 : 0]   data = 0,

               bit  [`MEM_MAX_DATA_WIDTH-1 : 0]   byte_num = `MEM_MAX_DATA_WIDTH/8);

               

               bit  [`MEM_MAX_DATA_WIDTH-1 : 0]     data_tmp = 0;

               bit  [`MEM_MAX_ADDR_WIDTH-1 : 0]    end_addr = addr + byte_num -1;

                bit  [`MEM_MAX_DATA_WIDTH/8-1 : 0] byteen = ~0;//所有bit 为1

               int  dwidth_power =0;

               bit  [`MEM_MAX_ADDR_WIDTH-1 : 0] addr_lsb =0;

               bit  [`MEM_MAX_ADDR_WIDTH-1 : 0] end_addr_lsb =0;

               dwidth_power = cal_data_width_power(`MEM_MAX_ADDR_WIDTH;

               addr_lsb  = addr & {dwidth_power{1'b1}};//用于计算unalign addr

               end_addr_lsb  = end_addr & {dwidth_power{1'b1}};

                if((addr >> dwidth_power) == (end_addr >> dwidth_power)begin//同一个memory entry

                      byteen=0;

                      for(int i=addr_lsb;i<=end_addr_lsb;i++)

                          byteen[i] = 1'b1;

                      data_tmp = data <<(data_lsb*8);

                      if(slave_mem.write(addr,data_tmp,byteen) == 0)begin

                           `uvm_fatal(....)

                            return 0;

                     end

                end

              else begin

                 byteen = ~0;

                 for(int i=0;i<addr_lsb;I++)

                      byteen[i] = 1'b0;

                data_tmp = data <<(addr_lsb*8);

                slave_mem.write(addr,data_tmp,byteen);

                byteen= 'b0; 

                for(int i=0;i<end_addr_lsb;i++)

                      byteen[i] = 1'b1;

               data_tmp = data >>((`MEM_MAX_DATA_WIDTH/8-addr_lsb)*8);

               addr = ((addr>>dwidth_power)+1)<<dwidth_power;

               slave_mem.write(addr,data_tmp,byteen);

             end

             rerurn 1;

endfunction

===================================================================

//用于计算数据位宽是2的几次幂;

//对于memory而言,每行entry的起始addr(即aligned addr)的低data_width_power位是全为0;

//比如 数据宽度为64bit, 则power=3,每行entry对应的起始addr为'h0,'h8,'h10,'h18....,其低3bit全为0;

function int cal_data_width_power(data_width);

   int i = 0;

   int tmp_value = data_width/8;

   while(tmp_value>0)begin

       tmp_value = tmp_value >> 1;

       if(tmp_value == 0) break;

       i++;

   end

   return i;

endfunction

 

========================================================================

class mem extends uvm_sequence_item;

    typedef bit [`MEM_MAX_DATA_WIDTH-1:0] data_t;

    typedef bit [`MEM_MAX_ADDR_WIDTH-1:0] addr_t;

    bit [`MEM_MAX_ADDR_REGION_WIDTH-1:0] addr_region = 0;//暂时没用到

    bit [`MEM_MAX_ADDR_WIDTH-1:0] min_addr = 0;

     bit [`MEM_MAX_ADDR_WIDTH-1:0] max_addr = 0;

     int  data_wdth = 0;

     bit [`MEM_MAX_DATA_WIDTH-1:0] meminit_value;

     mem_word   mem_array[*];//memory hash

     mem_word   mem_item;   //每个memory entry

     static int  dwidth_power;

 

     function new(string name = "mem_inst",

                           int data_wdth = 32,

                           int addr_region = 0,

                           bit  [`MEM_MAX_ADDR_WIDTH-1:0] min_addr = 0,

                           bit  [`MEM_MAX_ADDR_WIDTH-1:0] max_addr = ((1<<`MEM_MAX_ADDR_WIDTH)-1)                 

                        );

          this.addr_region = addr_region;

          this.data_wdth = data_wdth;

          this.min_addr = min_addr;

          this.max_addr = max_addr;

     endfunction

 

     function logic[`MEM_MAX_DATA_WIDTH-1:0] read(bit [`MEM_MAX_ADDR_WIDTH-1:0] addr,  int set_lock = -1);

         bit [`MEM_MAX_DATA_WIDTH-1:0] mem_idx = (addr >>dwidth_power);

         if(mem_array.exists(mem_idx))

             return mem_array[mem_idx].read();

          else begin

              set_meminit_value();//设置初始值

              mem_item = new(addr_region,mem_idx,);//例化一个memory entry

              mem_item.write(this.meminit_value);  //把初始值写入entry

              mem_array[mem_idx] = mem_item;    //把entry 存入memory

              return this.meminit_value;

          end

     endfunction

 

 function bit  write (bit [`MEM_MAX_ADDR_WIDTH-1:0] addr,  bit [`MEM_MAX_DATA_WIDTH-1:0] data = 0,

                               bit [`MEM_MAX_DATA_WIDTH/8-1:0] byteen=~0,int set_lock = -1);

         bit [`MEM_MAX_DATA_WIDTH-1:0] mem_idx = (addr >>dwidth_power);

 

         if(set_lock == 1)

            return 0;

         else begin

            if(! mem_array.exists(mem_idx))begin

                 mem_item = new(addr_region,mem_idx,);//例化一个memory entry

                 set_meminit_value();//设置初始值,随机选择全0,全1,随机值

                 mem_item.write(this.meminit_value);  //把初始值写入entry

                 mem_array[mem_idx] = mem_item;    //把entry 存入memory

            end

            void' (mem_array[mem_idx].write(data,byteen,));

            return 1;

          end

     endfunction

     function void clear();

           mem_array.delete;

     endfunction

 endclass

=================================================================================

class mem_word;

       bit [`MEM_MAX_ADDR_REGION_WIDTH-1:0]    addrspace;

       bit [`MEM_MAX_ADDR_WIDTH-1:0] addr;

       bit [`MEM_MAX_DATA_WIDTH-1:0] data;

       static int dwidth_power = 7;

 

       function new (bit [`MEM_MAX_ADDR_REGION_WIDTH-1:0]    addrspace,                       

                             bit [`MEM_MAX_ADDR_WIDTH-1:0] addr;

                             bit [`MEM_MAX_DATA_WIDTH-1:0] init_data = 'bx;

                              );

               this.addrspace = addrspace;

               this.addr = addr;

               this.data = init_data;

     endfunction

 

      function logic[`MEM_MAX_DATA_WIDTH-1:0] read();

             return this.data;

     endfunction

    

function bit  write (bit [`MEM_MAX_DATA_WIDTH-1:0] data ,

                               bit [`MEM_MAX_DATA_WIDTH/8-1:0] byteen=~0,

                               int  set_lock = -1);

 

         logic [`MEM_MAX_DATA_WIDTH-1:0] org_word_tmp;

         logic [`MEM_MAX_DATA_WIDTH-1:0] in_word_tmp;

         logic [`MEM_MAX_DATA_WIDTH-1:0] word_tmp;

         logic [7:0] byte_tmp;

         logic [7:0] in_byte_tmp;

         int  i;

 

         if(set_lock == 1)

              return 0;

         else begin

              for(i=(`MEM_MAX_DATA_WIDTH/8-1);i>=0;i--)begin

                  org_word_tmp = (this.data>>(i*8));//之前已经存入memory中的data

                  byte_tmp = org_word_tmp[7:0];//从最高byte(MSB)开始循环,每次把当前byte右移到最低byte处

                  in_word_tmp = (data>>(i*8));//当前要存入memory中的data

                  in_byte_tmp = in_word_tmp[7:0];

                  if(byteen[i]==1)//当前byte 数据有更新

                        byte_tmp = in_byte_tmp;

                  word_tmp = (word_tmp<<8) | byte_tmp;

             end

             this.data = word_tmp;

             return 1;

         end

endclass

                                                                                                        

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值