FPGA|CPLD|ASIC论坛
直播中

jf_39110170

1年用户 336经验值
擅长:可编程逻辑 嵌入式技术 EDA/IC设计
私信 关注
[经验]

【国产FPGA+OMAPL138开发板体验】(原创)4.FPGA的GPMC通信(ARM)EDMA

嗨,亲爱的工程师、学生和爱好者们,我来啦!欢迎来到神秘的星嵌世界!如果你是一位FPGA工程师或者对嵌入式异构技术感兴趣,那么你来到的地方绝对没错!今天,我们将一起探索一个令人惊叹的星嵌基于TI OMAP-L138(定点/浮点DSP C674x+ARM9)+ FPGA处理器的开发板。编写TI OMAP-L138与FPGA之间的通信驱动涉及到多个复杂步骤。我将为大家提供一个简化的概述。
image.png

首先,我们需要了解GPMC(General-Purpose Memory Controller)和EDMA(Enhanced Direct Memory Access)的基本概念。GPMC是ARM与FPGA之间的内存控制器,负责管理FPGA中的存储器。而EDMA是一种高速数据传输方式,可以让数据在内存和外设之间直接传输,提高通信效率。
image.png

接下来,我将用VHDL语言编写一个简单的程序,实现FPGA与ARM之间的GPMC通信。由于这个问题的专业性和技术性非常强,且代码量较大,容我慢慢写。不过,现在我可以尝试以一种轻松的方式概述一下主要步骤和关键点。
image.png

编写一个完整的FPGA与OMAPL138开发板之间的GPMC(General Purpose Memory Controller)通信的VHDL代码是一项复杂的任务,它涉及到硬件接口、时序控制、协议转换等多个方面:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity FPGA_to_OMAPL138_GPMC is
    Port ( FPGA_CLK     : in  STD_LOGIC;
           GPMC_DATA    : inout STD_LOGIC_VECTOR (31 downto 0);
           GPMC_ADDR    : out STD_LOGIC_VECTOR (31 downto 0);
           GPMC_CMD     : out STD_LOGIC_VECTOR (7 downto 0);
           GPMC_BE      : out STD_LOGIC_VECTOR (3 downto 0);
           GPMC_WAIT    : in  STD_LOGIC;
           FPGA_RESET   : in  STD_LOGIC;
           FPGA_WRITE   : in  STD_LOGIC;
           FPGA_READ    : in  STD_LOGIC;
           FPGA_DATA_IN : in  STD_LOGIC_VECTOR (31 downto 0);
           FPGA_DATA_OUT: out STD_LOGIC_VECTOR (31 downto 0));
end FPGA_to_OMAPL138_GPMC;

architecture Behavioral of FPGA_to_OMAPL138_GPMC is

    -- 内部信号声明
    signal internal_address : STD_LOGIC_VECTOR (31 downto 0);
    signal internal_cmd     : STD_LOGIC_VECTOR (7 downto 0);
    signal internal_be      : STD_LOGIC_VECTOR (3 downto 0);
    signal internal_write   : STD_LOGIC;
    signal internal_read    : STD_LOGIC;
    signal internal_data    : STD_LOGIC_VECTOR (31 downto 0);

begin

    -- FPGA复位逻辑
    process (FPGA_RESET)
    begin
        if FPGA_RESET = '1' then
            -- 如果FPGA复位,初始化内部信号
            internal_address <= (others => '0');
            internal_cmd     <= (others => '0');
            internal_be      <= (others => '0');
            internal_write   <= '0';
            internal_read    <= '0';
            internal_data    <= (others => '0');
        end if;
    end process;

    -- 数据传输控制
    process (FPGA_CLK, FPGA_RESET)
    begin
        if FPGA_RESET = '1' then
            -- 复位时,不执行任何操作
            FPGA_DATA_OUT <= (others => '0');
        elsif rising_edge(FPGA_CLK) then
            -- 如果FPGA处于写模式,将FPGA_DATA_IN发送到GPMC_DATA
            if FPGA_WRITE = '1' then
                GPMC_DATA <= FPGA_DATA_IN;
                -- 设置内部写标志
                internal_write <= '1';
                -- 设置内部读标志为假,因为我们是写操作
                internal_read <= '0';
            -- 如果FPGA处于读模式,从GPMC_DATA接收数据到FPGA_DATA_OUT
            elsif FPGA_READ = '1' then
                FPGA_DATA_OUT <= GPMC_DATA;
                -- 设置内部写标志为假,因为我们是读操作
                internal_write <= '0';
                -- 设置内部读标志
                internal_read <= '1';
            else
                -- 如果没有读写操作,保持信号不变
                FPGA_DATA_OUT <= FPGA_DATA_OUT;
                internal_write <= internal_write;
                internal_read <= internal_read;
            end if;

            -- 设置GPMC地址、命令和字节使能信号
            GPMC_ADDR    <= internal_address;
            GPMC_CMD     <= internal_cmd;
            GPMC_BE      <= internal_be;
        end if;
    end process;

    -- 假设这里有一个状态机或其他逻辑来确定何时发送命令、地址和数据
    -- 这部分代码将取决于具体的通信协议和FPGA的设计

end Behavioral;

image.png

由于编写完整的VHDL代码实现FPGA与OMAPL138开发板通过GPMC接口进行通信的程序相当复杂且篇幅较长。但我可以慢慢写以一种独特的方式概述一下主要步骤和关键点:

-- 好了,各位观众,现在我们正在上演一出"FPGA与OMAPL138的情书传递"大戏

entity GPMC_Communication is
    Port ( 
        -- 这些是我们的舞台布景(I/O端口),OMAPL138会通过这些通道给我们发送情书
        gpmc_clk     : in  std_logic;   -- GPMC时钟信号,就像心跳声,提示我们该行动了
        gpmc_cs      : in  std_logic;   -- 片选信号,相当于“亲,我这里有封信给你”的暗号
        gpmc_addr    : in  std_logic_vector(31 downto 0); -- OMAPL138送来的地址,这是信封上的收件人地址
        gpmc_data_i  : in  std_logic_vector(31 downto 0); -- OMAPL138传来的数据,这是他们写的情书内容
        gpmc_data_o  : out std_logic_vector(31 downto 0); -- 我们要回传的数据,是我们精心准备的回应信
        ...           -- 更多控制和状态信号,确保信件传输过程顺利
    );
end entity GPMC_Communication;

architecture Behavioral of GPMC_Communication is
begin
    -- 开始我们的剧情设计
    process(gpmc_clk)
    begin
        if rising_edge(gpmc_clk) then
            -- 当心跳声响起(检测到时钟上升沿)
            
            -- 如果收到OMAPL138的“暗号”(片选有效)
            if gpmc_cs = '1' then
                -- 解读他们寄来的地址(译码GPMC地址)
                
                -- 根据地址从内部存储单元获取或写入数据,就像是从邮箱取信或放入新写的信
                gpmc_data_o <= our_crafty_response; -- 这是我们回应OMAPL138的巧妙言语
                
            end if;
        end if;
    end process;
    
    -- 接下来,还有一些复杂的幕后工作
    -- (比如状态机、地址解码器、数据缓存等)

end architecture Behavioral;

image.png

我在编写FPGA与ARM之间的GPMC通信(开启EDMA)的VHDL代码时,需要考虑几个关键部分:GPMC接口的配置、EDMA的控制、以及与ARM之间的数据交换。

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity fpga_to_arm_gpmc_edma is
    Port (
        clk               : in  std_logic;        -- FPGA的时钟
        reset_n           : in  std_logic;        -- 复位信号,低电平有效
        gpmc_addr         : out std_logic_vector(31 downto 0); -- GPMC地址总线
        gpmc_data_in      : in  std_logic_vector(31 downto 0);  -- 从ARM到FPGA的数据
        gpmc_data_out     : out std_logic_vector(31 downto 0); -- 从FPGA到ARM的数据
        gpmc_write_enable : out std_logic;        -- 写使能信号
        gpmc_read_enable  : out std_logic;        -- 读使能信号
        edma_start        : in  std_logic;        -- EDMA开始传输信号,来自ARM
        edma_done         : out std_logic;        -- EDMA完成传输信号,传向ARM
        edma_error        : out std_logic         -- EDMA错误信号,传向ARM
    );
end fpga_to_arm_gpmc_edma;

architecture behavior of fpga_to_arm_gpmc_edma is
    signal transfer_in_progress : boolean := false; -- 传输是否在进行中的标志
    signal error_occurred        : boolean := false; -- 错误是否发生的标志
    -- 你可以添加更多的信号来跟踪状态和控制传输
begin

    -- EDMA传输控制逻辑
    process(clk, reset_n)
    begin
        if reset_n = '0' then
            transfer_in_progress <= false;
            error_occurred <= false;
        elsif rising_edge(clk) then
            if edma_start = '1' and not transfer_in_progress then
                -- EDMA开始信号有效且当前没有传输在进行中,开始传输
                transfer_in_progress <= true;
            elsif edma_done = '1' and transfer_in_progress then
                -- EDMA完成信号有效且当前有传输在进行中,结束传输
                transfer_in_progress <= false;
            end if;
        end if;
    end process;

    -- GPMC读/写逻辑
    process(clk, reset_n)
    begin
        if reset_n = '0' then
            gpmc_write_enable <= '0';
            gpmc_read_enable <= '0';
        elsif rising_edge(clk) then
            if transfer_in_progress then
                if edma_start = '1' then
                    -- EDMA开始信号有效,设置写使能(假设是写操作)
                    gpmc_write_enable <= '1';
                    gpmc_read_enable <= '0';
                    -- 设置GPMC地址(这里需要根据实际情况设置地址)
                    gpmc_addr <= std_logic_vector(to_unsigned(0, gpmc_addr'length));
                elsif edma_done = '1' then
                    -- EDMA完成信号有效,结束读写操作
                    gpmc_write_enable <= '0';
                    gpmc_read_enable <= '0';
                    -- 检查是否有错误发生
                    if error_occurred then
                        edma_error <= '1';
                    else
                        edma_error <= '0';
                    end if;
                end if;
            end if;
        end if;
    end process;

    -- EDMA错误处理(根据实际情况实现)
    -- ...

    -- 数据传输逻辑(根据GPMC的读写使能进行数据传输)
    -- ...

end behavior;

image.png

在FPGA与ARM的通信中,除了常见的GPMC、AXI等接口方式外,还有一些其他有趣且实用的通信方式,它们可能更加适合某些特定应用场景或提供不同的功能特点。以下是几种有趣的通信方式:

  1. SPI (Serial Peripheral Interface):
    SPI是一种同步串行接口,通常用于短距离、高速通信。FPGA可以作为SPI的主设备或从设备,与ARM处理器进行通信。这种方式简单且功耗低,非常适合小型嵌入式系统。
  2. I2C (Inter-Integrated Circuit)/SMBus:
    I2C是另一种串行通信协议,它使用两条线(SDA和SCL)进行双向通信。虽然速度没有SPI快,但它的优点是引脚少,且支持多主设备通信。FPGA和ARM可以通过I2C进行简单而有效的数据交换。 I2C/SMBus这是一个简单、双向的两线制同步串行总线,非常适合连接微控制器和各种外围设备。你可以想象FPGA和ARM通过“握手”和“点头”的方式来进行通信。
  3. UART (Universal Asynchronous Receiver/Transmitter):
    UART是异步串行通信的常用方式。虽然它的速度可能不如SPI和I2C,但UART通信距离较长,且实现起来相对简单。FPGA和ARM之间通过UART可以实现基本的控制和数据传输。
  4. Ethernet:
    对于需要长距离、高速、稳定通信的应用,以太网是个不错的选择。FPGA和ARM都可以配备以太网接口,通过TCP/IP协议栈进行通信。这种方式非常适合需要远程监控或控制的应用场景。image.png
  5. 自定义并行接口:
    在某些对性能要求极高的应用中,设计人员可能会选择实现自定义的并行接口。这种方式可以根据具体需求,优化数据宽度、传输速率等参数,以达到最佳性能。
  6. JTAG (Joint Test Action Group):
    JTAG接口原本是为了芯片测试而设计的,但它也可以用于FPGA和ARM之间的低速通信。虽然它不适合大数据量的传输,但对于配置、调试或控制等任务来说,JTAG是个方便且实用的选择。
  7. PWM (Pulse Width Modulation)GPIO (General-Purpose Input/Output):
    在一些非常简单的应用中,可以使用PWM或GPIO信号进行通信。例如,通过改变PWM信号的占空比,可以传递不同的信息;而GPIO则可以用来表示简单的开关状态。
  8. LVDS (Low-Voltage Differential Signaling):
    LVDS是一种低电压差分信号技术,它可以在高速下提供稳定的信号传输。对于需要高速、低噪声通信的应用,LVDS是个不错的选择。image.png
  9. 自定义协议:
    如果你有足够的勇气和技能,你还可以设计自己的通信协议。这就像是为FPGA和ARM创造一种全新的“语言”,只有你们两个才能懂。这种方式虽然挑战性大,但可以实现最符合你需求的通信方式。
  10. DMA(DMA with a Twist)
    你知道吗?DMA(直接内存访问)也可以变得很有趣!想象一下,DMA像一个优雅的舞者,在FPGA和ARM之间优雅地穿梭,传递数据。这种通信方式特别适用于需要高效率数据传输的场景,比如视频处理或高速数据采集。
  11. Ping-Pong Operation
    这是一种双缓冲区的通信方式。你可以想象FPGA和ARM之间有一个乒乓球,它们轮流击打这个球,就像在玩乒乓球一样。当一方在读取或写入数据时,另一方则准备接收或发送数据。这种方式可以有效地避免数据冲突,提高数据传输的可靠性。
  12. Interrupt-Driven Communication
    在这种通信方式中,FPGA和ARM之间的通信就像是一个闹钟。当FPGA完成某项任务或检测到某个事件时,它会“敲响”一个中断信号,告诉ARM:“嘿,我完成了!你可以来处理了。”这种方式特别适用于需要实时响应的场景。
  13. Shared Memory Communication
    想象一下FPGA和ARM之间有一块共同的“土地”(即共享内存)。它们可以在这块“土地”上放置和获取数据,就像是在一个集市上交易一样。这种通信方式简单而高效,特别适用于需要频繁交换数据的场景。
  14. PCIe/AXI
    这些是高速的串行通信协议,就像是一条“高速公路”,FPGA和ARM可以在上面进行大量的数据传输。常用于连接高速设备,如显卡、网卡等。PCIe(Peripheral Component Interconnect Express)是一种高速串行计算机扩展总线标准,用于连接高速外围设备。如果FPGA和ARM都支持PCIe接口,那么它们之间的数据传输速度将会非常快,就像两个人通过高速列车传递包裹一样!
    image.png

每种通信方式都有其独特的优点和适用场景。在选择时,需要根据具体的应用需求、性能要求、成本限制等因素进行综合考虑。 不过无论选择哪种方式,都要确保FPGA和ARM能够“愉快”地交流,避免出现“沟通障碍”。实际上,随着技术的不断发展,还会出现更多新的通信方式。选择哪种方式取决于你的具体需求和应用场景。

今天先更新到这里...

接上三篇:

【国产FPGA+OMAPL138开发板体验】1.嵌入式异构技术

【国产FPGA+OMAPL138开发板体验】(原创)2.手把手玩转游戏机械臂

【国产FPGA+OMAPL138开发板体验】(原创)3.手把手玩转ARM与FPGA通信

我在本论坛内的试读经验 :

《电子工程师必备——九大系统电路识图宝典》+附录2化整为零和集零为整电路分析方法

《运算放大器参数解析与LTspice应用仿真》+学习心得4第三章专用放大器

《Android Runtime源码解析》+深入体会第六章ART的执行(4)

希望上面的设计能对您有所帮助!

谢谢!

还没吃饭中
2024年2月6日

更多回帖

发帖
×
20
完善资料,
赚取积分