-4

最近学习了nios II SOPC,遇到了写内存和读内存的过程。指针 int* 和 char* 的使用让我有两个不同的结果。代码如下。

#include "system.h"
#include "stdio.h"

int main()
{
    char* n = (char*) MEMORY_0_BASE; //the address for first block of memory
    int i;

    for(i=0;i<16;i++)
    {
        *(n+i)=i;
    }

    for(i=0;i<16;i++)
    {
        printf("Du lieu tai o nho thu %d la %d\n", i , *(n+i));
    }

    while(1);

}

“int*”的代码如下

#include "system.h"
#include "stdio.h"

int main()
{
    char* n = (char*) MEMORY_0_BASE; //the address for first block of memory
    int i;

    for(i=0;i<16;i++)
    {
        *(n+i)=i;
    }

    for(i=0;i<16;i++)
    {
        printf("Du lieu tai o nho thu %d la %d\n", i , *(n+i));
    }

    while(1);

}

使用 "int*" 的结果是 0,1,2,...,15 而使用 "char*" 的结果是 3,3,3,3,7,7,7,7,11,11,11 ,11,15,15,15,15。我无法解释为什么会这样。

以下是我的内存块代码

module memory 
#(parameter DATA_WIDTH=32, parameter ADDR_WIDTH=4)
(
    input iClk, iReset_n,
    input iRead_n, iWrite_n,
    input [ADDR_WIDTH-1:0] iAddress,
    input [DATA_WIDTH-1:0] iData,
    output [DATA_WIDTH-1:0] oData
);

reg [DATA_WIDTH-1:0] mem [2**ADDR_WIDTH-1:0];
reg [ADDR_WIDTH-1:0] addr_reg;

always@(posedge iClk)
begin

    if(!iWrite_n)
        mem[iAddress] = iData;

    if(!iRead_n)
        addr_reg = iAddress;

end


assign oData = mem[addr_reg];

endmodule
4

1 回答 1

2

这是我基于观察到的行为的推测。

您的存储设备由 16 x 32 位整数组成。我的猜测是,喜欢以字节为单位的编译器实际上是在屏蔽地址的最低两位。第零个寄存器有地址MEMORY_0_BASE + 0 * 4,第一个寄存器有地址MEMORY_0_BASE + 1 * 4,第二个寄存器有地址MEMORY_0_BASE + 2 * 4等等。

如果使用 int 指针将 int 存储到寄存器中,每次递增 int 指针时,C 指针算法实际上会将sizeof(int)= 4 添加到指针中的地址,因此存储 int 的地址序列如上。

如果使用 char 指针存储 char,每次递增 char 指针时,C 指针算法会将sizeof(char)= 1 添加到指针中的地址。该代码尝试将前四个字符 (0, 1, 2, 3) 存储到MEMORY_0_BASE + 0, MEMORY_0_BASE + 1, MEMORY_0_BASE + 2, MEMORY_0_BASE + 3。如果,正如我所相信的那样,指针的底部两位被屏蔽了,那么所有这些地址都会存储到MEMORY_0_BASE,并且当你完成时,它的值是 3。

对于后四个字符(4、5、6、7)也是如此。它们被存储到MEMORY_0_BASE + 4, MEMORY_0_BASE + 5, MEMORY_0_BASE + 6, MEMORY_0_BASE + 7, 掩蔽后都映射到MEMORY_0_BASE + 4, 留下它包含数字 7 等等。

这就是您获得序列 3,3,3,3,7,7,7,7,11,11,11,11,15,15,15,15 的方式。

于 2015-11-24T14:31:23.340 回答