zoukankan      html  css  js  c++  java
  • 【iBoard 电子学堂教程】【STM32通过 FSMC 读写 FPGA示例】

    本文版权归 XiaomaGee所有,转载请注明出处。

    _____________________________________

    深入交流QQ群:

    A: 204255896500人超级群,满员) B: 165201798500人超级群,满员)
    C: 215053598
    200人高级群,满员) D: 215054675200人高级群)

    E: 215055211200人高级群) F: 78538605 500人高级群)

    G:158560047500人高级群,满员)

    YY 7182393

    YY频道80518139(不定期语音群课)

    论坛:http://www.heijin.org

    店铺:http://i-board.taobao.com

    博客:http://XiaomaGee.cnblogs.com

    提示:请关注论坛和博客,以便浏览本文档最新版本

    _____________________________________

    一、 ARM 程序介绍

    1. 写函数

    1 #define fpga_write(offset, data) *((volatile unsigned short int*)(CS0_BASE + (offset << 17))) = data

    其中:

    • offset为空间偏移量,范围为 0~7(8个空间);
    • data 为数据,16位整数,范围为 0~65535;
    • CS0_BASE 为ARM连接FPGA cs0的基地址,具体内容详见原理图。

    若向空间2写入1234,则调用方法为:

    1 fpga_write(2,1234);

    2. 读函数

    1 #define fpga_read(offset) *((volatile unsigned short int*)(CS0_BASE + (offset << 17)))

    其中:

    • offset 为空间偏移量,范围为0~7(共8个空间);
    • 范围值为16位证书,范围为0~65535;
    • CS0_BASE 为ARM连接FPGAcs0的基地址,具体内容详见原理图。

    若读取空间2的值,则调用方法为:

    1 unsigned short int read_data;
    2 
    3 read_data = fpga_read(2);

    二、 FPGA 程序介绍

    image

    图示为FSMC 代码生成的顶层模块连接示意图,其中:

    • DB[15..0] AB[18..16] WR RD CS0 连接到 ARM上;
    • LED_FPGA 使用outg[0] 控制其亮和灭(可以通过面板控制);
    • ina[15..0] ~ inh[15..0] 为读取数据输入,共包含8个空间,每个空间16位;
    • outa[15..0]~outh[15..0]为写入空间寄存器,共8个空间,每个空间16位;

    具体实现原理请参考 fsmc.v 程序。 

    //fsmc read / write ep4ce6 demo
    
    module fsmc(
        ab,   //address
        db,    //data
        wrn,    //wr
        rdn,    //rd
        resetn,    //resetn
        csn,    //cs
        ina,    //input data a
        inb,    //input data b
        inc,    //input data c
        ind,    //input data d
        ine,    //input data e
        inf,    //input data f
        ing,    //input data g
        inh,    //input data h
        outa,    //output data a
        outb,    //output data a
        outc,    //output data a
        outd,    //output data a
        oute,    //output data a
        outf,    //output data a
        outg,    //output data a
        outh    //output data a
        );
        
        input[2:0]    ab;
        inout[15:0] db;
        input wrn;
        input rdn;
        input resetn;
        input csn;
        input [15:0] ina;
        input [15:0] inb;
        input [15:0] inc;
        input [15:0] ind;
        input [15:0] ine;
        input [15:0] inf;
        input [15:0] ing;
        input [15:0] inh;
        
        output reg [15:0] outa;
        output reg [15:0] outb;
        output reg [15:0] outc;
        output reg [15:0] outd;
        output reg [15:0] oute;
        output reg [15:0] outf;
        output reg [15:0] outg;
        output reg [15:0] outh;
        
        wire rd;
        wire wr;
        
        reg [15:0] indata;
        
        assign rd = !(csn & rdn); //get rd pulse  ____|~~~~|______
        assign wr = !(csn & wrn); //get wr pulse  ____|~~~~|______
        
        assign db = rd ? indata:16'hzzzz;
        
        
        //write data, 根据地址线选择八个空间写入,每个空间16位
        always @(negedge wr or negedge resetn)
        begin
            if(!resetn)begin
                outa <= 16'h0000;
                outb <= 16'h0000;
                outc <= 16'h0000;
                outd <= 16'h0000;
                oute <= 16'h0000;
                outf <= 16'h0000;
                outg <= 16'h0000;
                outh <= 16'h0000;
            end    else  begin
            case (ab)            
                3'b000:outa <= db;
                3'b001:outb <= db;
                3'b010:outc <= db;
                3'b011:outd <= db;
                3'b100:oute <= db;
                3'b101:outf <= db;
                3'b110:outg <= db;
                3'b111:outh <= db;
                default:;
            endcase
            end
        end
        
                
        //read data 根据地址线选择8个空间读取,每个空间 16位
        always @(rd or !resetn)
        begin
            if(!resetn)indata <= 16'h0000;
            else  begin
            case (ab)
                3'b000:indata <= ina;
                3'b001:indata <= inb;
                3'b010:indata <= inc;
                3'b011:indata <= ind;
                3'b100:indata <= ine;
                3'b101:indata <= inf;
                3'b110:indata <= ing;
                3'b111:indata <= inh;
                default:;
            endcase
            end
        end
        
    endmodule
      

    三、 功能测试

    如上图所示,FPGA 内把outh[15..0] 输出的数据,取非后连接到 ina[15..0],ARM程序会写入空间7(也就是outh[15..0]),然后读取空间0(也就是ina[15..0]),然后做数据取非校验,判断成功与否。每轮测试 65536次,共进行300轮测试。核心代码如下:

    for (i = 0; i < 65536; i++) {
    
    fpga_write(7, i);
    
    dat = fpga_read(0);
    
    if ((dat + i) != 65535) {
    
    errors++;
    
    }else success++;
    
    }

    四、 软件界面

    界面包含四个按键,按下【开始测试】则进行读写测试,测试中,按下【停止测试】则停止测试,按下【发光管亮】则FPGA 控制的发光二极管亮,【发光管灭】则FPGA控制的发光二极管灭。

    image

    image

    image

      

    image

    软件包及 PDF 文档下载:

    https://files.cnblogs.com/xiaomagee/iboard_fsmc_pub.zip

  • 相关阅读:
    matlab--“下标索引必须为正整数类型或逻辑类型”
    将中缀表达式转化为后缀表达式
    MATLAB那些常见的命令
    关于实现线程同步的几种方式
    关于http协议
    小白学习之activiti工作流入门
    小白- jquery 学习笔记
    小白-Javascript学习笔记
    小白-css笔记
    小白- html笔记
  • 原文地址:https://www.cnblogs.com/xiaomagee/p/2808206.html
Copyright © 2011-2022 走看看