精华内容
下载资源
问答
  • 摘 要:为实现高速、大容量的数据存储,提出一种基于硬盘Ultra DMA传输模式的高性价比解决方案。详细介绍Nios嵌入式系统的整体构架和各个子模块的功能;提出一种在不改变传输频率条件下,通过使用寄存嚣组对不同时钟...
  • DDR3 数据传输 (三)

    2021-09-19 15:52:15
    本文将继续介绍DDR3数据传输过程的读写时序问题。 前情回顾: 1、DDR3 数据 传输 (一) 2、DDR3 数据 传输 (二) 一、地址 参考说明 【1】Zynq-7000 SoC and 7 Series FPGAs MIS v4.2 ...

    目录

    前言

    一、地址映射

     二、命令路径

     三、写路径

    四、读路径

    五、内存刷新

    六、ZQ校准

    参考说明




    前言

    前两篇文章主要介绍 MIS IP的配置(非AXI4)以及用户接口各信号的含义。本文将继续介绍DDR3数据传输过程的读写时序问题。

    前情回顾:

    1、DDR3 数据 传输 (一)

    2、DDR3 数据 传输 (二)

    建议PC端食用~



    一、地址映射

     

    地址空间有两种方式:

            1、Bank- Row-Column

            2、Row-Bank-Column

            方式的选择由字符参数:MEM_ADDR_ORDER控制,参数为 BANK_ROW_COLUMN 时,地址空间为方式1,参数为 ROW_BANK_COLUMN 时,地址空间为方式2。参数为 TG_TEST 时,地址映射仅用于测试目的。它使地址重新映射能够测试对DRAM不同部分的地址访问。它重新映射地址,重新映射在控制器的UI部分中完成。

    举例说明

            行地址位宽:15,列地址位宽:10,BANK位宽:3 地址映射方式为: ROW_BANK_COLUMN 

     

     二、命令路径

            当用户逻辑侧的  app_en 信号和 MIS IP核的UI块输出的 app_rdy 信号同时有效时,用户发出的命令(读或者写)被 IP核接收,并且写入 命令 FIFO中等待被执行。但如果  app_rdy 信号无效,那么用户发出的命令将不被IP 核接收。如下图所示,用户需要一直保持   app_en信号、地址信号、命令信号有效直到  app_rdy 信号有效,将命令以及地址接收。下图中,app_cmd信号、app_addr信号、app_en信号一直保持3个时钟周期同时有效,直到第三个时钟周期时,app_rdy信号输出有效才将命令信号、地址信号接收。

             非连续的写命令如下图所示,对应有三种不同情况:

    • 写的数据和与之对应的写命令同时有效;
    • 写的数据出现(有效)的时刻早于写命令一个时钟周期;
    • 写的数据出现(有效)的时刻晚于写命令,但是不能超过两个时钟周期;

     三、写路径

            当 app_wdf_wren 和 app_wdf_rdy 均有效时(握手),写入的数据将被寄存在写FIFO中。如果 app_wdf_rdy 信号输出无效(低电平),用户需要保持 app_wdf_wren 和 app_wdf_end 高电平 以及 数据 app_wdf_data 有效,直到 app_wdf_rdy 信号输出有效。

             上图中,内存的突发类型为 BL8(突发长度为8,即连续写入8个数据),2:1模式 和 4:1模式 指的是在配置MIS IP的GUI界面选择的DDR3时钟频率与FPGA内部逻辑时钟频率之间的比例。 app_wdf_end 信号必须在写突发模式结束时拉高。对于内存突发类型为 BL8,2:1 模式下,app_wdf_end 信号必须在第二个写数据字拉高(如图1-76)。

           ※ 以8位内存、突发类型为 BL8 ,4:1模式为例,如果应用接口处的64位数据是:0000_0806_0000_0805(16进制),那么在外部DRAM接口处的数据如下图所示。

             在不同时钟边沿的数据为:

             8位内存、突发类型为 BL8 ,2:1模式为例,应用数据位宽为32位,第一个周期发送的数据是:0000_0405(16进制),第二个周期发送的应用数据是:0000_080A(16进制)如下图所示,64位的用户数据必须用两个时钟周期发送。

             对应的外部DRAM接口的数据为:

     总结:

    1、突发类型与模式(2:1或4:1)之间没有任何关系,对于BL8(Burst Length eight),突发长度为8,仅仅表示一次性连续写入数据(app_wdf_data)的周期个数。

    2、假设 app_wdf_data 位宽为 WIDTH_DATA;选择的模式为 MODE (MODE=2或4);DDR3的存储单元位宽 WIDTH_DDR3 (一般来说等于8或16),在DDR3存储单元位宽等于GUI界面(Controller Options 页面)设置的数据位宽(Data Width)的前提下,位宽则有如下关系成立: 

    WIDTH_DATA = MODE * WIDTH_DDR3 * 2

    再假设 Controller Options 页面设置的数据位宽为:WIDTH_USER,则通用的表达式为:

    WIDTH_DATA = MODE * WIDTH_USER * 2

    3、详细解释一下  app_wdf_end 信号拉高的条件,该信号表面含义指的是在最后一个周期数据(app_wdf_data)传输时,拉高。那么何为最后一次?如何把握?

            技术文档原话:The app_wdf_end signal must be used to indicate the end of a memory write burst.

            意思是,在一次内存突发写的末尾将该信号,拉高,那么何时是一次突发写结束?对于存储单元位宽为8位的DDR3来说,BL8的突发模式下,一共需要写入8*8=64位,对于app_wdf_data为64位的情况,写的第一次即是最后一次,对于app_wdf_data 为32位的情况,写的第二次即使最后一次。(认真对比图1-76 和1-77的相关信号 特别是  app_wdf_end 信号)

    四、读路径

            IP 的UI块 会把用户侧请求的读数据按照请求的顺序进行数据输出。当 app_rd_data_valid 拉高时,UI输出的数据为有效数据。如下图所示:

             app_rd_data_end 信号在一次 突发读 操作结束时拉高。但是对于 用户侧的逻辑不是那么必要。

            读取的数据会按照 请求的地址顺序进行输出。如下图所示:

    五、内存刷新

            用户逻辑需要通过将 app_ref_req 信号拉高一个时钟周期,来发起一次内存刷新请求。IP 核中 内存控制器模块(Memory Controller)向物理层(PHY)发送刷新指令后,物理层会将 app_ref_ack 拉高一个时钟周期来响应刷新请求。 在 app_ref_ack 信号应答之后,才可以发送第二次刷新请求。时序逻辑如下图:

    六、ZQ校准

            用户逻辑需要通过将 app_zq_req 信号拉高一个时钟周期,来发起一次内存ZQ校准请求。IP 核中 内存控制器模块(Memory Controller)向物理层(PHY)发送ZQ校准指令后,物理层会将 app_zq_ack 拉高一个时钟周期来响应ZQ校准请求。 在 app_zq_ack 信号应答之后,才可以发送第二次ZQ校准请求。时序逻辑如下图:

     

     

    参考说明

    【1】Zynq-7000 SoC and 7 Series FPGAs MIS v4.2

    【2】图取自官方文档 ☝ 

    展开全文
  • DDR3联合HDMI进行图片数据传输 项目概况 DDR3 IP核调用及介绍 DDR3 IP核的调取 IP核引脚以及功能说明 DDR3内部模块 仲裁模块 读写模块 仿真测试 DDR3外部模块 外部读写模块 内外联合测试仿真 HDMI模块 ...

    DDR3联合HDMI进行图片数据的传输

     

    • 项目概况
    • DDR3 IP核调用及介绍
    1. DDR3 IP核的调取
    2. IP核引脚以及功能说明
    • DDR3内部模块
    1. 仲裁模块
    2. 读写模块
    3. 仿真测试
    • DDR3外部模块
    1. 外部读写模块
    2. 内外联合测试仿真
    • HDMI模块
    1. encode模块
    2. par2ser模块
    3. HDMI仿真测试
    • DDR3联合HDMI

    项目概述

    本次项目是为了实现DDR3联合HDMI,进行一幅1024*768图片的显示,在PC机上利用串口讲图片的数据发送给DDR3并存入到DDR3中,然后由HDMI将数据取出来,显示到显示器上。

    项目框图如下:

          

    本次项目的主要目的是通过DDR3和HDMI这种联合的方式,掌握DDR3的存取原理和HDMI的显示原理,自己搭建起DD3的控制器,将DDR3灵活的运用起来,同时编写HDMI_trans模块去发送我们想要显示的图像数据,以达到通用的效果。

    实验环境为Vivado 16.4,Win10,64位,采用开发板为XC7A35T-2FGG484。

    DDR3 IP核调取及介绍

    一.DDR3 IP核的调取:

    1.调取方法

     A7的DDR3调用方法和Spartan6一样,通过GUI界面调取IP的方法来调用DDR3

           下面为DDR3 IP核调用事项(放大后看清):

                  在IP界面中选择7系列的MIG:

    选择你的IP名字:

    这一页改动很多,而且很重要,在这里有较为详细的解释:

    DDR3数据的位宽是16位,并且是双沿数据,因为在用户端是只能上沿发送数据,所以用户端的数据位宽就为:16*2*4==128位的,这个的*4就是4:1造成的。

    关于参考时钟:理论上应该给一个稳定200M的时钟,用来恢复主时钟的时钟质量,

           下面的一个页面全部选默认,到了绑定管教的界面直接绑定管脚就好了

    接下来一点默认到生成IP核,之后会在你的工程中生成这样的文件夹:

    在调取完成DDR3的IP核之后,就可以启动仿真来测试一下:

    2.IP核的例化

     首先建立一个顶层文件,将DDR3的IP核例化进来:

    在这个界面可以找到DDR3 IP核的例化模板,将IP核例化进去,然后需要将连接DDR3的绑定管脚的部分引到外面去,而那些中间用户变量需要模块中声明(ddr3开头为引脚,app的则为用户变量):

    3.IP核的仿真

     将ip核例化好之后,在tb里面将顶层文件例化一下,声明各种中间变量,同时,还需要加一个DDR3的模型到tb中来充当DDR3。模型的位置如下:

    启动仿真打开ModelSim之后,选择添加ddr3_ctrl模块,运行一段时间,如果init_calib_complete拉高,则表示DDR3初始化成功,调取DDR3 IP核可以进行更进一步的操作。

    二 . 功能及引脚介绍

    1. DDR3时序介绍:

           如果想要完全的用起来DDR3的IP核,需要知道它内部的运作原理和时序。通过查阅相应的DataSheet可知:A7的DDR3突发长度是固定为8的,也就是一次突写写8次单位地址的长度,如果DDR3的数据线为8位,突写一次就需要些8*8=64bit,而16位的话则需要16*8=128bit。

    1. DDR3的两种模式:

           DDR3有4:1和2::1两种模式,,这个4:1 和 2:1 是我们在调取IP的时候可以选择的,这里的 4:和2指的是DDR3与DDR3的IP核完成一次突发所需要的时钟周期的长度,而1指的是用户端向DDR3的IP核发送数据所需要的时钟周期数,不同的模式,有不同时序。 以数据线为8为例来说:

            如果选择2:1的模式,用户需要用两个时钟周期发送一次突写的数据,8*8=64,一个时钟周期也就是32位,而DDR3与IP核交互数据时,需要64/2(双沿)/8(单位数据位宽)=4; DDR3与IP核交互完成一次突发所需要的时钟周期,和用户和IP核完成一次突发所需要的时钟周期之比,就为DDR3的这两种模式。

           同样的4:1也是如此,只不过在用户端与IP核交互时,一次突写只需要一个时钟周期。而DDR3与IP核交互数据不变。

    1. DDR3的时钟方面:

     DDR3有许多的时钟,不管是什么时钟,我们都需要弄清楚,从最开始调用IP核说明: 这个Clock Peried就是DDR3的时钟,为400M,和芯片的种类和速度等级有关。而下         面的4:1就是上面所说到的DDR3的两种模式,也就是用户时钟和DDR3时钟的关系。

    Input Clock Period :这个时钟是输入给DDR3 IP核的时钟,IP核中自带了一个PLL,它会将输入的时钟分倍频到DDR3所需要的时钟。如果输入到 IP 核的时钟是外部晶振生成的切单端,那就选择Singel_Ended ,如果是差分的,就选择Differential,但是现在我们决定用外部PLL产生一个200M的时钟,来给IP核,而PLL自带BUFFG,所以选择 No Buffer。

    Reference Clock :参考时钟,利用这个参考时钟,来生成用户的100M时钟(ui_clk),它的精度要求范围为199M-201M,如果上面选择输入时钟为200M,则这个可以用输入的系统时钟来代替,如果不是则需要另外开一个接口输入进来200M的时钟。

    1. IP核的读写时序:
    1. 写时序:

     IP核往DDR3里面写入数据时,需要向AXI总线那样,给出一定的握手信号才能完成。

    由上图可知:在采用4:1的模式下,数据(app_wdf_data[127:0])和写使能(app_wdf_wren)和数据突写结束信号(app_wdf_end)同时出现,标志着此时数据有效,但只有当准备信号(app_wdf_rdy)信号有效时,才标志着数据被暂时的缓存到了IP核中,只有当给出了写的命令,和地址,而且app_en 和 app_rdy同时拉高,表示命令(3’b000)和地址被接受,就会将缓存在IP核中的数据,真正的写入到了DDR3中。写的命令和地址,可以提前与数据,也可以同时或者落后,但是数据落后的时间不应超过两个时钟周期。

    为了确保能正确的将数据送入到DDR3中,我们只选择一种模式,而且是和Spartan一样的先给出数据,再给出命令。

    1. 读时序:

    在 4:1的模式下,首先给出读的命令(3‘b001)和地址,当app_en和app_rdy信号同时有效时,表示命令和地址被接受,在接下来的一段时间内,IP核会将所读地址的数据读出来并且伴随着一个有效的同步信号(app_rd_data_valid)。

    1. 读写时序总结:无论是读还是写,都会是分为两个部分,命令端和数据端。

    对于写来说,先给出数据端(app_wdf_data[127:0], app_wdf_end, app_wdf_wren, app_wdf_rdy),等数据端被IP核接受了之后,发送命令端的信号(app_cmd,app_addr,app_en,app_rdy),将数据写入到DDR3中,只有这几个信号之间相互配合,才能将数据写入到DDR3中,完成一次数据写的突发。

    对于读来说,是先给出命令端信号(app_cmd, app_addr, app_en, app_rdy),当IP核接受到这些命令之后,就会将数据端的信号送出来(app_rd_data[127:0], app_rd_data_valid)。从而完成一次数据读的突发。

    1. IP核引脚及功能说明:

    IP的引脚共分为两个部分,一个是和DDR3直接交互的引脚部分,另一个则是和用户端交互的。

                 

    下面是对引脚的说明:

     

    Name

    输入输出

    备注

    ddr3_dq[15:0]

    inout

    DDR3的数据位宽,传输数据的单位以它位基础,如果来8位,则是以字节为单位,而16位则是以Word为单位

    ddr3_dqs_n[1:0]

    inout

    数据选通。读时是输出,边缘与读出的数据对齐。写时是输入,中心与写数据对齐。

    ddr3_dqs_p[1:0]

    inout

     

    ddr3_addr[13:0]

    output

    和SDRAM一样采取行列复用的原则 2^3*2^14*2^10=2^27=128M

    ddr3_ba[2:0]

    output

    BANK地址

    ddr3_ras_n

    output

    行地址选通,低有效

    ddr3_cas_n

    output

    列地址选通,低有效

    ddr3_we_n

    output

    写使能,低有效

    ddr3_reset_n

    output

    DDR3的复位,低有效

    ddr3_ck_p

    output

    DDR3系统时钟,由200M倍频而来,差分对

    ddr3_ck_n

    output

     

    ddr3_cke

    output

    时钟使能,高有效

    ddr3_cs_n

    output

    片选,低有效

    ddr3_dm[1:0]

    output

    Data mask DDR3输入数据的掩码

    ddr3_odt

    output

    片上终端使能

    app_addr[27:0]

    input

    用户地址,

    app_cmd[2:0]

    input

    用户命令,3‘b000(写),3’b001(读)

    app_en

    input

    命令使能信号,拉高表示命令被使能

    app_wdf_data[127:0]

    input

    写数据,表示需要往DDR3里写的数据

    app_wdf_end

    input

    一次突发的结束

    app_wdf_mask[15:0]

    input

    数据掩码。一位掩码可以掩掉8bit数据,掩码位宽等于数据位宽/8

    app_wdf_wren

    input

    数据写使能

    app_rd_data[127:0]

    output

    读数据,DDR3中读取出来的数据

    app_rd_data_valid

    output

    读数据的同步信号

    app_rdy

    output

    IP核命令准备信号,拉高表示此时IP核能接受命令

    app_wdf_rdy

    output

    IP核写命令信号,拉高表示此时IP核能接受数据

    ui_clk

    input

    用户时钟,用参考时钟分频而来

    ui_clk_sync_rst

    input

    用户时钟复位

    init_calib_complete

    output

    DDR3初始化完成信号,一切对DDR3的操作应该在初始化完成之后。

     IP核与DDR3交互的接口,不需要我们去关心,Xilinx已经帮我们做好了。对于DDR3,都是基于用户接口来操作的,所以需要将app接口的各种信号相互配合,灵活的运用起来,已达到我们想要的目的。

    DDR3内部模块

    在A7这块芯片中,DDR3 IP核的用户接口和AXI总线有类似的地方,并没有像Spartan6那样方便,DDR3需要同时和不同的模块进行交互时在,这样的接口就显得有些不足,并没有通用性,为了以后方便使用A7的DDR3,可以在Spartan6的基础上,将A7的DDR3接口和用户交互功能做到和Spartan一样,即保证了通用性,还具有一定的统一性。

    下图为Spartan 6 中的DDR控制器:

    我们可以仿照Spartan6 作一个同样的:

    我们可以将红色的线条内的逻辑,和Spartan6 一样具有相同的功能,用户只需要将命令和数据存储到命令FIFO和数据FIFO中,仲裁状态就会判断是否去执行读和写,从而启动WR_CTRL 和RD_CTRL,利用WR_CTRL 和RD_CTRL去和A7_DDR3的IP和交互,完成数据的收发

    一.仲裁状态:

           仲裁模块是用户端和读写端的桥梁,同时也是控制器,当读或者写的命令FIFO中不为空,表示用户端发出读写的请求,则启动仲裁模块,下图为仲裁模块的时序图:

           uploading.4e448015.gif正在上传…重新上传取消

    当命令fifo不就为空时,状态机就会从仲裁状态跳转到相应的读写状态,同时产生一个内部读写模块的启动信号,这个启动信号又去读取命令fifo中数据传到相应的读写模块中,当完成一次自定义的突发时,读写模块回传一个结束标志,状态机又跳转到仲裁状态,等待下一次命令的到来。

           接口定义解释:

    Name

    输入输出

    备注

    ui_clk

    Input

    IP核中由参考时钟分屏出来的100M用户时钟

    calib_done

    Input

    IP核初始化完成信号,一切对IP核的操作需要在它拉高之后

    pi_wr_start

    Input

    写命令FIFO的空信号取反,不空则表示有命令输入进来需要进行相对应的状态的跳转

    pi_rd_start

    Input

    读命令FIFO的空信号取反,不空则表示有命令输入进来需要进行相对应的状态的跳转

    wr_end

    Input

    写模块结束一次自定义突发长度时信号

    rd_end

    Input

    读模块结束一次自定义突发长度时信号

    po_wr_start

    Output

    写模块开始一次自定义突发长度时信号

    po_rd_start

    Output

    写模块开始一次自定义突发长度时信号

    二.内部读写模块:

           1.写模块

           对于写的操作,仲裁模块给出一个写的启动信号,然后模块开始工作,需要给出写的数据(app_wdf_data[127:0]),和写使能(app_wdf_wren),当IP核准备好接收这些数据时,就会把写准备拉高(app_wdf_rdy),那么数据就会被存入到IP核中,等到命令使能(app_en)和命令准备(app_rdy)同时拉高时,就会将数据写入到给出的地址当中。完成一次突发写的操作。用于DDR3的数据线为16位,一次固定突发为8,那么采用4:1的模式,用户数据位宽位128位,即一个用户时钟,就可以完成一次DDR3的突发,所以我们可以自定义IP核完成突发的个数。

           下图为内部写的时序图:

    当收到wr_start_flag时,启动并完成bl=64的一次写。由于两个rdy信号不受我们控制,所以需要计数器去控制命令端和数据端的个数。当写使能和些准备同时为高,当前数据被写入,还需要data_req信号输出到外部去请求数据。命令端和数据端的使能信号和准备信号同时拉高了突写次数时,就完成了一次突发,可以将使能信号拉低,同时计数器归零,以备下一次突发。关于app_en的启动,可以检测app_wdf_wren的上升沿来判断。

           接口定义解释:

    Name

    输入输出

    备注

    ui_clk

    input

     IP核中由参考时钟分屏出来的100M用户时钟

    calib_done

    input

     IP核初始化完成信号,一切对IP核的操作需要在它拉高之后

    po_wr_flag

    input

    模块工作信号,相对于命令fifo的读使能晚一拍

    data_req

     

    数据请求

    wr_end

     

    IP核突写一次用户自定义长度的结束信号

    app_wdf_rdy

    input

    IP核写准备信号,拉高表示能结束数据写入

    app_rdy

    input

    IP核命令准备信号,拉高表示能接受命令写入

    wr_data[127:0]

    input

    外模块传进来需要向IP核写入的数据

    wr_cmd_addr[27:0]

    input

    外模块传进来需要给IP核的写入地址

    wr_cmd_instr[5:0]

    input

    外模块传进来需要给IP核的一次用户自定义的突写长度

    wr_cmd[2:0]

    input

    外模块传进来需要向IP核写入的命令

    wr_data_mask[15:0]

    input

    外模块传进来数据掩码,某一位为高则表示相应的字节数据被掩掉

    app_wdf_wren

    output

    IP核数据写使能

    app_wdf_end

    output

    IP核突写的结束信号

    app_en

    output

    命令使能信号

    app_addr[27:0]

    output

    用户地址

    app_cmd[2:0]

    output

    用户命令

    app_wdf_data[127:0]

    output

    用户写数据

    app_wdf_mask[15;0]

    output

    用户数据掩码

    2.读模块:

           当仲裁模块传过来读的启动信号,RD_CTRL就会启动,读取一次用户自定义的突发长度的数据。 时序图如下:

    uploading.4e448015.gif正在上传…重新上传取消

    启动信号拉高后,app_en和app_rdy这两个命令端的必须同时拉高用户自定义突发长度个时钟周期,同时给出读命令和地址,然后延迟几个时钟周期,就会产生app_rd_data[127:0]和app_rd_data_valid信号。当app_rd_data_valid为高,表示读数据有效,而且当app_rd_data_valid拉高了用户自定义突发长度时,表示一次用户自定的突写结束,此时传出一个rd_end信号,告诉仲裁模块退出读状态 

          

    3.内部连线:

           当内部模块完成之后,由于各个模块相互约束,交错连接,连线成了设计的一个难点,需要十分的认真仔细,注意位宽,给各个信号取不易混淆的变量名,一步一步,从顶端输入输出,一步一步连接下去。在顶端先加入Spartan一样的接口:

    接下来就需要例化四个fifo,分别是命令的读和写的fifo,数据的读和写的fifo,命令fifo深度为16,位宽位({p2_cmd_instr[2:0],p2_cmd_bl[6:0],p2_cmd_byte_addr[27:0]})}因为对其去求量不大,可以采用分布式ram以减少逻辑资源的浪费。数据fifo可以用深度为64,位宽位144(p2_wr_mask[15:0],p2_wr_data[127:0]),读数据fifo中掩码的部分可以不用,用0代替。

     

       接下来就内部读和写模块,仲裁模块之间的相互接连,仲裁模块的启动信号是命令fifo的空信号,不空则跳转到相应的状态,同时读出命令fifo的数据给相对的读模块或者写模块,并且启动该模块,当完成时,传回一个结束信号,标志着此次突发完成,仲裁模块有重新判断命令FIFO的空信号,这样就使得各个模块循环起来。

    连线完成之后,DDR3_CTRL模块就基本上和Spartan6的IP核一致了,具有通用性核统一性。

    三.模块功能仿真,新建一个顶层,将DDR3_CTRL模块例化进去,通过控制P2 和 p3口,来达到写入数据,并且能读出来的效果。

           创建一个data_gen模块用于产生测试数据和读写信号,先将0-3f 64个数据写入到DDR3_ctrl模块的写数据fifo中,然后在给一个写的命令,仲裁模块会判断是否写,并且启动内部的写模块,从而将存储在DDR3_ctrl的写数据FIFO中的数据写入到DDR3中,然后在data_gen模块中在产生一个读的命令,仲裁模块就会启动内部的读模块,从而将数据从DDR3中读取出来存到读数据的FIFO中。一次的读和写给出相同的地址和突发长度,就会将刚刚写入的数据读出来,以达到完成ddr3_ctrl模块测试的效果。

     

     

           由上图所示,写入 0-3f数据后,又读出来0-3f,同时伴随着app_rd_data_valid同步有效信号,证明模块测试正确,达到了我们想要的目的。   

     

     

     

     

     

     

    DDR3 外部模块

    一.外部读写模块测试。

           外部的读写模块不同于内部,是直接与用户交互的模块,所以分别取名user_wr_ctrl和user_rd_ctrl 以区分内部和外部读写模块。在外部模块中,通过控制DDR3_CTLR的用户接口,达到和DDR3读写交互的效果,可以适当添加一下全局的参数来增加其通用性。

    1. 写模块:

     无论外部的数据是连续的还是间断的写入,都应该能将数据完整的写入到DDR3中,

    所以在本模块中,应该起到一个适配的作用,将传过来的数据,在位宽和数量上进行一定的处理,假设数据是由串口过来的八bit数据图像数据,由于DDR3_ctrl的数据位宽位为28位,所以传给DDR3_ctr一次需要16次串口发过来的数据拼接在一起发送。本模块采用尝试采用全局参数的方法,不仅可以支持串口的8位数据拼接,也可以支持其他不同位宽的数据拼接。时序图如下:

            将传送过来的数据没拼接成128位时,就启动一次写使能,然后将128位数据写入到IP核中,等到突发的次数够了,启动一次写的命令,将IP核的数据,写入到DDR3中。

    全局参数相关变量: 需要拼接的数据位宽,突写长度,读写基地址

    利用二进制一位代表一个位宽的特点,采用下图函数计算参数的位宽:

    Name

    输入输出

    备注

    sys_clk

    Input

    系统时钟

    sys_rst_n

    Input

    系统复位

    in_data[8:0]

    input

    输入数据

    in_flag

    input

    输入数据的同步信号

    p2_wr_data[127:0]

    output

    拼接起来的数据

    p2_wr_en

    output

    传给DDR3_ctrl模块的写使能

    p2_cmd_en

    output

    传给DDR3_ctrl模块的命令使能

    p2_wr_addr

    output

    传给DDR3_ctrl模块的地址

    p2_cmd_instr

    output

    传给DDR3_ctrl模块的命令

    p2_cmd_bl

    output

    传给DDR3_ctrl模块的突写长度

     

    1. 读模块:

      由于本次实验需要和HDMI联合进行图片的显示,由于两者的时钟不同,系统时钟为125M,而VGA的时钟为65M,所以需要在读模块中读取DDR3的数据,然后存储到一个用户fifo中,当HDMI场同步到来之后紧接着的第一个de有效信号表示显示的第一行,如果此时fifo的数据大于门限值,则可以将数据读出显示到HDMI上,而当fifo的数据小于一定的门限值时(可以是一行像素点的数据),读模块有继续向DDR3中读取数据,以此往复。形成循环。

            时序图如下:

    当fifo中的数据小于门限值时,需要向DDR3中读取数据填充fifo:先给一个读的命令(伴随着地址,命令,地址,完成之后地址加一,为下一次做准备),然后当DDR3_CTRL中读数据fifo存储到够一次突写的长度时,拉高读使能,将数据读出来并且存储到fifo中,当HDMI需要数据时(图像的第一行),打开读使能,并且正确的将128位数据合理的分拆成24位一组的RGB数据。这样的话,就完成了DDR3方面的工作。

           模块引脚说明:

    Name

    输入输出

    备注

    sys_clk

    input

    系统时钟

    sys_rst_n

    input

    系统复位

    vclk

    input

    VGA时钟,fifo的读时钟

    fifo_rd_en

    input

    Fifo的读使能,由HDMI模块给出

    v_sync

    input

    场同步信号,用于同步图片

    pixel_rgb[23:0

    output

    像素点的RGB值,由fifo中读出

    p3_cmd_full

    input

    读端口的命令fifo慢信号,不能再满的时候给出信号

    p3_rd_count

    input

    读端口数据fifo存储的数量

    p3_rd_data[127:0]

    input

    DDR3中存储的RGB值,由

    p3_cmd_instr[2:0]

    output

    传给DDR3_ctrl模块的命令

    p3_cmd_bl[6:0]

    output

    传给DDR3_ctrl模块的突发长度

    p3_cmd_en

    output

    传给DDR3_ctrl模块的命令使能

    p3_rd_en      

    output

    传给DDR3_ctrl模块的读使能

    p3_cmd_addr[27:0]

    output

    传给DDR3_ctrl模块的读地址

    拆分时序图如下:

    当fifo中有一定数量的值时,且场同步到了,此时拉高pixel_oe信号,作为数据和图像的同步信号,由于进来的数据为128位,而rgb的值为24位,不是整数倍的关系,股可以将128的数据每三个拼接在一起(128*3/24=16),先将384的shift_data填充满,当vga需要数据时,就将shift_data的低24位送出,然后右移24位,等全部移出后(rgb_cnt==15),在取出384位继续填充shift_data,以此往复,这样就循环起来了。

    二.内外联合测试仿真,

       当完成了内部和外部的读写,就可以用仿真来测试自己的逻辑是否正确,测试模块有多种写法,就写一个最简单的吧,在DD3R复位后,首先在测试模块data_gen中,连续给出8位的数据和同步信号,知道满足一次突写的长度,也就是64*128=8192,而8192/8=1024,0也就是连续需要1024个8位的数据和同步信号,给到外部的user_wr_ctrl之后,而user_wr_ctrl将数据写入到DDR3_Ctrl中的写数据fifo,之后等存储的数据达到了突写的长度,就给出一次命令,就fifo的中的数据存入到DDR3中,之后拉高一次p3口的写使能,测试数据是否会存储到外部user_rd_ctrl中的fifo。由于还没有加上HDMI模块,所以不好断定读模块是否正常,所以可以将先测试写模块。

    Data_gen模块波形图:

    User_wr_ctrl模块波形图

       insder_wr_ctrl模块波形图:

     

    由上波形图可以得出,数据在     User_wr_ctrl处拼接,然后送往内部写数据fifo,存到一定数据量时,就将数据存储到ddr3中,之后完成传出一个wr_end命令,标志这一次突发的写结束,初步达到了预期的效果,如果需要测试读模块是否正确的话,可以等加上HDMI模块之后,联合HDMI模块一起测试。这样的话,DDR3从调用到正常的使用自如,到这步算是初步完成了。

    HDMI模块

    一.HDMI介绍:

               HDMI的全称是“High Definition Multimedia Interface” 高清多媒体接口,是2002年,来自电子行业的七家公司,日立,松下,飞利浦,Silicon Image,索尼,汤姆逊,东芝共同组建了HDMI高清多媒体接口组织HDMI,开始制定一种符合高清时代标准的全新数字化视频、音频接口技术,经过半年多的时间准备工作,HDMI founders在2002年12月9日正式发布了HDMI1.0版标准,标志着HDMI正式进入历史舞台。

           DHMI传输原理如下:

         传输的方式是在VGA的基础上演变而来的,将VGA的时序,转化为4路TMDS通道(R,G,B,clk),HDMI使用最小跳变差分信号(TMDS)技术,差分信号上拉电压为+3.3v,端口阻抗为20欧姆,单端信号为400-600mV,标称为500mV,差分信号的逻辑摆幅在800-1200Mv之间,实际差分电压可以再150-1200Mv之间变化,而且偏置电压是由Sink端提供的。

      HDMI相对VGA具有以下优点:

    1. 更好的抗干扰性能,且兼容性更好
    2. 支持24bit色深处理,且支持音频,
    3. 一根线缆实现数字音频,视频信号的同步传输,有效降低成本和繁杂程度。
    4. 支持热插拔技术。

     

    想要利用HDMI进行图像的显示,需要将VGA的时序转化我HDMI的时序,需要经过如下图所示的几个步骤:

          

    1.8b/10b编码

           进行8b/10b编码是为了防止在发送数据的过程中连续出现多个0或者是1,这样的话在这段时间内,数据线的电流可视为直流电压,而直流电流会影响数据的传输,8B10B编码转换的作用就是让DC平衡,使得电路中0和1出现的次数向接近,以达到DC平衡的作用。

    在Xilinx的官网上,可以找到8b/10b转换的V文件和相关文档。将其下载下来可以直接使用,我们只需要将其例化进来,然后就能直接使用,就8bit的R,G,B数据转换为10bit的数据。

    encode模块接口说明:

    Name

    输入输出

    备注

    clkin

    Input

    pixel clock input 数据同步时钟

    rstin

    Input

    async. reset input (active high) 异步,高有效

    din[7:0]

    Input

    8bit数据输入

    c0

    Input

    Contrl Port 0,控制端口,数据为B时连接VGA的行同步信号

    c1

    Input

    Contrl Port 0,控制端口,数据为B时连接VGA的场同步信号

    de

    Input

    数据有效信号

    dout[9:0]

    output

    输出的10bit数据

    2.par2ser并转串模块:

           HDMI_trans模块中数据的发送是四路单bit串行数据发送,而VGA的数据是是由24bit R,G,B 8bit一组的并行数据,所以在数据发送的过程总需要并行数据转换为串行的数据, 在Vivado中,Xilinx为我们提供OSERDES的原语,作用是将并行数据串行化输出,

     

    对于原语更多的介绍,必须要查找相关的Datasheet手册才能准确的了解清楚。在Xilinx官方的7_Series FPGAs SelectIO Resources中,给出来OSERDES的具体介绍:

    7系列的OSERDES具有支持多种模式和不同速率的并行转串行化输出的原语,同时支持三态门数据和双沿数据的转换,具有普遍性和统一性。在上一个模块这种,R,G,B的8bit数据已经变为10bit的具有DC平衡的数据,在本模块模块中需要使用到OSERDES的扩展模式(支持10bit数据输入),采用双沿模式输出串行数据,假设R,G,B的时钟为65M,如果采用单沿模式输出串行数据,则需要650M的同步时钟,而使用双沿模式,则只需要325M的时钟即可,减少了对时钟的要求,利于我们更好的做进一步的设计。

    OSERDES原语参数说明:

     

    由于数据为10bit,则需要使用OSERDES的扩展模式,需要将两个OSERDES级联在一起:

      

     

     

    扩展模式的OSERDES,具有主机和从机,需要将主机的SHIFTIN1和2分别与从机SHIFTOUT1和2相连,数据的低8bit由主机进入,高两位由从机进入,串行数据的输出从主机的OQ口输出。在OSERDES中,数据的传送如下所示:

    输入的并行数据由低到高依次从OQ端输出,如果时串行数据进入到ISERDES,则串行数据先进来的进入到高位。

    OSERDES 参数说明:

    Name

    可选项

    说明

    DATA_RATE_OQ

    DDR, SDR

    输出串行数据的模式

    DATA_RATE_TQ

    DDR, BUF, SDR

    三态数据输出模式

    DATA_WIDTH

    2-8,10,14

    并行数据的位宽

    INIT_OQ

    1'b0,1'b1

    初始化是OQ的值

    INIT_TQ

    1'b0,1'b1

    初始化是OQ的值

    SERDES_MODE

    MASTER, SLAVE

    选择这个OSERDES是主机还是从机

    SRVAL_OQ

    1'b0,1'b1

    复位时第一个寄存器的值

    SRVAL_TQ

    1'b0,1'b1

    传输三态数据时复位时第一个寄存器的值

    TBYTE_CTL

    FALSE, TRUE

    Only for use via the MIG tool. Set to FALSE

    TBYTE_SRC

    FALSE, TRUE

    Only for use via the MIG tool. Set to FALSE

    TRISTATE_WIDTH

    1,4

    三态数据的位宽

    OSERDES 接口说明:

    Name

    输入输出

    说明

    OFB

    output

    用于联合ISERDES所用

    OQ

    output

    串行化数据的输出

    SHIFTOUT1

    output

    用于扩展模式,从机输出连接主机

    SHIFTOUT2

    output

    用于扩展模式,从机输出连接主机

    TBYTEOUT

    output

    Byte group tristate

    TFB

    output

    3-state control

    TQ

    output

    3-state control

    CLK

    Input

    High speed clock 高速时钟,串行化数据的同步时钟

    CLKDIV

    Input

    Divided clock 分频时钟,

    D1 – D8

    Input

    并行数据的输入

    OCE

    Input

    Output data clock enable,输出数据时钟使能

    RST

    Input

    Reset,高有效

    SHIFTIN1

    Input

    用于扩展模式,主机接收从机输入

    SHIFTIN2

    Input

    用于扩展模式,主机接收从机输入

    T1-T4

    Input

    三态数据

    TBYTEIN

    Input

    Byte group tristate

    TCE

    Input

    3-state clock enable

    因为HDMI是四路通道,还需要一路像素时钟来同步R,G,B的数据,为了让时钟尽可能的和串行数据同步化,所以可以让10‘b111110000也经过OSERDES来产生一路随路时钟同步数据,

       在最后,由于HDMI端的输出是一对差分信号,差分信号的主要作用是为了抑制抗共模噪声,一对差分对在几乎相同的布局布线上,收到外面噪声的干扰几乎是一直,但因为是差分的,当接收端接收到了差分信号时,可以很好的解决掉噪声的干扰。所以,

    需要给串行化的数据添加一个OBUFDS(单端转差分)的原语

    例化之后如下所示:

     Par2ser模块接口说明:

    Name

    输入输出

    说明

    clk

    input

    慢时钟,10bit数据随路时钟

    clk_5x

    input

    快时钟,串行化数据随路时钟

    rst_n

    input

    复位,低有效

    i_dat_10bit

    input

    输入10bit数据

    ser_p

    output

    输出1bit差分数据      

    ser_n

    output

     

    至此,HDMI_TRANS的三个模块就完成了,先例化VGA_TIMING模块,将R,G,B像素点的值和行场同步信号传出去,在顶层需要将encode模块例化三次(R,G,B),然后10bit的数据进入par2ser模块转成单端的数据输出,同时不要忘了对时钟也需要经过par2ser模块,注意在顶层需要输出一个HDMI_OUT_En信号,高电平有效,为HDMI的使能。

    1. Modelsim仿真:

     为了能观察的确切,将主时钟的时钟频率调到10M,5倍时钟为50M,这样的话就完

    在Modelsim仿真时:出现了一个未知的错误:

    好像说是encode模块没有定义时间,功能文件是不可不用定义的呀,只有tb测试文件才需要,在网上询问了一番,找到了解决的办法:对于这个错误,可以通过一个指令来屏蔽掉。具体如下:底层模块没有是`timescale或者timeunit/timepresicion定义,在仿真加载时会出错,而不是像之前版本一样作为告警。
    解决:可以使用在vsim指令后加-supress 3009屏蔽该告警。

    说的是好像ModelSim的版本不同导致的。

    解决完之后,仿真波形如下:

    由于RGB 赋值时连续一样,所以差分的串行输出也是一样,但并不影响结果。

     

        HDMI_trans模块算是基本完成了,但是还没有和DDR3挂和关系,如果要和DDR3方面联系在一起,就需要将VGA_TIMNG的R,G,B数据的值,由DDR3模块传送过来,而DDR3的值由串口发送过来的图像数据,这样就完成了DDR3联合HDMI进行图片的显示,这就是我们下一步该做的。

    DDR3联合HDMI

    在完成了各个模块之后,将DDR3模块和HDMI模块统一在一起,用一个大的顶层串在一起。如下所示:

    关于时钟方面:外部晶振过来的时钟为50M,我的方法时50先经PLL分别生成100M,125M和200M时钟DDR3时钟,在用100M的时钟去经过PLL生成65M和325M的HDMI时钟。由于模块有点多参杂在一起,我的想法是先用Modelsim进行一些简单的功能仿真,当Modelsim觉得差不多了,可以下板子试试,如若出错,可以用Modelsim联合ChipSocpe的方法,依靠抓取实际的波形,和仿真波形对比,基本上能解决很多问题。

    首先是添加XDC文件,先找到之前在DDR3 IP核中绑定过的管脚,其所在位置如下  

       复制一份然后在其基础上添加别的管脚的约束,包括时钟复位,HDMI模块:

     完成后启动ModelSim仿真,观察DDR3 和HDMI之间数据交互的情况:

     

       由上波形图可以看出,DDR3刚复位时,,外部的fifo为空,需要向DDR3_ctrl给出命令,读出数据填充,,当等到HDMI显示的第一行有效区域时,将fifo中数据读取走,送给HDMI显示,,当fifo数据小于门限值时,就会继续向DDR3读取数据,以此往复,循环起来,这样的话,HDMI和DDR3的读模块就结合起来了,上面已经完成DDR3的写,这次完成了读,就可以联合串口,发送数据到DDR3,在读取DDR3的数据到HDMI显示,这是本次工程的最终实验结果。

     

     

     

    将以前用过的串口可以直接拿过来用,切记将串口参数改一下,波特率改为115200,系统时钟为125M,例化串口并添加相对应的管脚约束后,用matlab将一幅图片转化为24bit的RGB数据,然后将数据通过串口发送到DDR3中

           Matlab代码如下:,

     

       在下板子之后,出现了屏幕画面闪动的问题,就像平时在打游戏的时候有掉帧的情况,在Modelsim观察不出问题之后,调取ChipSocpe来抓取工程中的信号,首先观察user_rd_ctrl模块中的pixel_rgb[23:0], fifo_rd_en, fifo_rd_count[10:0], fifo_wr_count[10:0],

    触发信号为fifo_rd_en的上升沿,时钟为VGA的65M时钟,

    计数器在这个时刻为0,但是RGB却有值,说明计数器曾经到到过门限值,而打开了FIFO的读使能,但是现在却为0,中间肯定出了一些现在还未知的错误,这就需要在抓一下其他的波形来观察。

           应当注意的是,当需要观察别的波形时,需要改变chipsocpe所添加的波形时,可以将原来观察的信号截图留下来,一边和之后的波形一起观察。

     

    对着波形仔细找了下代码,发现swap是给出写命令或者读命令的条件,结果写反了,这也是自己一时粗心大意而造成的,改过之后,抓取波形图如下:

     

    通过串口串口发送一幅(0-255)黑白渐变的图片数据,可以帮组我们更好的找出错误所在:

    发送完成之后,在显示器上显示如下:

     

     

     

     

    展开全文
  • 我们总结一下已经掌握的 PS与 PL进行 交互(耦合)的...大量 的数据DDR3存储器 。 那么我们 可以在很熟悉 AXI MASTER和 AXI Stream的基础上自 己编写接口实现数据的搬运 假如的话) 。 而 通常在 VIVADO开发环境下

    我们总结一下已经掌握的
    PS与 PL进行 交互(耦合)的方式
    1, PS通过 AXI_LITE读写 PL的寄存器。实现对少量外设寄存器的控制。
    2, PL中断 PS PS调用中断服务程序响应。实现 PL主动通知 PS,协调工作。
    以上两个特性侧重于
    控制和小量低速 的数据,在很多应用中要求 PL以足够的带宽 传输连续
    大量 的数据到 DDR3存储器 。 那么我们 可以在很熟悉 AXI MASTER和 AXI Stream的基础上自
    己编写接口实现数据的搬运 假如的话) 。 而 通常在 VIVADO开发环境下不需要这样做:
    VIVADO给我们提供了多中 IP核,如 DMA CDMA DATAMOVER 以及用于视频数据的 VDMA。
    且在
    zynq中由 arm核进行逻辑控制操作。并非由 pl控制(毕竟这些核本身就属于嵌入式设
    计分类中,而非纯粹的 fpga核)。至于生成的 ip核是否占用资源还没有研究过。
    有读就有写,有输入就有输出,有
    PL从 DDR读数,就有 PL写数到 DDR。所有 VIVADO提供
    的所有的上述 IP 都是有从 PL部分写数到 DDR,也有从 DDR读数到 PL部分。 PL部分我们一
    般用数据流表 示,具体来说是 AXI_STREAM;我们一般是用内存映射地址方式即 MAPED MEMORY表示的。所以一般表示方向就有了 MM2S和 S2MM,即
    MM2S:从地址映射的内存到 数据流接口,具体说从 DDR搬运数据到 PL。
    S2MM:从数据流接口到地址映射的内存接口,具体说从 PL搬运数据到 DDR。
    我们对照图来看一下:在这里插入图片描述
    以上说有
    DMA,VDMA,CDMA,以及 DATAMOVER这几种方式,我们实际来学习一个 IP。这四
    个 IP中最基础的是 DATAMOVER,其实也是最重要的,其他的另外三个都是包装了
    DATAMOVER实现的,接下来我们来学习一下 DATAMOVER。在这里插入图片描述
    上图为
    DATAMOVER核概观。大致为,接受控制命令,控制读或写,并返回核工作状态。
    并且
    控制模块 使用了先入先出队列,实现完全的异步工作。对 DATAMOVER来说,他是不断
    直接行命令,若没有这个 FIFO,执行完每条令执行之后,通过 STATUS告知 PL端的控制器,
    之后 PL端再发来新的命令,之后 DATAMOVER再执行,这就个步骤下来,几个周期甚至更
    多周期就已经损失掉了。所以使用队列就是为了让 DATAMOVER的工作不间断:执行完当前
    指令,可以立即 从队列获取下一命令进行执行。
    DATAMOVER接受主机控制命令的控制寄存器( MM2S和 S2MM均可使用。且为一次写入。
    无需反复写入)。默认为 72bit(对应的是使用 32bit的 axi地址)。可被扩展(在 ip核配置
    界面)。且地址应该为 8的整数倍,(例, ,33位地址则设置为 40位)。在这里插入图片描述
    BTT Bytes To Transfer 要传送的字节数。 且在 ip核内配置实际的位数,默认为 16。不允
    许从 0开始,会造成错误。其取值范围为 1到 8388607。
    TYPE 用于设置接入的方式。 1表示 地址 加一操作。 0则是固定地址
    DRR :从新对齐使能,以及参考字节
    DSA :从新对齐使能,以及参考字节 ,仅 MM2S使用。
    EOF 是否为最后一次传输, 最后一帧到来,则 发送 TLAST信号 。
    SADDR:开始地址。 并且地址应为 8的整数倍。可在 vivado里看到。根据具体配置。
    TAG 四位,标识命令。 并插入。
    Xcache ,Xuser 是出现在 MM2S的 或 S2MM 的 AXI_stream额外标识信号。在这里插入图片描述
    上图为基本模式下的寄存器。对于此状态下。
    Btt位可自己设置。但应该位 8的整数倍。
    本例子中实现的是
    1024X768的视频显示,所以 VGA接口的时钟频率是 65M。
    这里的位图文件是
    24位色的,由于实际板载 VGA只有 12位色,是使用了 RGB三基色的前
    4位作为显示。
    下图为
    Ip手册上给出的参考模型。除了基本的控制模块核 datamover核外。还应额外加上
    一个 fifo模块。在这里插入图片描述
    原理图在这里插入图片描述
    在这里插入图片描述
    关于
    lite核用户逻辑。主要为绑定寄存器。在这里插入图片描述
    Sdk代码。

    1. 从 ddr读写数据到 pl。
      由下图可知。基地址为
      0X43C00000 m_data[63:32]对应为寄存器 0 slv_reg0)。基址加 20则对应寄存器 5的前两位。在这里插入图片描述
      在这里插入图片描述
      其中
      Xil_DCacheFlushRange函数为将 cache数据从指定的地址更新到到 ddr。第一个参数为。
      基地址。第二个为参数
    2. 从 pl写数据到 ddr
      在这里插入图片描述
      和上面一样。不同的是对进行了设置。在这里插入图片描述
      在这里插入图片描述
    展开全文
  • 提出一种以多核DSP TMS320C6678为核心的高速数据传输存储系统,基于DSP高速串行Rapid IO(SRIO)模块进行图像数据高速传输,使用SRIO模块的Direct I/O传输模式,采用4x接口模式配置,每路接口传输速率为3.125 Gb/s,...
  • 实验中,处理机和上位机之间的数据传输距离不小于8m。在这种前提下,计算机上现有的串口、并口显然不能满足要求,而USB2.0接口工作在高速模式时传输距离只有3m,其它诸如以太网传输的实时性难于满足要求,光纤通道...
  • 本测试程序实现的功能是: PC 与 FPGA 通过 PCIE 进行 DMA 方式的数据传输
  •  如果使用的是内部的16MHz时钟,这三行初始化代码应该可以启动串口传输数据,但是我发现数据传输的过程中出错,刚开始也怀疑是串口配置出错,假如配置出错,理论上是不会收到数据的,上面的代码能在内部时钟下...

            最近有个小东西用到STM8S来驱动,之前用STM8S使用的是内部自带的16MHz RC时钟,尚未尝试过使用外部晶振作为主时钟。今天记录一下使用外部晶振时遇到的一个问题。

          老规矩,在进行程序设计时,首先初始化时钟,本次使用的是STM8S103F3P6芯片,8MHz的外部晶振,为了方便内外部时钟切换,结合资料写了两个切换函数

    /***********************************************
    *描述:采用内部16MHz的RC时钟为主时钟
    *      初始化时钟为1分频 16M,无外部晶振
    *版本:V1.0
    *作者:
    ************************************************/
    void HsiInit(void)
    {
        CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
    }
    /***********************************************
    *描述:采用8M外部晶振为主时钟,用于时钟切换    
    *版本:V1.0
    *作者:
    ************************************************/
    void HseInit(void)
    {   
      CLK_DeInit();                                         //时钟初始化
      CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);              //8MHz,不分频
      CLK_HSECmd(ENABLE);                                   //外部时钟开  
      CLK_HSICmd(ENABLE);                                   //内部RC开 
      while(SET != CLK_GetFlagStatus(CLK_FLAG_HSERDY));    //等待外部晶振起振 
      CLK_ClockSwitchConfig(CLK_SWITCHMODE_MANUAL,CLK_SOURCE_HSE,DISABLE,CLK_CURRENTCLOCKSTATE_DISABLE);
      CLK_ClockSwitchCmd(ENABLE);                           //开始切换 
    }

    在主函数调用所需的时钟函数即可,为了验证外部时钟是否切换成功,我在定时器1的通道1输出PWM进行验证,所幸得到了想要的波形,定时器1的配置如下

    /***********************************************
    *描述:TIM1CH1(PC6)输出PWM,频率为1K
    *      定时器时钟为外部的8MHz
    *版本:V1.0
    *作者:
    ************************************************/
    void TIM1_Init(void)
    {
        TIM1->EGR = 0x01;//重新初始化定时器1
        TIM1->CR1 = 0x00;//边沿对齐方式,向上计数,发生更新事件,计数器不停止更新
        TIM1->RCR = 0x00;//重复计数器的值为0,计时时间到,重复多少次产生中断,该值是重复多少次那个值
        
        //设定预分频为,80分频 8M
        TIM1->PSCRH =0x00;  //PWM的时钟 影响周期
        TIM1->PSCRL =0x4f;  //80分频,TIM1的时钟为100K
    
        TIM1->ARRH = 0x00;  //设定重装载值
        TIM1->ARRL = 0x63;  //计数100次,等于T,即1ms(f=1K),每10us计一个数
    
        //CH1
        TIM1->CCER1 = 0x01; //CC2ER1开启CH1,CC1配置入输出,低电平有效
        TIM1->CCMR1 = 0x68; //PWM模式1,使能预装载
    
        //设置占空比
        TIM1->CCR1H = 0x00;
        TIM1->CCR1L = 0x0A;  // 占空比值
    
        TIM1->OISR &= ~0x03;
        TIM1->BKR |= 0x80;   //刹车
        TIM1->CR1 |= 0x01;  //使能TIM1计数器
        
    //    GPIO_Init(GPIOC, GPIO_PIN_6, GPIO_MODE_OUT_PP_LOW_FAST);
        GPIOC->DDR|=0xff;//输出
        GPIOC->CR1|=0xff;//推挽
        GPIOC->CR2|=0xf0;//速度
    }

    接下来开始进入本次主题,采用8MHz外部时钟时,串口1传输数据异常。开始时串口初始化函数如下,使用波特率是9600

    void Uart1_Init(u32 Baudrate)
    {
        UART1_DeInit(); 
        UART1_Init((u32)Baudrate, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, UART1_PARITY_NO, UART1_SYNCMODE_CLOCK_DISABLE, UART1_MODE_TXRX_ENABLE);
        UART1_Cmd(ENABLE );  //启用串口
    }

            如果使用的是内部的16MHz时钟,这三行初始化代码应该可以启动串口传输数据,但是我发现数据在传输的过程中出错,刚开始也怀疑是串口配置出错,假如配置出错,理论上是不会收到数据的,上面的代码能在内部时钟下正常传输数据,在外部时钟下传输出错,那很大可能就是波特率出现了问题。

          串口初始化的波特率是9600,串口调试助手在9600的波特率下得不到正确的数据,printf打印出来的是乱码

    啒f槝骧槝灅?榾ff啒f槝骧槝灅?榾ff啒f槝骧
    槝灅?榾ff啒f槝骧槝灅?榾ff啒f槝骧槝灅?榾ff
    啒f槝骧槝灅?榾ff啒f槝骧槝灅?榾ff啒f槝骧
    槝灅?榾ff啒f槝骧槝灅?榾ff啒f槝骧槝灅?榾ff
    啒f槝骧槝灅?榾ff啒f槝骧槝灅?榾ff啒f槝骧
    槝灅?榾ff啒f槝骧槝灅?榾ff啒f槝骧槝灅?榾ff

    当我把串口调试助手的波特率改为4800后,神奇的一幕出现了

    ART1 is OK!
    UART1 is OK!
    UART1 is OK!
    UART1 is OK!
    UART1 is OK!
    UART1 is OK!
    UART1 is OK!
    UART1 is OK!
    UART1 is OK!
    UART1 is OK!
    UART1 is OK!

    为什么呢?很好奇发生了什么,我把波特率两个寄存器值打印出来

    UART1->BRR2: 2
    UART1->BRR1: 68
    UART1->BRR2: 2
    UART1->BRR1: 68
    UART1->BRR2: 2
    UART1->BRR1: 68
    UART1->BRR2: 2
    UART1->BRR1: 68

          结合STM8S参考手册,将这两个寄存器的值还原,得到UART_DIV = 0x0682,十进制就是UART_DIV = 1666,按照公式:

                                         UART_DIV  = F / Baudrate,其中F是主时钟频率,Baudrate是波特率,为9600

    那么主时钟频率 = 1666 * 9600 = 15993600,接近16MHz,通过上面可以观察到,UART_DIV = 1666对应的是16MHz,那么8MHz应该为多少?

    UART_DIV  =  8000 000 / 9600 = 833.3,即UART_DIV  = 0x0341

    参考数据手册的设置规则,BRR1和BRR2的值应该为

        UART1->BRR2 = 0x01;
        UART1->BRR1 = 0x34;

    所以串口初始化函数应该为(注意必须是先设置BRR2,再设置BRR1)

    void Uart1_Init(u32 Baudrate)
    {
        UART1_DeInit(); 
        UART1_Init((u32)Baudrate, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, UART1_PARITY_NO, UART1_SYNCMODE_CLOCK_DISABLE, UART1_MODE_TXRX_ENABLE);
        UART1->BRR2 = 0x01;
        UART1->BRR1 = 0x34;
        UART1_Cmd(ENABLE );  //启用串口
    }

    此时,再将串口调试助手的波特率设置为9600,可以得到如下数据

    UART1->BRR2: 1
    UART1->BRR1: 34
    UART1->BRR2: 1
    UART1->BRR1: 34
    UART1->BRR2: 1
    UART1->BRR1: 34
    UART1->BRR2: 1
    UART1->BRR1: 34
    UART1->BRR2: 1
    UART1->BRR1: 34
    UART1->BRR2: 1
    UART1->BRR1: 34
    UART1->BRR2: 1
    UART1->BRR1: 34

    至此,串口调试完成,引起传输数据出错,应该是库函数计算波特率是以内部的16MHz频率作为标准,假如你要用到其他频率,需要重新设置BRR1和BRR2这两个寄存器的值。

    展开全文
  • LVDS(Low Voltage Differential Signaling)即低压差分信号传输,是一种满足当今高性能数据传输应用的新型技术。由于其可使系统供电电压低至 2V,因此它还能满足未来应用的需要。此技术基于ANSI/TIA/EIA-644 LVDS ...
  • 红圈中的信息就是对数据传输的一些配置,我们可以看到FPGA 到ARM的数据传输采用的是AXI总线协议,前两个都是高速AXI、最后一个是低速AXI,位宽分别设置成128、32、32bit。Altera还单独给了我们一个对DDR直接操作的...
  • 实现USB2.0高速数据传输的问题探讨

    千次阅读 2015-08-11 19:13:52
    摘要:针对USB2.0高速数据传输在实际应用中存在的具体问题,深入分析了诸如协议开销、带宽...并利用USB2.0控制 芯片EZ-USB FX2进行了不同模式数据传输的实验.最后在此基础上指出解决高速数据传输问题的几条对策。
  • FPGA学习日记(七)HDMI图像数据传输

    千次阅读 2020-08-14 22:46:35
    (1)通过三个通道分别可传入8位的rgb视频信号,2位的控制信号,4位的音频信号或其他数据信号,其中行场同步信号在blue的控制信号中传输; (2)在encode编码器这端,将输入的8位视频信号通过TMDS算法转换为10位的...
  • DDR,DDR2,DDR3区别

    千次阅读 2018-02-02 17:25:12
    DDR是一种继SDRAM后产生的内存技术,DDR,英文原意为“DoubleDataRate”,顾名思义,就是双数据传输模式。之所以称其为“双”,也就意味着有“单”,我们日常所使用的SDRAM都是“单数据传输模式”,这种内存的特性是...
  • FPGA+DSP SRIO通信(三)——基于LSU的数据传输

    万次阅读 多人点赞 2017-05-15 22:29:48
    之前的配置中我们知道如何配置通道速率、设置deviceID。 也就是马路已经铺设好了,我们应该造车...二、LSU传输流程 三、LSU方式_发送代码的实现 下面提及的关于LSU寄存器的详细知识,在我的以下两篇博客中...
  • FPGA之LVDS传输

    千次阅读 2019-08-23 18:10:34
    以两个FPGA的LVDS互联作为示例,V71数据传输给V72 接口 I/O 定义 V71 V71_V72_TRAIN_P I 传输开始标志 V71_V72_TRAIN_N I 传输开始标志 V71_V72_LVDS_CLKP O LVDS随路时钟 ...
  • SDR与DDR的区别

    千次阅读 2019-05-27 23:08:00
    传统的SDR SDRAM只能在信号的上升沿进行数据传输,而DDR SDRAM却可以在信号的上升沿和下降沿都进行数据传输,所以DDR内存在每个时钟周期都可以完成两倍于SDRAM的数据传输量,这也是DDR的意义——Double Data Rate,...
  • DDR扫盲——DDR与DDR2、DDR3的区别

    万次阅读 多人点赞 2018-10-06 15:11:57
    DDR2的实际工作频率是DDR的两倍,DDR2内存拥有两倍于标准DDR内存的4bit预期能力。 2、封装与电压 DDR封装为TSOPII,DDR2封装为FBGA; DDR的标准电压为2.5V,DDR2的标准电压为1.8V。 3、bit...
  •  i.MX 6ULL系列芯片的MMDC是一个多模式DDR控制器,支持DDR3/DDR3Lx16和LPDDR2x16的存储类型,MMDC是可配置,高性能,优化的内存控制器。  注:DDR3/DDR3Lx16、LPDDR2x16 ,此处的x16表示芯片位宽,每个传输周期...
  • 数据中心是一整套复杂的设施。它不仅仅包括计算机系统和其它与之配套的设备(例如通信和存储系统),还包含冗余的数据通信连接、环境控制设备、监控设备以及各种安全装置”。谷歌在其发布的《The Datacenter as a ...
  • 基于ZYNQ的uart传输任意长度的数据

    千次阅读 2019-09-02 15:36:07
    参见上一次实验:基于ZYNQ 的UART中断实验之串口写数据DDR3中 3、实验目的 基于ZYNQ 的UART中断实验,这里在上一次实验的基础上将发送固定的数据改为可以发送不定的数据。 4、实验过程 建立工程,设置并初始化串口...
  • 细说DDR

    2021-02-28 21:48:47
    同步是指其时钟频率与CPU前端总线的系统时钟频率相同,并且内部的命令的发送与数据传输都以它为基准;动态是指存储阵列需要不断的刷新来保证数据不丢失,随机是指数据不是线性依次存储,而是自由
  • DDR,DDR2,DDR3,DDR4,LPDDR区别

    万次阅读 多人点赞 2019-12-22 22:47:42
    DDR,DDR2,DDR3,DDR4,LPDDR区别 作者:AirCity 2019.12.17 Aircity007@sina.com 本文所有权归作者Aircity所有 1 什么是DDR DDR是Double Data Rate的缩写,即“双比特翻转”。DDR是一种技术,中国大陆工程师习惯用...
  • DDR,DDR2,DDR3,DDR4,LPDDR区别讲解

    千次阅读 2021-01-04 10:36:11
    1 什么是DDR DDR是Double Data Rate的缩写,即“双比特翻转”。...DDR的核心要义是在一个时钟周期内,上升沿和下降沿都做一次数据采样,这样400MHz的主频可以实现800Mbps的数据传输速率。 RAM,ROM,SRAM,DRAM,SDR
  • LVDS(Low Voltage Differential Signaling)即低压差分信号传输,是一种满足当今高性能数据传输应用的新型技术。由于其可使系统供电电压低至 2V,因此它还能满足未来应用的需要。此技术基于ANSI/TIA/EIA-644 LVDS ...
  • BL)也固定为8,而对于DDR2和早期的DDR架构系统,BL=4也是常用的,DDR3为此增加了一个4bitBurstChop(突发突变)模式,即由一个BL=4的读取操作加上一个BL=4的写入操作来合成一个BL=8的数据突发传输,届时可通过A12...
  • DDR存储器接口

    千次阅读 2020-04-19 23:22:18
    与传统的SDR SDRAM不同的是,DDR SDRAM采用双数据速率端口,在时钟的正沿和负沿都需要对数据进行采样,是一种2-n预取(2-n Prefetch)结构,即每个时钟周期数据传输率为2nbit。 由于DDR SDRAM的频率很高,如果...
  • DDR工作时序

    2019-11-04 15:43:32
    下图是DDR和SDRAM的数据传输对比图 图上可以清楚的看到,DDR SDRAM可在一个时钟周期内传送两次数据,上升沿传一次,下降沿传一次。 1.DDR的基本原理 先来看一张DDR读操作时序图 从中可以发现它多了两个信号:C.....
  • DDR工作原理

    万次阅读 多人点赞 2018-06-21 18:57:44
    DDR SDRAM全称为Double Data Rate SDRAM,中文名为“双倍数据流SDRAM”。DDR SDRAM在原有的SDRAM的基础上改进而来。也正因为如此,DDR能够凭借着转产成本优势来打败...DDR的核心频率、时钟频率和数据传输频率: ...
  • DDR2基础

    千次阅读 2018-10-27 23:15:46
    一. DDR2介绍 DDR2由JEDEC(电子设备工程联合委员会)开发的新生代内存技术标准。该标准定义了DDR2封装、寻址及操作、电气等所有特性。 DDR相关技术对比 ...数据传输率 200~400 400~...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,326
精华内容 2,930
关键字:

数据的传输模式是ddr传输