关于这个问题的第一个背景故事。在我目前的项目中,我尝试创建一个使用FPGA优化的Mandelbrot计算器。此时我试图在nios处理器和FPGA之间建立一个桥梁(遗憾的是没有运气)。
我试图使用Avalon总线了解nios和FPGA(运行VHDL)之间的通信。我现在已经使用VHDL超过15周了,并且在过去的5周内开始使用nios 2处理器。现在我要完成的事情如下: 所以我想创建一个设置,我可以测试发送两次64位值,记住VHDL中的这个值,他们尝试读取它,以便它回到Nios 2处理器上(用C代码)。
在我尝试自己解决这个问题之前,我没有把这个问题放在这里。这是我迄今为止所做的工作。
在nios上我创建了一个简单的设置,主要向FPGA写入两个64位值,然后将它们转发并显示红色和绿色指示灯上的输出,顺便说一下:我在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总线相连。应该处理incomming和传出请求的组件是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;
对我而言,这个设置应该可行,但是当我尝试测试整个事情时它看起来似乎不应该起作用。很明显,我在这里做错了,也许有经验的人可以看看它。希望有人能尽快帮助我。
提前致谢。
答案 0 :(得分:4)
我没有专门与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。
答案 1 :(得分:0)
在您的Nios代码中,您正在写入0x12,这与addr 12(十六进制为0xC)不同。
IOWR(MANDELBROT_CORE_BASE, 0x12, 0xEEEEEEEE);
你需要
IOWR(MANDELBROT_CORE_BASE, 0xC, 0xEEEEEEEE);