【问题标题】:FPGA to HPS communication in VHDL with FIFO使用 FIFO 的 VHDL 中的 FPGA 到 HPS 通信
【发布时间】:2020-06-30 10:28:08
【问题描述】:

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

虽然通信正常工作(因为我可以从 fpga 获取一些数据到 hps),但我有一个问题是创建一个适当的状态机,它可以使用不同的时钟向 FIFO 添加一个新值(在本例中为 12500Hz)比 50MHz 的基本时钟。其他时钟(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 的 start- 和 endofpacket 信号。

谢谢!

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;

【问题讨论】:

    标签: vhdl fpga quartus


    【解决方案1】:

    所有三个状态都正确同步到系统时钟clk_50MHz,但是第一个和第三个状态F2H_IDLEF2H_WRITESAMPLE 正在寻找clk_12500Hz 的上升沿,而您的第二个状态F2H_WAIT_START 不是不。相反,它只寻找in_fft_sop 的上升沿。这意味着第一个和第三个状态与clk_12500Hz 信号的上升沿同步,但第二个状态不与clk_12500Hz 信号同步(仅in_fft_sop 信号)。这是你想要的吗?这可以解释为什么您会在 counter_sample 上获得随机值。

    我已经重组了逻辑,以便所有状态都与系统时钟clk_50MHzclk_12500Hz 信号同步,这是我从你的问题中理解的,我假设新数据只是当out_fifo_write 为高电平时进入 FIFO。

    我还添加了三个边沿检测器以使代码更具可读性,并将第三状态的电平检测器更改为上升沿检测器。

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    
    entity FPGA2HPS is
        port
        (
            clk_50MHz: in std_logic;
            clk_12500Hz: in std_logic;
            in_reset: in std_logic;
            in_fft_sop: in std_logic;
            in_fft_eop: in std_logic;
            in_fft_real: in std_logic_vector(11 downto 0);
            in_fft_imag: in std_logic_vector(11 downto 0);
            out_fifo_write: out std_logic;
            out_fifo_writedata: out std_logic_vector(63 downto 0)
        );
    end entity;
    
    architecture V1 of FPGA2HPS is
    
        type F2H_STATES is (F2H_IDLE, F2H_WAIT_START, F2H_WRITESAMPLE);
        signal f2h_state: F2H_STATES;
        signal rising_edge_clk_12500Hz: std_logic;
        signal rising_edge_in_fft_sop: std_logic;
        signal rising_edge_in_fft_eop: std_logic;
        signal clk_12500Hz_old: std_logic;
        signal fft_sop_old: std_logic;
        signal fft_eop_old: std_logic;
        signal clk_12500Hz_alt: std_logic;
        signal counter_sample: integer;
        signal counter_wait: integer;
    
    begin
    
        --
        -- Rising edge detectors
        --
        rising_edge_clk_12500Hz <= clk_12500Hz and not clk_12500Hz_old;
        rising_edge_in_fft_sop <= in_fft_sop and not fft_sop_old;
        rising_edge_in_fft_eop <= in_fft_eop and not fft_eop_old;
    
        process(clk_50MHz, in_reset)
        begin
    
            if in_reset 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
    
                -- Ensure all the state machine logic works on the rising edge of the clk_12500Hz signal while also synchronised to the clk_50MHz clock.
                if rising_edge_clk_12500Hz 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 =>
    
                            f2h_state <= F2H_IDLE;
    
                            counter_wait <= counter_wait + 1;
                            if counter_wait = 8190 then
                                f2h_state <= F2H_WAIT_START;
                            end if;
    
                        when F2H_WAIT_START =>
    
                            f2h_state <= F2H_WAIT_START;
    
                            out_fifo_write <= '0';
    
                            if rising_edge_in_fft_sop then
                                out_fifo_write <= '1';
                                out_fifo_writedata(10 downto 0) <= std_logic_vector(to_unsigned(1, 11));  -- CHANGED
                                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 =>
    
                            f2h_state <= F2H_WRITESAMPLE;
    
                            counter_sample <= counter_sample + 1;
                            out_fifo_writedata(10 downto 0) <= std_logic_vector(to_unsigned(counter_sample, 11));  -- CHANGED
                            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 rising_edge_in_fft_eop then  -- CHANGED: Should this be on the rising edge of in_fft_eop?
                                out_fifo_write <= '0';      -- ADDED: End of write mode?
                                f2h_state <= F2H_WAIT_START;
                            end if;
    
                    end case;
                end if;
            end if;
        end process;
    
    end architecture;
    

    希望对您有所帮助,但没有 FFT 和 FIFO 的时序图,也没有测试台,我无法对其进行仿真。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多