首先是关于这个问题的一些背景知识。在我当前的项目中,我试图创建一个曼德尔布罗特计算器,它是通过使用一个fpga优化的。在这一点上,我试图在nios处理器和fpga之间建立一个桥梁(不幸的是,没有运气,什么都没有)。
我试图理解nios和使用avalon总线的fpga(运行vhdl)之间的通信。我已经使用vhdl超过15周了,并且在nios 2处理器上启动了过去的5周。现在我想完成的事情是:
所以我想在wich上创建一个设置,我可以测试发送两次64位值,用vhdl记住这个值,然后他们尝试读取它,这样它就可以回到nios 2处理器上(用c代码)。
很可能在我想弄清楚之前我没有把这个问题提出来。这是我到现在为止所做的工作。
在nios上,我在main中创建了一个简单的设置,它将两个64位值写入fpga,然后检索它们并在红色和绿色的led上显示输出,顺便说一句:我在altera de2板上运行这个。C代码如下所示

int main (void)
{
    //Reset the green and red leds to off
    IOWR(REDLEDS_BASE, 0, 0x0);
    IOWR(GREENLEDS_BASE, 0, 0x0);

    //Write the 64 bit x coordinate
    IOWR(MANDELBROT_CORE_BASE, 0x0, 0xAAAAAAAA);
    IOWR(MANDELBROT_CORE_BASE, 0x4, 0xAAAAAAAA);

    //Write the 64 bit y coordinate
    IOWR(MANDELBROT_CORE_BASE, 0x8, 0xEEEEEEEE);
    IOWR(MANDELBROT_CORE_BASE, 0x12, 0xEEEEEEEE);

    //Read the 64 bit x coordinate
    double x = IORD(MANDELBROT_CORE_BASE, 0);

    //Read the 64 bit y coordinate
    double y = IORD(MANDELBROT_CORE_BASE, 8);

    //Write the values to the leds
    IOWR(REDLEDS_BASE, 0, x);
    IOWR(GREENLEDS_BASE, 0, y);

    while(bRunning == true)
    {
    }

    return 1;
}

我知道这段代码可能不正确,因为iqrd只能检索32位值。但是我无法找到一个同时读取64位地址的解决方案。我从this question那里学到了很多技巧。所以我不知道这是否正确。
其次,用vhdl语言编写了fpga端。这个组件是一个64位组件,它在qsys中与nios的avalon总线相连。处理传入和传出请求的组件是avalon_mandelbrot组件(如下所示)。
entity avalon_mandelbrot is
    port (
        avs_s0_read        : in  std_logic                     := '0'; -- s0.read
        avs_s0_readdata    : out std_logic_vector(63 downto 0);        -- readdata
        avs_s0_write       : in  std_logic                     := '0'; -- write
        avs_s0_writedata   : in  std_logic_vector(63 downto 0) := (others => '0'); -- writedata
        avs_s0_waitrequest : out std_logic;                                        -- waitrequest
        avs_s0_address     : in  std_logic_vector(7 downto 0)  := (others => '0'); -- address
        avs_s0_byteenable  : in  std_logic_vector(7 downto 0) ;                    -- byte enable
        clk                : in  std_logic                     := '0';             -- clock
        reset              : in  std_logic                     := '0';             -- reset
    );
end entity avalon_mandelbrot;

architecture rtl of avalon_mandelbrot is
   begin
       process(clk)
           variable data_in : std_logic_vector(63 downto 0):= (others => '0');
           variable data_temp_x : std_logic_vector(63 downto 0):= (others => '0');
           variable data_temp_y : std_logic_vector(63 downto 0):= (others => '0');
       begin

           if rising_edge(clk) then

               if avs_s0_write = '1' then
                   if avs_s0_byteenable(0) = '1' then
                       data_in(7 downto 0) := avs_s0_writedata(7 downto 0);
                   end if;

                   if avs_s0_byteenable(1) = '1' then
                       data_in(15 downto 8) := avs_s0_writedata(15 downto 8);
                   end if;

                   if avs_s0_byteenable(2) = '1' then
                       data_in(23 downto 16) := avs_s0_writedata(23 downto 16);
                   end if;

                   if avs_s0_byteenable(3) = '1' then
                       data_in(31 downto 24) := avs_s0_writedata(31 downto 24);
                   end if;

                   if avs_s0_byteenable(4) = '1' then
                       data_in(39 downto 32) := avs_s0_writedata(39 downto 32);
                   end if;

                   if avs_s0_byteenable(5) = '1' then
                       data_in(47 downto 40) := avs_s0_writedata(47 downto 40);
                   end if;

                   if avs_s0_byteenable(6) = '1' then
                       data_in(55 downto 48) := avs_s0_writedata(55 downto 48);
                   end if;

                   if avs_s0_byteenable(7) = '1' then
                       data_in(63 downto 56) := avs_s0_writedata(63 downto 56);
                   end if;
               end if;


               --Master wants to write to slave
               if avs_s0_write = '1' then
                   case avs_s0_address is
                       when "00000000" => -- ADDR 0
                           data_temp_x(31 downto 0) := data_in(31 downto 0);
                       when "00000100" => -- ADDR 4
                           data_temp_x(63 downto 32) := data_in(63 downto 32);
                       when "00001000" => -- ADDR 8
                           data_temp_y(31 downto 0) := data_in(31 downto 0);
                       when "00001100" => -- ADDR 12
                           data_temp_y(63 downto 32) := data_in(63 downto 32);
                   end case;
               end if;

               --Master wants to read from slave
               if avs_s0_read = '1' then
                   case avs_s0_address is
                       when "00000000" =>
                           avs_s0_readdata <= data_temp_x;
                       when "00001000" =>
                           avs_s0_readdata <= data_temp_y;
                       when others =>
                           avs_s0_readdata <= (others => '0');
                   end case;
               end if;
           end if;
       end process;
end architecture rtl;

在我看来,这个设置应该可以正常工作,但当我尝试测试整个东西时,它似乎没有正常工作。显然我在这里做错了什么,也许有点经验的人可以看看。希望不久有人能帮我。
提前谢谢。

最佳答案

我没有与nios进行过太多的通信,但我使用altera的avalon总线接口。
如果你还没有这样做,我会读他们的参考资料。www.altera.com/literature/manual/mnl_avalon_spec.pdf
特别是第3.5.1节,给出了典型转移的示例。
在您的示例中,您没有指定为此特定的avalon接口使用固定的等待状态时间。我不确定这在nios上是否可以配置,但通常固定的等待状态不是avalon总线的默认操作。这意味着您需要在读/写完成时使用avs_s0_waitrequest信号向主机(nios)发送信号。此端口在您的设计中未连接。
在您的情况下,它可能很简单,例如在写操作期间将avs_s0_waitrequest连接到avs_s0_write,在读取期间将avs_s0_read连接到,因为您的读取延迟为1。

关于c - 如何使用avalon总线将两个64位从nios传输到VHDL?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27744843/

10-08 22:07