VHDL中FPGA与HPS的FIFO通信

VHDL中FPGA与HPS的FIFO通信,vhdl,fpga,quartus,Vhdl,Fpga,Quartus,我试图在Altera DE10nano开发板上实现FPGA和HPS之间的通信。要编辑vhdl,我使用Quartus Prime软件 当通信在一般情况下工作时(如我可以从fpga获取一些数据到hps),我有一个问题,即创建一个适当的状态机,该状态机可以使用不同于50MHz基准时钟的时钟(在本例中为12500Hz)向FIFO添加一个新值。其他时钟(100kHz和12500Hz)在不同的vhdl模块中生成 总体思路是在12,5kHz时钟的每个周期中写入一个样本。每个循环我都有一个计数器,它会增加,还有

我试图在Altera DE10nano开发板上实现FPGA和HPS之间的通信。要编辑vhdl,我使用Quartus Prime软件

当通信在一般情况下工作时(如我可以从fpga获取一些数据到hps),我有一个问题,即创建一个适当的状态机,该状态机可以使用不同于50MHz基准时钟的时钟(在本例中为12500Hz)向FIFO添加一个新值。其他时钟(100kHz和12500Hz)在不同的vhdl模块中生成

总体思路是在12,5kHz时钟的每个周期中写入一个样本。每个循环我都有一个计数器,它会增加,还有一些来自上游FFT的数据

我在HPS中使用一个简单的C代码来读取fifo并将读取的值保存到一个.csv文件中

现在,问题是:当我使用我的板来加载我的设计时,我没有得到正确的样本号。我在.csv文件中获得随机值(来自“counter_sample”),而状态机的模拟(使用ModelSim)正在执行我希望它执行的操作。 此外,当我使用100kHz时钟触发该过程时,该设计确实工作良好,但我被告知这是一种糟糕的做法,因为时钟不是由pll生成的。这也让我认为这不是使用C代码的问题

我得到的随机值不是连续的,而是彼此相隔200-300个计数器值

我不是vhdl编程方面的老手(你可能知道),但我会在下面复制我的状态机。我很高兴听到你的意见,并将提供进一步的信息,如果需要的话

fft_sop和fft_eop信号是来自上游fft的启动和结束分组信号

谢谢

process(Clk_50MHz, in_reset)
begin

    if (in_reset = '1') then 
        f2h_state <= f2h_idle;
        counter_sample <=0;
        counter_wait <=0;
        out_fifo_write <='0';
        out_fifo_writedata <= (others => '0');
        fft_sop_old <= '0';
        fft_eop_old <= '0';
        Clk_12500Hz_alt<='0';
        
    elsif(rising_edge(Clk_50MHz)) then
        fft_sop_old <= in_fft_sop;
        fft_eop_old <= in_fft_eop;
        Clk_12500Hz_old <= Clk_12500Hz;
    
        case f2h_state is

            when f2h_idle =>
                if ((Clk_12500Hz = '1') and (Clk_12500Hz_old = '0')) then
                    counter_wait <= counter_wait + 1;
                    if counter_wait = 8190 then
                        f2h_state <= f2h_wait_start;
                    else 
                        f2h_state <= f2h_idle;
                    end if;
                else
                f2h_state <= f2h_idle;
                end if;
            
            when    f2h_wait_start =>
            
                out_fifo_write <= '0';

                if ((in_fft_sop = '1') and (fft_sop_old = '0')) then
                    out_fifo_write <= '1';
                    out_fifo_writedata(10 downto 0) <= conv_std_logic_vector(1, 11);
                    counter_sample <= 2;
                    out_fifo_writedata(22 downto 11) <= in_fft_real(11 downto 0);
                    out_fifo_writedata(34 downto 23) <= in_fft_imag(11 downto 0);
                    out_fifo_writedata(63 downto 35) <= (others => '0');
                    f2h_state <= f2h_writesample;
                end if;
            
            when    f2h_writesample =>
                
                if ((Clk_12500Hz = '1') and (Clk_12500Hz_old = '0')) then
                    out_fifo_write <= '1';
                    counter_sample <= counter_sample + 1;
                    out_fifo_writedata(10 downto 0) <= conv_std_logic_vector(counter_sample, 11);
                    out_fifo_writedata(22 downto 11) <= in_fft_real(11 downto 0);
                    out_fifo_writedata(34 downto 23) <= in_fft_imag(11 downto 0);
                    out_fifo_writedata(63 downto 35) <= (others => '0');
                    
                    if in_fft_eop = '1' then
                         f2h_state <= f2h_wait_start;
                    end if;

                    f2h_state <= f2h_writesample;
                else
                    out_fifo_write <= '0';
                end if;

                
        end case;
    end if;
end process;
过程(时钟50MHz,输入复位)
开始
如果(in_reset='1'),则

f2h_状态所有三种状态都正确地与系统时钟同步
clk_50MHz
,但是第一和第三种状态,
f2h_空闲
f2h_写入示例
,正在寻找
clk_12500Hz
的上升沿,而您的第二种状态
f2h_等待_启动
。相反,它只是在寻找fft sop中
的上升沿。这意味着第一和第三状态与
clk_12500Hz
信号的上升沿同步,但第二状态与
clk_12500Hz
信号不同步(仅与
in_fft_sop
信号同步)。这是你想要的吗?这可以解释为什么在
计数器样本上获得随机值

我重新构造了逻辑,使所有状态同步到系统时钟
clk_50MHz
clk_12500Hz
信号,这是我从您的问题中了解到的,并且我假设当
out_FIFO\u write
较高时,新数据只需进入FIFO

我还添加了三个边缘检测器,使代码更具可读性,并将处于第三种状态的级别检测器更改为上升边缘检测器

ieee库;
使用ieee.std_logic_1164.all;
使用ieee.numeric_std.all;
实体FPGA2HPS为
港口
(
时钟50MHz:标准逻辑中;
时钟12500Hz:标准逻辑中;
in_复位:in-std_逻辑;
in_fft_sop:标准逻辑中;
in_fft_eop:标准逻辑中;
in_fft_real:in std_逻辑_向量(11向下至0);
in_fft_imag:in std_逻辑_向量(11向下至0);
输出fifo写入:输出标准逻辑;
输出fifo写入数据:输出标准逻辑向量(63到0)
);
终端实体;
FPGA2HPS的架构V1为
类型F2H_状态为(F2H_空闲、F2H_等待_启动、F2H_写入示例);
信号f2h_状态:f2h_状态;
信号上升沿时钟12500Hz:标准逻辑;
fft sop中的信号上升沿:标准逻辑;
fft eop中的信号上升沿:标准逻辑;
信号时钟12500Hz旧:标准逻辑;
信号fft\U sop\U old:标准逻辑;
信号fft\U eop\U old:标准逻辑;
信号clk_12500Hz_alt:std_逻辑;
信号计数器样本:整数;
信号计数器等待:整数;
开始
--
--上升沿探测器
--

上升沿clk_12500Hz所有三种状态都正确地与系统时钟同步
clk_50MHz
,但是第一和第三种状态,
F2H_IDLE
F2H_WRITESAMPLE
,正在寻找
clk_12500Hz
的上升沿,而第二种状态
F2H_WAIT_START
则不是。相反,它只是在寻找fft sop中
的上升沿。这意味着第一和第三状态与
clk_12500Hz
信号的上升沿同步,但第二状态与
clk_12500Hz
信号不同步(仅与
in_fft_sop
信号同步)。这是你想要的吗?这可以解释为什么在
计数器样本上获得随机值

我重新构造了逻辑,使所有状态同步到系统时钟
clk_50MHz
clk_12500Hz
信号,这是我从您的问题中了解到的,并且我假设当
out_FIFO\u write
较高时,新数据只需进入FIFO

我还添加了三个边缘检测器,使代码更具可读性,并将处于第三种状态的级别检测器更改为上升边缘检测器

ieee库;
使用ieee.std_logic_1164.all;
使用ieee.numeric_std.all;
实体FPGA2HPS为
港口
(
时钟50MHz:标准逻辑中;
时钟12500Hz:标准逻辑中;
in_复位:in-std_逻辑;
in_fft_sop:标准逻辑中;
in_fft_eop:标准逻辑中;
in_fft_real:in std_逻辑_向量(11向下至0);
in_fft_imag:in std_逻辑_向量(11向下至0);
输出fifo写入:输出标准逻辑;
输出fifo写入数据:输出标准逻辑向量(63到0)
);
终端实体;
FPGA2HPS的架构V1为
类型F2H_状态为(F2H_空闲、F2H_等待_启动、F2H_写入示例);
信号f2h_状态:f2h_状态;
信号上升沿时钟12500Hz:标准逻辑;
信号ri