我有一个用VHDL编写的NIOS2自定义指令,可以与我的自制FPGA组件进行通信。它从自定义指令中获取dataa和datab,并将其转换为带有地址和数据线的各种通信总线。 两者都在一个时钟周期内均为高电平,并且在2个周期后从读取的结果中回读结果。 到现在为止,这已经非常好了,使用该总线读取和写入数据都可以正常工作。 但是,我现在有一个实体,需要被写入确切的次数。 (它需要特定数量的数据字节) 这里的事情很不对劲。不知何故,每个写入操作都会处理两次,因此数据变得一团糟。
在modelsim中使用测试平台模拟自定义指令时,它确实可以实现我期望的功能。当我将自定义指令用作较大的测试平台系统的一部分时,情况相同。我已经编写了测试平台,以使进入定制指令的数据波形与NIOS2定制指令手册中的波形完全匹配。
但是,我已经在系统中的测试中确认,每个写操作在2个时钟周期内都处于激活状态。为此,我创建了一个加法器,该加法器在地址匹配的每个时钟周期将1加到一个寄存器。链接到LED。这表明,每次写操作时,寄存器都会增加2。
我找不到解释。
elsif rising_edge(clk) then
COM_Address <= (others => '0'); --default
COM_CPU_WRITE_DATA <= (others => '0'); --default
if clk_en = '1' then
case state is
when s_idle =>
if start = '1' then -- if the cpu says to start, immediately send address and data, else keep idle.
result <= (others => '0');
done <= '0';
COM_Address <= dataa(15 downto 0); -- send out the address and data provided by the cpu
COM_CPU_WRITE_DATA <= datab;
state <= s_wait_one;
else
state <= s_idle;
result <= (others => '0');
done <= '0';
COM_Address <= (others => '0');
COM_CPU_WRITE_DATA <= (others => '0');
end if;
when s_wait_one => -- wait one tick, to allow the slave to put data on the read lines.
result <= (others => '0');
done <= '0';
COM_Address <= (others => '0'); --Address and data can be put back to zeros. Only wait for reading, writing is done by now.
COM_CPU_WRITE_DATA <= (others => '0');
state <= s_reading_done;
这是nios定制指令中VHDL代码的一部分。如您所见,COM_Address和COM_CPU_WRITE_DATA线仅在单个时钟周期内为高。我什至在每个时钟周期都将它们拉为默认值0。
unsigned com_bus_simple(unsigned dataa, unsigned datab)
{
unsigned readdata;
readdata = (unsigned)ALT_CI_NIOS_FPGA_COM_0(dataa, datab);
return readdata;
}
此功能用于执行写入(和/或读取)操作。 每个实体驱动程序都将其包装在多层功能中,但是从根本上讲,这就是在FPGA中写入通信总线的内容
没有错误消息,它可以编译并模拟得很好,除了我希望(并模拟)地址线在1个时钟周期内为高电平,而在某些情况下却在2个时钟周期内为高电平。
编辑:出于无奈,我完全重写了自定义指令,现在作为扩展指令,其具体目标是确保每条指令不能将地址和数据线保持高电平一个以上的周期。那个现在工作正常。 我仍然不知道是什么使旧的失败,但是新的失败了。所以..是吗? 如果有人感兴趣,我可以发布整个新说明。