【问题标题】:How to transfer two 64 bit from the nios to VHDL using the avalon bus?如何使用 avalon 总线将两个 64 位从 nios 传输到 VHDL?
【发布时间】:2015-02-28 22:38:27
【问题描述】:

首先是关于这个问题的一些背景故事。在我当前的项目中,我正在尝试创建一个使用 FPGA 进行优化的 Mandelbrot 计算器。在这一点上,我试图在 nios 处理器和 FPGA 之间建立一座桥梁(遗憾的是没有运气)。

我正在尝试使用 Avalon 总线了解 nios 和 FPGA(运行 VHDL)之间的通信。我已经使用 VHDL 超过 15 周了,过去 5 周开始使用 nios 2 处理器。现在我想要完成的事情如下: 所以我想创建一个设置,我可以测试发送两次 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;

在我看来,这个设置应该可行,但当我尝试测试整个事情时,它似乎并没有按应有的方式运行。显然我在这里做错了,也许有更多经验的人可以看看它。希望有人能尽快帮助我。

【问题讨论】:

  • 您是否尝试过使用 SignalTap 调试您的设计?
  • 不,我没有。实际上我以前从未使用过它,因为它对我来说相当新。我去看看。

标签: c vhdl fpga nios


【解决方案1】:

我没有专门与 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。

【讨论】:

  • 感谢您的快速回复。我一直在阅读您指定的 pdf,但我无法理解 64 位组件的地址映射。我知道一个字被指定为 32 位。因此,为了传输 64,偏移量应该是 1 或 4(取决于类型、单词或符号),对吧?我在组件中使用了单词,因为我不需要访问 8 位或 16 位部分。快速检查一下,您是否说我使用了正确的方法来实现 avalon mm 从组件(不管缺少 waitrequest 处理)?
  • 我不确定我是否关注您的 64 位/32 位问题。您的 VHDL 设计中的 NIOS 的 Avalon 总线接口是 64 位的吗? (即 NIOS 组件本身的 avs_readdata 和 avs_writedata 总线为 64 位宽)?如果是这样,那么您应该在软件中更改您的 IOWR 和 IORD 函数以采用 64 位字(无符号长长)。如果总线宽度只有 32 位(这不是您的 VHDL 示例代码显示的内容),那么我会首先尝试通过工具更改 NIOS 的 Avalon 总线宽度。根据文档,Avalon 总线配置范围为 8-1024 位。
【解决方案2】:

在您的 Nios 代码中,您写入的 0x12 与 addr 12(十六进制的 0xC)不同。

IOWR(MANDELBROT_CORE_BASE, 0x12, 0xEEEEEEEE);

你需要

IOWR(MANDELBROT_CORE_BASE, 0xC, 0xEEEEEEEE);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-24
    • 1970-01-01
    • 2014-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-24
    相关资源
    最近更新 更多