mem_ri32m16.v 11.8 KB
// mem_ri32m16.v
// DDR memory backdoor;
// :set tabstop=4

// below tasks are compatible with the cpu bus interface task;
// this allows running with either of them to setup or check memory;

// single write to memory backdoor;
// extent bits are set to x in x36 space;

// XXXXXXX
// A[23](M36) is ignored since  we only have one DDR chip(4 banks). 
// A[24](M64)
// Also for higher memory

task ddr_addr;
	output [31:0] ddr_addr;
	input [31:0] cbus_addr;
	input x36;
	reg [13:0] row;
	reg [9:0]  col;
	reg [31:0] addr;
	reg [31:0] tmp;

	begin

			/* Convert all address to 0 base addr */
		if (cbus_addr[31] == 1) 
			tmp = cbus_addr & 32'h3FFF_FFFF;
		else begin
			if (x36) tmp = cbus_addr & 32'h00FF_FFFF;
			else begin
				tmp = (cbus_addr - 32'h0100_0000) & 32'h01FF_FFFF;
			end
		end
		
		if (x36) begin
			addr[31:3] = tmp[30:2];
			addr[2] = 0;
			addr[1:0] = tmp[1:0]; 
		end else addr = tmp;
			
		col[9] = addr[26];		// Col
		col[8] = addr[24];
		col[7:5] = addr[10:8];
		col[4:0] = addr[6:2];

		row[13] = addr[25];		// Row
		row[12:10]= addr[23:22];
		row[9:0] =  addr[20:11];

		ddr_addr = {9'b0, row, col};    
		
		if(mem_mon)
			$display("%t %M cbus_Addr=%x addr=%x ddr_addr=%x row=%x col=%x",
				 $time, addr, cbus_addr, ddr_addr, row, col);
	end

endtask

task mem_swrite;
	input [31:0] addr;
	input [1:0] size;
	input [31:0] data;

	reg x36, valid;
    reg[31:0] valid_addr;
    reg[31:0] mask;               // write mask
    reg[31:0] mdata;              // original memory data  

	begin
		if(mem_mon)
			$display("%t: mem_write: addr 0x%h data 0x%h %b", $time, addr, data, data);
		mem_check_addr(addr, mirror, x36, valid);
		if(valid) begin
            mask = sgl_mask(addr[1:0], size);

			ddr_addr(valid_addr, addr, x36);
	        if (x36) begin
                if (addr[20]) begin  // Bank 2 3
                    if (addr[6]) begin
                        mdata = {vsim.ddr0.Bank3[valid_addr],
				 				 vsim.ddr1.Bank3[valid_addr]};
						mdata = (mdata & ~mask) | (data & mask);
                        vsim.ddr0.Bank3[valid_addr] = mdata[31:16];
                        vsim.ddr1.Bank3[valid_addr] = mdata[15:0];
                        vsim.ddr0.Bank3[valid_addr+1]={7'b0, data[16], 7'b0, data[16]};
                        vsim.ddr1.Bank3[valid_addr+1]={7'b0, data[0], 7'b0, data[0]};
                    end else begin
                        mdata = {vsim.ddr0.Bank2[valid_addr],
				 				 vsim.ddr1.Bank2[valid_addr]};
						mdata = (mdata & ~mask) | (data & mask);
                        vsim.ddr0.Bank2[valid_addr] = mdata[31:16];
                        vsim.ddr1.Bank2[valid_addr] = mdata[15:0];
                        vsim.ddr0.Bank2[valid_addr+1]={7'b0, data[16], 7'b0, data[16]};
                        vsim.ddr1.Bank2[valid_addr+1]={7'b0, data[0], 7'b0, data[0]};
                    end
                end else begin       // Bank 0 1
                    if (addr[6]) begin 
                        mdata = {vsim.ddr0.Bank1[valid_addr],
				 				 vsim.ddr1.Bank1[valid_addr]};
						mdata = (mdata & ~mask) | (data & mask);
                        vsim.ddr0.Bank1[valid_addr] = mdata[31:16];
                        vsim.ddr1.Bank1[valid_addr] = mdata[15:0];
                        vsim.ddr0.Bank1[valid_addr+1]={7'b0, data[16], 7'b0, data[16]};
                        vsim.ddr1.Bank1[valid_addr+1]={7'b0, data[0], 7'b0, data[0]};
                    end else begin
                        mdata = {vsim.ddr0.Bank0[valid_addr],
				 				 vsim.ddr1.Bank0[valid_addr]};
						mdata = (mdata & ~mask) | (data & mask);
                        vsim.ddr0.Bank0[valid_addr] = mdata[31:16];
                        vsim.ddr1.Bank0[valid_addr] = mdata[15:0];
                        vsim.ddr0.Bank0[valid_addr+1]={7'b0, data[16], 7'b0, data[16]};
                        vsim.ddr1.Bank0[valid_addr+1]={7'b0, data[0], 7'b0, data[0]};
					end
                end
 	
            end else begin

                if (addr[21]) begin  // Bank 2 3
                    if (addr[7]) begin
                        mdata = {vsim.ddr0.Bank3[valid_addr],
				 				 vsim.ddr1.Bank3[valid_addr]};
                        mdata = (mdata & ~mask) | (data & mask);
                        vsim.ddr0.Bank3[valid_addr] = mdata[31:16];
                        vsim.ddr1.Bank3[valid_addr] = mdata[15:0];
                    end else begin
                        mdata = {vsim.ddr0.Bank2[valid_addr],
				 				 vsim.ddr1.Bank2[valid_addr]};
						mdata = (mdata & ~mask) | (data & mask);
                        vsim.ddr0.Bank2[valid_addr] = mdata[31:16];
                        vsim.ddr1.Bank2[valid_addr] = mdata[15:0];
                    end
                end else begin       // Bank 0 1
                    if (addr[7]) begin
                        mdata = {vsim.ddr0.Bank1[valid_addr],
				 				 vsim.ddr1.Bank1[valid_addr]};
						mdata = (mdata & ~mask) | (data & mask);
                        vsim.ddr0.Bank1[valid_addr] = mdata[31:16];
                        vsim.ddr1.Bank1[valid_addr] = mdata[15:0];
                    end else begin
                        mdata = {vsim.ddr0.Bank0[valid_addr],
				 				 vsim.ddr1.Bank0[valid_addr]};
						mdata = (mdata & ~mask) | (data & mask);
                        vsim.ddr0.Bank0[valid_addr] = mdata[31:16];
                        vsim.ddr1.Bank0[valid_addr] = mdata[15:0];
                    end
                end 
            end
		end
	end
endtask

// single read from memory backdoor;
// extent bits are ignored in x36 space;

task mem_sread;
	input [31:0] addr;
	input [1:0] size;
	output [31:0] data;

	reg x36, valid;
    reg[31:0] valid_addr;
    reg[31:0] mask;

	begin
		mem_check_addr(addr, mirror, x36, valid);
	
		if(valid) begin
            mask = sgl_mask(addr[1:0], size);
			
			ddr_addr(valid_addr, addr, x36);
			if (x36) begin
                if (addr[20]) begin  // Bank 2 3
                    if (addr[6])
                    data = {vsim.ddr0.Bank3[valid_addr],
				 		    vsim.ddr1.Bank3[valid_addr]};
                    else
                    data = {vsim.ddr0.Bank2[valid_addr],
				 		    vsim.ddr1.Bank2[valid_addr]};
                end else begin       // Bank 0 1
                    if (addr[6]) 
                    data = {vsim.ddr0.Bank1[valid_addr],
				 		    vsim.ddr1.Bank1[valid_addr]};
                    else 
                    data = {vsim.ddr0.Bank0[valid_addr],
				 		    vsim.ddr1.Bank0[valid_addr]};
                end
                
            end else begin
                if (addr[21]) begin  // Bank 2 3
                    if (addr[7])
                    data = {vsim.ddr0.Bank3[valid_addr],
				 		    vsim.ddr1.Bank3[valid_addr]};
                    else
                    data = {vsim.ddr0.Bank2[valid_addr],
				 		    vsim.ddr1.Bank2[valid_addr]};
                end else begin       // Bank 0 1
                    if (addr[7])
                    data = {vsim.ddr0.Bank1[valid_addr],
				 		    vsim.ddr1.Bank1[valid_addr]};
                    else 
                    data = {vsim.ddr0.Bank0[valid_addr],
				 		    vsim.ddr1.Bank0[valid_addr]};
                end
            end

            data = (data & mask) | (32'bx & ~mask);
		end

		if(mem_mon)
			$display("%t: mem_read: addr 0x%h data 0x%h %b", $time, addr, data, data);
	end
endtask

   // block memory read 
   // for n-bytes w/r, it should be n-bytes aligned 
task mem_bread;
	input  [31:0] addr;
    input  [1:0] size;
	output [31:0] d0;
	output [31:0] d1;
	output [31:0] d2;
	output [31:0] d3;
	output [31:0] d4;
	output [31:0] d5;
	output [31:0] d6;
	output [31:0] d7;
    reg    [31:0] mem_data [0:7];

    reg x36,  valid;
    reg[31:0] valid_addr;
    reg[31:0] byte_size, byte_mask;
    integer   i;
    
    begin
 		if(mem_mon) begin
            $display("%t: mem_bread: addr 0x%h size 0x%h ", $time, addr, size);
        end

        byte_size = 8 << size;
        byte_mask = byte_size - 1;
		if (addr & byte_mask) begin
            $display("ERROR: %t mem_bwrite addr is not align to 0x%x bytes", 
					 $time, byte_size);
		end else begin 
			for (i=0; i<byte_size; i=i+4)
				mem_sread(addr+i, 3, mem_data[(i>>2)]);
        end
		
        // copy data from arrary
		d0 = mem_data[0];		 d1 = mem_data[1];
		d2 = mem_data[2];		 d3 = mem_data[3];
		d4 = mem_data[4];		 d5 = mem_data[5];
		d6 = mem_data[6];		 d7 = mem_data[7];
	end
endtask

   // block memory write
   // for n-bytes w/r, it should be n-bytes aligned 
task mem_bwrite;
	input  [31:0] addr;
    input  [1:0] size;
	input [31:0] d0;
	input [31:0] d1;
	input [31:0] d2;
	input [31:0] d3;
	input [31:0] d4;
	input [31:0] d5;
	input [31:0] d6;
	input [31:0] d7;
    reg    [31:0] mem_data [0:7];

    reg x36,  valid;
    reg[31:0] valid_addr;
    reg[31:0] byte_size, byte_mask;
    integer   i;
    
    begin
 		if(mem_mon) begin
            $display("%t: mem_bread: addr 0x%h size 0x%h ", $time, addr, size);
        end

        // copy data into arrary
		mem_data[0] = d0 & 32'hffff_ffff;		 
		mem_data[1] = d1 & 32'hffff_ffff;
		mem_data[2] = d2 & 32'hffff_ffff;
		mem_data[3] = d3 & 32'hffff_ffff;
		mem_data[4] = d4 & 32'hffff_ffff;
		mem_data[5] = d5 & 32'hffff_ffff;
		mem_data[6] = d6 & 32'hffff_ffff;		
		mem_data[7] = d7 & 32'hffff_ffff;

        byte_size = 8 << size;
        byte_mask = byte_size - 1;
		if (addr & byte_mask) begin
            $display("ERROR: %t mem_bwrite addr is not align to 0x%x bytes", 
					 $time, byte_size);
		end else begin 

			for (i=0; i<byte_size; i=i+4)
				mem_swrite(addr+i, 3, mem_data[(i>>2)]);
        end
	end
endtask


   // This is only for debug purpose
task mem_search;
    input [31:0] data;
    integer i;
 
    begin 
        for (i=0; i<1024*1024; i=i+1) begin
			if ({vsim.ddr0.Bank0[i],
				 vsim.ddr1.Bank0[i]} === data) begin
                $display("+++ In Bank 0  @ 0x%x\n", i<<2);
                $display("next 4 is: 0x%x  0x%x  0x%x  0x%x \n", 
						 {vsim.ddr0.Bank0[i+1],vsim.ddr1.Bank0[i+1]}, 
						 {vsim.ddr0.Bank0[i+2],vsim.ddr1.Bank0[i+2]},
                         {vsim.ddr0.Bank0[i+3],vsim.ddr1.Bank0[i+3]}, 
						 {vsim.ddr0.Bank0[i+4],vsim.ddr1.Bank0[i+4]});
                i=i+1024*1025;	 
            end
        end
        if (i < 1024*1025) $display("+++ DATA not found in Bank0");      

        for (i=0; i<1024*1024; i=i+1) begin
			if ({vsim.ddr0.Bank1[i],
				 vsim.ddr1.Bank1[i]} === data) begin
                $display("+++ In Bank 1  @ 0x%x\n", i<<2);
                $display("next 4 is: 0x%x  0x%x  0x%x  0x%x \n", 
						 {vsim.ddr0.Bank1[i+1],vsim.ddr1.Bank1[i+1]}, 
						 {vsim.ddr0.Bank1[i+2],vsim.ddr1.Bank1[i+2]},
                         {vsim.ddr0.Bank1[i+3],vsim.ddr1.Bank1[i+3]}, 
						 {vsim.ddr0.Bank1[i+4],vsim.ddr1.Bank1[i+4]});
                i=i+1024*1025;	 
            end
        end
        if (i < 1024*1025) $display("+++ DATA not found in Bank1");      

        for (i=0; i<1024*1024; i=i+1) begin
			if ({vsim.ddr0.Bank2[i],
				 vsim.ddr1.Bank2[i]} === data) begin
                $display("+++ In Bank 2  @ 0x%x\n", i<<2);
                $display("next 4 is: 0x%x  0x%x  0x%x  0x%x \n", 
						 {vsim.ddr0.Bank2[i+1],vsim.ddr1.Bank2[i+1]}, 
						 {vsim.ddr0.Bank2[i+2],vsim.ddr1.Bank2[i+2]},
                         {vsim.ddr0.Bank2[i+3],vsim.ddr1.Bank2[i+3]}, 
						 {vsim.ddr0.Bank2[i+4],vsim.ddr1.Bank2[i+4]});
                i=i+1024*1025;	 
            end
        end
        if (i < 1024*1025) $display("+++ DATA not found in Bank2");      

        for (i=0; i<1024*1024; i=i+1) begin
			if ({vsim.ddr0.Bank3[i],
				 vsim.ddr1.Bank3[i]} === data) begin
                $display("+++ In Bank 3  @ 0x%x\n", i<<2);
                $display("next 4 is: 0x%x  0x%x  0x%x  0x%x \n", 
						 {vsim.ddr0.Bank3[i+1],vsim.ddr1.Bank3[i+1]}, 
						 {vsim.ddr0.Bank3[i+2],vsim.ddr1.Bank3[i+2]},
                         {vsim.ddr0.Bank3[i+3],vsim.ddr1.Bank3[i+3]}, 
						 {vsim.ddr0.Bank3[i+4],vsim.ddr1.Bank3[i+4]});
                i=i+1024*1025;	 
            end
        end
        if (i < 1024*1025) $display("+++ DATA not found in Bank3");      

    end
     
endtask