搜索
bottom↓
回复: 30

ARM与FPGA之间的数据传输(出现问题,请高手帮忙,附源程序)

[复制链接]

出0入0汤圆

发表于 2010-2-24 10:20:55 | 显示全部楼层 |阅读模式
ARM与FPGA之间的数据传输:
ARM(主)负责分析处理数据,FPGA(从)负责收集存储数据,两者之间通过地址/数据总线方式通信(不复用),下面是我编写的通信程序。ARM通过FPGA的内部RAM对数据进行读写处理。开发软件libero,在仿真中数据读写都正确,写到板子上功能就不对了,大家给分析下我写的程序是否有问题,谢谢!
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
----FPGA内部寄存器地址定义:
package  interface is
constant addr_reg1 : std_logic_vector(9 downto 0) := "0000000000";
constant addr_reg2 : std_logic_vector(9 downto 0) := "0000000001";
constant addr_reg3 : std_logic_vector(9 downto 0) := "0000000010";
constant addr_reg4 : std_logic_vector(9 downto 0) := "0000000011";
end;


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use work.interface.all;

entity arm_fpga is
port(
mcudata : inout std_logic_vector(7 downto 0);--8位数据
mcuaddress : in std_logic_vector(9 downto 0);--10位地址
wr : in std_logic;--写信号
rd : in std_logic;
cs : in std_logic;
led : out std_logic_vector(7 downto 0));
end;

architecture  armfpga of arm_fpga is
signal  addresstemp : std_logic_vector(9 downto 0);--内部寄存器
signal  datatemp1, datatemp2, datatemp3, datatemp4 : std_logic_vector(7 downto 0);
signal  wr_en,rd_en : std_logic;--读写使能

begin
addresstemp <= mcuaddress;
wr_en <= (wr and rd) or wr;
rd_en <= (wr and rd) or rd;
--ARM写数据到FPGA:
process(wr,wr_en)
begin
if  wr'event and wr = '0' then
if cs = '0'and  wr_en = '0' then
case addresstemp is
when addr_reg1 =>
datatemp1 <= mcudata;

when addr_reg2 =>
datatemp2 <= mcudata;

when addr_reg3 =>
datatemp3 <= mcudata;

when addr_reg4 =>
datatemp4 <= mcudata;

when others => null;
end case;
end if;
end if;
end process;
--ARM从FPGA读取数据:
process(rd,rd_en)
begin
if  rd'event and rd = '0'  then
if cs = '0' and rd_en = '0' then
case addresstemp is
when addr_reg1 =>
mcudata <= datatemp1;

when addr_reg2 =>
mcudata <= datatemp2;

when addr_reg3 =>
mcudata <= datatemp3;

when addr_reg4 =>
mcudata <= datatemp4;

when others => null;
end case;
end if;
end if;
end process;

led <= mcudata; --验证传输数据,LED显示
end;


还有一个问题,我在综合的时候出现了一个警告:
Failed to find top level module 'work.arm_fpga' as specified in project file
这是什么原因?没搞明白

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2010-2-24 12:26:31 | 显示全部楼层
mcudata是双向总线,在没有输出时要输出'Z'

出0入0汤圆

 楼主| 发表于 2010-2-24 13:05:38 | 显示全部楼层
回复【1楼】liurangzhou
mcudata是双向总线,在没有输出时要输出'Z'
-----------------------------------------------------------------------

行,我加上试试

出0入0汤圆

 楼主| 发表于 2010-2-24 13:55:01 | 显示全部楼层
回复【2楼】liu_jing_yang
-----------------------------------------------------------------------
高手来啊

出0入4汤圆

发表于 2010-2-24 14:08:19 | 显示全部楼层
wr_en <= (wr and rd) or wr;
rd_en <= (wr and rd) or rd;    ?? 这个是什么逻辑,不明白.

其实用简单的锁存就可以了, 代码总共10行. 而且地址用低2位就可以了
写:
datatemp1 <= mcudata when( cs='0' and wr='0' and addresstemp = "00");
datatemp2 <= mcudata when( cs='0' and wr='0' and addresstemp = "01");
.....

读:
mcudata <= datatemp1 when( cs='0 and rd='0' and addresstemp = "00") else
           datatemp2 when( cs='0 and rd='0' and addresstemp = "01") else
           ................
           "ZZZZZZZZ";      -- "ZZ"不可少,否则总线被FPGA锁死.

出0入0汤圆

 楼主| 发表于 2010-2-24 15:10:57 | 显示全部楼层
回复【4楼】qinxg
-----------------------------------------------------------------------
先感谢你的帮助!
wr_en,rd_en是读写使能信号
地址线是10位 因为数据传输的原因,8位不够
我照你写的编了下,正在调试中
感觉逻辑关系比较简单,不知道这么写能实现ARM与FPGA的通信不?我觉得关键是ARM通过地址线读取FPGA内部RAM的数据,为啥实现不了?

出0入0汤圆

发表于 2010-2-24 15:48:00 | 显示全部楼层
回复【3楼】liu_jing_yang
回复【2楼】liu_jing_yang  
-----------------------------------------------------------------------
高手来啊
-----------------------------------------------------------------------

行还是不行?

出0入0汤圆

发表于 2010-2-24 17:45:09 | 显示全部楼层
回复【3楼】liu_jing_yang
回复【2楼】liu_jing_yang  
-----------------------------------------------------------------------
高手来啊
-----------------------------------------------------------------------

问题解决了没?

出0入0汤圆

 楼主| 发表于 2010-2-25 14:24:28 | 显示全部楼层
回复【7楼】liurangzhou
-----------------------------------------------------------------------

-- mcufpga.vhd

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
----FPGA内部寄存器地址定义:
package  interface is
constant addr_reg1 : std_logic_vector(9 downto 0) := "0000000000";
constant addr_reg2 : std_logic_vector(9 downto 0) := "0000000001";
constant addr_reg3 : std_logic_vector(9 downto 0) := "0000000010";
constant addr_reg4 : std_logic_vector(9 downto 0) := "0000000011";
end;

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use work.interface.all;

entity arm_fpga is
port(
mcudata : inout std_logic_vector(7 downto 0);--8位数据
mcuaddress : in std_logic_vector(9 downto 0);--10位地址
wr : in std_logic;--写信号
rd : in std_logic;
cs : in std_logic;
led : out std_logic_vector(7 downto 0));
end;

architecture  armfpga of arm_fpga is
signal  addresstemp : std_logic_vector(9 downto 0);--内部寄存器
signal  datatemp : std_logic_vector(31 downto 0);
--signal  wr_en,rd_en : std_logic;--读写使能

begin
addresstemp <= mcuaddress;

--ARM写数据到FPGA:
process(wr,cs)
begin

--datatemp1 <= mcudata  when  (cs= '0' and wr = '0' and addresstemp = addr_reg1);
if wr'event and wr = '0' and cs = '0' then
case addresstemp is
when addr_reg1 => datatemp(7 downto 0) <= mcudata;
when addr_reg2 => datatemp(15 downto 8) <= mcudata;
when addr_reg3 => datatemp(23 downto 16) <= mcudata;
when addr_reg4 => datatemp(31 downto 24) <= mcudata;
when others => null;
end case;
end if;
end process;

--ARM从FPGA读取数据:
process(rd,cs)
begin

if rd'event and rd = '0' and cs = '0' then
--case addresstemp is
--when addr_reg1 => mcudata <= datatemp(7 downto 0);
--when addr_reg2 => mcudata <= datatemp(15 downto 8);
--when addr_reg3 => mcudata <= datatemp(23 downto 16);
--when addr_reg4 => mcudata <= datatemp(31 downto 24);
--when others => mcudata <= "ZZZZZZZZ";
mcudata <=
datatemp(7 downto 0) when (addresstemp = addr_reg1) else
datatemp(15 downto 8) when (addresstemp = addr_reg2) else
datatemp(23 downto 16) when (addresstemp = addr_reg3) else
datatemp(31 downto 24) when (addresstemp = addr_reg4) else
"ZZZZZZZZ";
end case;
end if;
end process;
led <= mcudata;
end;

哥们 你在 软件上编译一下,我这里怎么就是不对啊?读数据进程
老是提示WHEN处错误

出0入0汤圆

 楼主| 发表于 2010-2-25 14:25:27 | 显示全部楼层
回复【7楼】liurangzhou
-----------------------------------------------------------------------

编译错误提示:
ERROR: syntax error near when (VHDL-1261)
读数据进程出现的错误提示

出0入0汤圆

 楼主| 发表于 2010-2-25 14:26:32 | 显示全部楼层
回复【4楼】qinxg
wr_en &lt;= (wr and rd) or wr;  
rd_en &lt;= (wr and rd) or rd;    ?? 这个是什么逻辑,不明白.  
其实用简单的锁存就可以了, 代码总共10行. 而且地址用低2位就可以了
写:  
datatemp1 &lt;= mcudata when( cs='0' and wr='0' and addresstemp = "00");
datatemp2 &lt;= mcudata when( cs='0' and wr='0' and addresstemp = "01");
.....
读:
mcudata &lt;= datatemp1 when( cs='0 and rd='0' and addresstemp = "00") else
           datatemp2 when( cs='0 and ......
-----------------------------------------------------------------------

哥们 我照你说的编译了一下,结果没通过编译,RD进程出现错误提示,ERROR: syntax error near when (VHDL-1261)

出0入4汤圆

发表于 2010-2-25 14:48:57 | 显示全部楼层
楼主误解了. 不需要进程, 只是简单的并行语句,不需要rd,wr的时钟逻辑.


-----------------------------------------------------------------------

-- mcufpga.vhd

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity arm_fpga is
port(
mcudata : inout std_logic_vector(7 downto 0);--8位数据
mcuaddress : in std_logic_vector(9 downto 0);--10位地址
wr : in std_logic;--写信号
rd : in std_logic;
cs : in std_logic;
led : out std_logic_vector(7 downto 0));
end;

architecture  armfpga of arm_fpga is
signal  addresstemp : std_logic_vector(1 downto 0);--内部寄存器
signal  datatemp : std_logic_vector(31 downto 0);

begin
addresstemp <= mcuaddress(1 downto 0);

--ARM写数据到FPGA:
datatemp(7 downto 0) <= mcudata when( cs='0' and wr='0' and addresstemp = "00");
datatemp(15 downto 8)  <= mcudata when( cs='0' and wr='0' and addresstemp = "01");
datatemp(23 downto 16)  <= mcudata when( cs='0' and wr='0' and addresstemp = "10");
datatemp(31 downto 24)  <= mcudata when( cs='0' and wr='0' and addresstemp = "11");


--ARM从FPGA读取数据:
mcudata <= datatemp(7 downto 0) when( cs='0 and rd='0' and addresstemp = "00") else
           datatemp(15 downto 8) when( cs='0 and rd='0' and addresstemp = "01") else
           datatemp(23 downto 16) when( cs='0 and rd='0' and addresstemp = "10") else
           datatemp(31 downto 24) when( cs='0 and rd='0' and addresstemp = "11") else
           "ZZZZZZZZ";      -- "ZZ"不可少,否则总线被FPGA锁死.

led <= mcudata;

end armfpga ;

出0入0汤圆

发表于 2010-2-25 16:09:48 | 显示全部楼层
回复【9楼】liu_jing_yang
回复【7楼】liurangzhou  
-----------------------------------------------------------------------
编译错误提示:
ERROR: syntax error near when (VHDL-1261)
读数据进程出现的错误提示
-----------------------------------------------------------------------

在进程中条件为时钟边沿的IF里面不能这样写

出0入0汤圆

 楼主| 发表于 2010-2-25 16:31:36 | 显示全部楼层
回复【11楼】qinxg
-----------------------------------------------------------------------

回复【11楼】qinxg
楼主误解了. 不需要进程, 只是简单的并行语句,不需要rd,wr的时钟逻辑.
-----------------------------------------------------------------------  
-- mcufpga.vhd  
library ieee;  
use ieee.std_logic_1164.all;  
use ieee.std_logic_arith.all;  
use ieee.std_logic_unsigned.all;  
entity arm_fpga is  
port(  
mcudata : inout std_logic_vector(7 downto 0);--8位数据  
mcuaddress : in std_logic_vector(9 downto 0);--10位地址  
wr : in std_logic......
-----------------------------------------------------------------------

哥们 ,能这么写吗?我调调试试把,怎么感觉好象优点问题啊,没有了WR  RD 信号指令,单片机怎么读写FPGA内部RAM的数据? 相当于没有时序了啊

出0入0汤圆

 楼主| 发表于 2010-2-25 16:32:52 | 显示全部楼层
回复【12楼】liurangzhou
回复【9楼】liu_jing_yang  
回复【7楼】liurangzhou   
-----------------------------------------------------------------------  
编译错误提示:  
ERROR: syntax error near when (VHDL-1261)  
读数据进程出现的错误提示
-----------------------------------------------------------------------
在进程中条件为时钟边沿的IF里面不能这样写
-----------------------------------------------------------------------

恩 写的语句不对,经过调试已经修改正确了~

出0入0汤圆

 楼主| 发表于 2010-2-25 16:38:35 | 显示全部楼层
首先感谢论坛的朋友qinxg  和liurangzhou  的热心帮助  少后我上传个单片机与FPGA通讯的PDF文件,希望能对研究此类项目的朋友有所帮助,不过我这个通讯问题还没有解决,我也正在努力调试中,同时也希望能得到更多的朋友的帮助!

出0入0汤圆

发表于 2010-2-25 21:07:14 | 显示全部楼层
回复【15楼】liu_jing_yang
首先感谢论坛的朋友qinxg  和liurangzhou  的热心帮助  少后我上传个单片机与FPGA通讯的PDF文件,希望能对研究此类项目的朋友有所帮助,不过我这个通讯问题还没有解决,我也正在努力调试中,同时也希望能得到更多的朋友的帮助!
-----------------------------------------------------------------------

这个问题并不复杂,你可以用内部逻辑分析仪看下问题

出0入0汤圆

 楼主| 发表于 2010-2-26 07:53:51 | 显示全部楼层
回复【楼主位】liu_jing_yang
-----------------------------------------------------------------------

上传个单片机与FPGA通信的PDF资料,有原理和原程序
单片机与FPGA通信的PDF资料,有原理和原程序ourdev_535353.pdf(文件大小:266K) (原文件名:mcu-fpga.pdf)

出0入0汤圆

 楼主| 发表于 2010-2-26 07:56:44 | 显示全部楼层
回复【楼主位】liu_jing_yang
-----------------------------------------------------------------------

问题目前得到初步解决,程序见下面,目前来说这个程序下到板子上可以实现ARM与FPGA的读写操作,还需要进一步调试,有可能还会出现问题,程序如下,大家可以和第一帖的程序坐下对比:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity arm_fpga is
port(
mcudata : inout std_logic_vector(7 downto 0);--8位数据
mcuaddress : in std_logic_vector(9 downto 0);--10位地址
wr : in std_logic;--写信号
rd : in std_logic;
cs : in std_logic;
led : out std_logic_vector(7 downto 0));
end;

architecture  armfpga of arm_fpga is
constant addr_reg1 : std_logic_vector(9 downto 0) := "0000000000";
constant addr_reg2 : std_logic_vector(9 downto 0) := "0000000001";
constant addr_reg3 : std_logic_vector(9 downto 0) := "0000000010";
constant addr_reg4 : std_logic_vector(9 downto 0) := "0000000011";

signal  addresstemp : std_logic_vector(9 downto 0);--内部寄存器
signal  datatemp : std_logic_vector(31 downto 0);
--signal  wr_en,rd_en : std_logic;--读写使能

begin
addresstemp <= mcuaddress;

--ARM写数据到FPGA:
process(wr,cs)
begin

if( wr'event and wr = '0' )then
if( cs = '0') then
case addresstemp is
when addr_reg1 => datatemp(7 downto 0) <= mcudata;
when addr_reg2 => datatemp(15 downto 8) <= mcudata;
when addr_reg3 => datatemp(23 downto 16) <= mcudata;
when addr_reg4 => datatemp(31 downto 24) <= mcudata;
when others =>
datatemp<=(others=>'0');
end case;
else
datatemp<=(others=>'0');
end if;
end if;
end process;

--ARM从FPGA读取数据:
process(rd,cs)
begin

if (rd'event and rd = '0' ) then
if (cs = '0')then
case addresstemp is
when addr_reg1 => mcudata<=datatemp(7 downto 0);
when addr_reg2 => mcudata<=datatemp(15 downto 8);
when addr_reg3 => mcudata<=datatemp(23 downto 16);
when addr_reg4 => mcudata<=datatemp(31 downto 24);
when others=>mcudata<="ZZZZZZZZ";
end case;
else
mcudata<="ZZZZZZZZ";
end if;
end if;
end process;
led <= mcudata;
end;

出0入4汤圆

发表于 2010-2-26 09:11:38 | 显示全部楼层
我的语句是可以用的,rd,wr在when的条件语句中用到了,是简单的锁存器逻辑.
你用rd,wr的时钟逻辑也是可以的,不过在FPGA内部要占用GCLK资源, 而且rd,wr最好接在FPGA的全局时钟管脚上. 否则延时不可控.

出0入0汤圆

 楼主| 发表于 2010-2-27 08:06:27 | 显示全部楼层
回复【19楼】qinxg
我的语句是可以用的,rd,wr在when的条件语句中用到了,是简单的锁存器逻辑.
你用rd,wr的时钟逻辑也是可以的,不过在FPGA内部要占用GCLK资源, 而且rd,wr最好接在FPGA的全局时钟管脚上. 否则延时不可控.

-----------------------------------------------------------------------

恩,仔细看看,你的程序确实比较简洁,节省很多资源,目前的情况为编译可以通过,但仿真出现错误,我得再调调

出0入0汤圆

 楼主| 发表于 2010-4-9 08:33:12 | 显示全部楼层
回复【20楼】liu_jing_yang
-----------------------------------------------------------------------

顶起来

出0入0汤圆

发表于 2010-4-13 17:15:57 | 显示全部楼层
初步看了你的代码,你的MCUDATA是双向的,但是虽然你的数据是双向,但是在FPGA内部它是有分的,知道我的意思吗?不能那样赋值

出0入0汤圆

发表于 2010-9-8 09:21:03 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-8 09:28:16 | 显示全部楼层
搞定没有啊?

出0入0汤圆

发表于 2010-9-8 10:26:50 | 显示全部楼层
不要瞎搞,先去看看书吧

出0入0汤圆

发表于 2011-7-29 22:52:54 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-30 16:36:53 | 显示全部楼层
mark lz搞定没

出0入0汤圆

发表于 2011-8-1 13:55:28 | 显示全部楼层
Q俺:609702901

出0入0汤圆

发表于 2012-5-6 03:46:34 | 显示全部楼层
12楼有点小错误:漏了一个  '
--ARM从FPGA读取数据:
mcudata <= datatemp(7 downto 0) when( cs='0 and rd='0' and addresstemp = "00") else
                  datatemp(15 downto 8) when( cs='0 and rd='0' and addresstemp = "01") else
                  datatemp(23 downto 16) when( cs='0 and rd='0' and addresstemp = "10") else
                  datatemp(31 downto 24) when( cs='0 and rd='0' and addresstemp = "11") else
                  "ZZZZZZZZ";      -- "ZZ"不可少,否则总线被FPGA锁死.
加上:
--ARM从FPGA读取数据:
mcudata <= datatemp(7 downto 0) when( cs='0' and rd='0' and addresstemp = "00") else
                  datatemp(15 downto 8) when( cs='0' and rd='0' and addresstemp = "01") else
                  datatemp(23 downto 16) when( cs='0' and rd='0' and addresstemp = "10") else
                  datatemp(31 downto 24) when( cs='0' and rd='0' and addresstemp = "11") else
                  "ZZZZZZZZ";      -- "ZZ"不可少,否则总线被FPGA锁死.

出0入0汤圆

发表于 2015-10-26 22:15:39 | 显示全部楼层
mark{:smile:
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 23:22

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表