当前位置:   article > 正文

Zynq-linux PL与PS通过DMA数据交互_zynq使用dma实现ps与pl端的数据交互

zynq使用dma实现ps与pl端的数据交互

一、目标
在米尔科技的z-turn板上,采用AXI DMA 实现zynq的PS与PL数据交互。
二、分析
①PS数据传PL
驱动中的测试程序中给出一堆数据,通过DMA传输到AXI4-Stream Data FIFO ,PL端从DATA FIFO中把数据读出来。
②PL数据传PS
将PS传入PL的数据回传,在PS端显示出数据,最后将数据乘2再送入DMA。
③PL端代码思路
1)读数据
在加上DATA FIFO的情况下,PL从DATA FIFO中读取数据。将DATA -FIFO的M_AXIS端引出,得到下面的信号。

信号名称 作用 方向
m_axis_tvalid 主机向从机发数据的信号声明,置1表示主机有数据要发向从机。 输出
m_axis_tready 主机判断从机是否准备好接收数据,当为1时表示从机准备好接收数据。 输入
m_axis_tdata 主机将要发送的数据。 输出
m_axis_tkeep 主机发送数据时需拉高。 输出
m_axis_tlast 表示主机发送是否是最后一个数据,置1时表示主机正在发送最后一个数据。 输出

从上表可以看出,DATA FIFO接收完数据后,想要从FIFO中读取数据,靠的就是上面5根线,FIFO作主机,PL端作从机。所以FIFO会自动将m_axis_tvalid置1,表明可以从主机中读取数据。PL只需要给出回应m_axis_tready置1,便可以在时钟上升沿来临时读取数据。
同时,AXI-DMA将PS数据传输完成后有完成标志mm2s_introut置1。通过这个标准来确定是否从FIFO中读取数据。所以这个信号用于PL中断的触发信号。
2)写数据
将PL读取出来的数据进行乘2,再传入PS,PS再将数据打印出来。PL端接的是AXI-DMA的S_AXIS_S2MM端口。其信号如下:

信号名称 作用 方向
s_axis_s2mm_tdata 从机接收数据线 输入
s_axis_s2mm_tkeep 数据有效信号线 输入
s_axis_s2mm_tlast 是否最后一个数据 输入
s_axis_s2mm_tready 从机准备是否准备好接收数据 输出
s_axis_s2mm_tvalid 主机是否有数据发向从机 输入

从信号列表可以看出,此时DMA端口是作从机,PL端口作主机向DMA端口发送数据。PL端想发送数据,通过s_axis_s2mm_tvalid表明有数据发往从机。等待从机响应s_axis_s2mm_tready信号,响应过后便可以发送数据。发送数据时需要将s_axis_s2mm_tkeep拉高,同时当传到最后一个数据时,需要将s_axis_s2mm_tlast置1。
3)整体架构
在这里插入图片描述
局部放大图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
三、代码实现
①pl_read.v

module pl_read(
clk,
rst,

m_axis_tvalid,
m_axis_tdata,
m_axis_tkeep,
m_axis_tlast,
m_axis_tready,

m_ready,
m_data,
m_datavalid,
m_datalast
);
input clk;
input rst;

input m_axis_tvalid;
input [31:0]m_axis_tdata;
input [3:0]m_axis_tkeep;
input m_axis_tlast;
output m_axis_tready;

input m_ready;
output [31:0]m_data;
output m_datavalid;
output m_datalast;

reg m_axis_tready;
reg [31:0]m_data;
reg m_datavalid;
reg m_datalast; 
always@(posedge clk or negedge rst)
begin
    if(!rst)
    begin
        m_axis_tready <= 0;
        m_data <= 0;
        m_datavalid <= 0;
        m_datalast <= 0;
    end
    else
    begin
        if(m_ready==1)
        begin
            m_axis_tready <= 1;
            if(m_axis_tvalid==1&&m_axis_tkeep==4'b1111)
            begin
                m_data <= m_axis_tdata;
                m_datavalid <= 1;
                if(m_axis_tlast==1) m_datalast <= 1;
                else m_datalast <= 0;
            end
            else
            begin
                m_data <= m_data;
                m_datavalid <= 0;
                m_datalast <= 0;
            end
        end
        else
        begin
            m_axis_tready <= 0;
            m_data <= m_data;
            m_datavalid <= 0;
            m_datalast <= 0;
        end
    end
end

endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

②pl_write.v

module pl_write(
clk,
rst,

s_data,
s_datavalid,
s_datalast,
s_ready,

s_axis_tdata,
s_axis_tkeep,
s_axis_tlast,
s_axis_tready,
s_axis_tvalid
);
input clk;
input rst;

input[31:0] s_data;//data stream
input s_datalast;//data last flag
input s_datavalid;//input data valid flag
output s_ready;//数据可以写入标志

input s_axis_tready;
output[31:0] s_axis_tdata;
output[3:0]s_axis_tkeep;
output s_axis_tlast;
output s_axis_tvalid;

reg [31:0] s_axis_tdata;
reg [3:0]s_axis_tkeep;
reg s_axis_tlast;
reg s_axis_tvalid;
reg s_ready;

always@(posedge clk or negedge rst)
begin
    if(!rst)
    begin
        s_axis_tkeep <= 4'b0000;
        s_axis_tvalid <= 0;
        s_axis_tdata <= 0;
        s_axis_tlast<=0;
        s_ready <= 0;        
    end
    else
    begin
       if(s_axis_tready==1)
        begin
            if(s_datavalid==1)
            begin
                s_axis_tvalid <= 1;
                s_axis_tkeep <= 4'b1111;
                s_axis_tdata <= s_data;
                if(s_datalast)s_axis_tlast <= 1;
                else s_axis_tlast <= 0;
            end
            else 
            begin
                s_axis_tvalid <= 0;
                s_axis_tkeep <= 4'b0000;
                s_axis_tdata <= s_axis_tdata;
                s_axis_tlast<=0;
            end
            s_ready <= 1;
        end
        else 
        begin
            s_axis_tkeep <= 4'b0000;
            s_axis_tvalid <= 0;
            s_axis_tdata <= s_axis_tdata;
            s_axis_tlast<=0;
            s_ready <= 0;
        end
    end
end

endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78

③top.v

module top(
);
wire clk;
wire rst;

wire m_axis_tvalid;
wire [31:0]m_axis_tdata;
wire [3:0]m_axis_tkeep;
wire m_axis_tlast;
wire m_axis_tready;

wire m_ready;
wire [31:0]m_data;
wire m_datavalid;
wire m_datalast;

wire s_axis_tready;
wire[31:0] s_axis_tdata;
wire[3:0]s_axis_tkeep;
wire s_axis_tlast;
wire s_axis_tvalid;

pl_write u1(
.clk(clk),
.rst(rst),

.s_data(m_data),
.s_datalast(m_datalast),
.s_datavalid(m_datavalid),
.s_ready(m_ready),

.s_axis_tready(s_axis_tready),
.s_axis_tdata(s_axis_tdata),
.s_axis_tkeep(s_axis_tkeep),
.s_axis_tlast(s_axis_tlast),
.s_axis_tvalid(s_axis_tvalid)
);
pl_read u2(
.clk(clk),
.rst(rst),

.m_data(m_data),
.m_datalast(m_datalast),
.m_datavalid(m_datavalid),
.m_ready(m_ready),

.m_axis_tready(m_axis_tready),
.m_axis_tdata(m_axis_tdata),
.m_axis_tkeep(m_axis_tkeep),
.m_axis_tlast(m_axis_tlast),
.m_axis_tvalid(m_axis_tvalid)
);
system_wrapper u3(
.FCLK_CLK0(clk),
.peripheral_aresetn(rst),
.s_axis_aclk(clk),
.s_axis_aclk_1(clk),
.s_axis_aresetn(rst),
.s_axis_aresetn_1(rst),

.s_axis_tready(s_axis_tready),
.s_axis_tdata(s_axis_tdata),
.s_axis_tkeep(s_axis_tkeep),
.s_axis_tlast(s_axis_tlast),
.s_axis_tvalid(s_axis_tvalid),

.m_axis_tready(m_axis_tready),
.m_axis_tdata(m_axis_tdata),
.m_axis_tkeep(m_axis_tkeep),
.m_axis_tlast(m_axis_tlast),
.m_axis_tvalid(m_axis_tvalid)
);


endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75

④dma驱动代码

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <asm/io.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/miscdevice.h>
#include <linux/ioport.h>
#include <linux/of.h>
#include <linux/uaccess.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
#include <linux/irq.h>
#include <asm/uaccess.h>
#include <linux/dma-mapping.h>
/**
 *DMA驱动程序
 *
 *
 *
 *
 *
 *
 *`
 *
 * **/
//DMA 基地址
#define DMA_S2MM_ADDR		0X40400000
#define DMA_MM2S_ADDR       0X40410000

//DMA MM2S控制寄存器
volatile unsigned int  * mm2s_cr;
#define MM2S_DMACR		0X00000000

//DMA MM2S状态控制寄存器
volatile unsigned int * mm2s_sr;
#define MM2S_DMASR		0X00000004

//DMA MM2S源地址低32位
volatile
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/975829
推荐阅读
相关标签
  

闽ICP备14008679号