基于FPGA的SDRAM实验Verilog源代码
- 格式:docx
- 大小:21.10 KB
- 文档页数:12
毕业设计(论文)机械与电气工程学院电气工程及其自动化专业毕业设计(论文)题目基于FPGA的SDRAM控制器的实现(软件部分)学生姓名班级电气工程及其自动化学号指导教师完成日期2012 年 6 月 6 日基于FPGA的SDRAM控制器的实现(软件部分)The realization of SDRAM controller based on FPGA (software)总计毕业设计(论文) 41 页表格 6 个插图 21 幅摘要文中介绍了FPGA的开发流程、硬件开发语言及其开发环境QuartusII和SDRAM的结构特点和工作原理,根据SDRAM的工作原理、控制时序和指令特点,设计一种基于FPGA的SDRAM控制器的方案。
SDRAM控制器的设计主要由主控制模块、信号产生模块、数据路径模块和参数模块组成。
本设计解决SDRAM控制复杂、不方便的问题,并用Verilog给予仿真结果。
仿真结果表明使用该方法设计实现的控制器能够使系统方便,可靠的对SDRAM进行操作。
关键字:SDRAM控制器FPGA 控制模块软件仿真AbstractThis paper introduces the development process and FPGA hardware development language and the development environment of SDRAM QuartusII and structural characteristics and working principle, according to the working principle of SDRAM, sequence control and instruction characteristics, a scheme based on FPGA SDRAM controller is designed. SDRAM controller design mainly by the master control module, signal module, data path module and parameter module composition. This design solved a problem about the controlling complexity of SDRAM controller, and gives the simulation results by using Verilog. The simulation results show that using this method to design the controller can realize the system is convenient, reliable operation of SDRAM.Key words: SDRAM controller FPGA Control module Software simulation目录摘要 (I)Abstract (II)第一章绪论 (1)课题背景 (1)课题研究的意义 (1)第二章FPGA与Quartus II软件简介 (2)FPGA简介 (2)FPGA背景 (2)FGPA结构原理 (2)Quartus II软件简介 (3)硬件描述语言Verilog (4)FPGA开发过程 (5)第三章SDRAM的技术介绍 (6) (6)SDRAM简介 (6)SRAM和DRAM (6)SDRAM发展过程 (7)SDRAM工作原理和基本操作 (8)SDRAM存储的工作原理 (9)SDRAM 的引脚信号 (9)SDRAM基本命令 (10)SDRAM初始化 (10)SDRAM读、写操作 (11)终止操作 (12)第四章 SDRAM控制器设计 (12)SDRAM控制器 (13)主控制模块 (14)信号产生模块 (16)参数模块 (18)数据通路模块 (19)第五章SDRAM的读、写仿真 (19)SDRAM控制器时序仿真 (20)Quartus II (20)读仿真时序 (20)写仿真时序 (21)仿真结果分析 (22)结论 (24)参考文献 (25)致谢 (26)附录 (27)第一章绪论课题背景伴随着电子信息技术的飞速发展和其在通讯、工业、商业、医疗等方面的广泛应用,人们对信息的需求逐渐向着更快、更多、更准确发展。
Open Journal of Circuits and Systems 电路与系统, 2014, 3, 19-24Published Online March 2014 in Hans. /journal/ojcs/10.12677/ojcs.2014.31004Design of SDRAM Controller Based on FPGALingli Zhong, Xiaobo ZhouSchool of Electronic Science and Technology, Beijing Jiaotong University, BeijingEmail: 09214027@, xbzhou@Received: Feb. 26th, 2014; revised: Mar. 19th, 2014; accepted: Mar. 25th, 2014Copyright © 2014 by authors and Hans Publishers Inc.This work is licensed under the Creative Commons Attribution International License (CC BY)./licenses/by/4.0/AbstractThe paper briefly introduces the characteristics of SDRAM and the basic operation principle, then puts forward a design method of SDRAM controller based on FPGA. The controller was achieved by the language of Verilog. The paper analyses the overall design and the specific realization of the design scheme of each module. Finally, the image data should be stored in SDRAM, and then the reading control through SDRAM should be achieved, which sent the data to display on the VGA screen. When the colorful picture was displayed on the screen, it means the function of the SDRAM controller was achieved.KeywordsSDRAM Controller; FPGA; Verilog基于FPGA的SDRAM控制器设计开发仲玲利,周晓波北京交通大学电子信息学院,北京Email: 09214027@, xbzhou@收稿日期:2014年2月26日;修回日期:2014年3月19日;录用日期:2014年3月25日摘要在简要介绍SDRAM特点和基本操作原理的基础上,提出了一种基于FPGA的SDRAM控制器的设计方法,用Verilog硬件语言加以实现。
基于FPGA的双端口SDRAM控制器的实现康磊;雒明世【摘要】在实时图像处理系统中数据存储和共享是一项关键技术.SDRAM凭借其大容量、高数据传输速率和低成本优势,正在广泛的被应用于实时图像处理系统中,为此,提出了一种基于FPGA技术的具有两个独立读写端口的SDRAM控制器方案.详细介绍了SDRAM控制器的模块构成、实现过程及其仿真结果,控制器是采用Verilog HDL实现的.通过仿真测试和硬件实验说明设计方案可行,可应用于实时信号的采集和处理系统中.%Data storage and sharing is a key technology in the real-time image processing system.Owing to its large capacity,high data transfer rate and low cost,SDRAM is increasingly used in real-time image processing system.For this reason,this paper puts forward a SDRAM controller scheme which has two independent reading and writing data ports based on FPGA technology.This paper introduces the structure and implementation process of a SDRAM controller module,and also gives the simulation results.The SDRAM controller is implemented by using Verilog HDL.The simulation test and hardware experiments show that this design scheme is feasible,and can be applied to real-time signal collection and processing system.【期刊名称】《电气自动化》【年(卷),期】2013(035)004【总页数】3页(P97-99)【关键词】SDRAM;FPGA;控制器;双端口;Verilog【作者】康磊;雒明世【作者单位】西安石油大学计算机学院,陕西西安710065;西安石油大学计算机学院,陕西西安710065【正文语种】中文【中图分类】TP330 引言在视频图像实时处理系统中,在数据的采集和显示环节需要实现快速的大量数据访问,因而就需要大容量高速度的存储设备进行数据存取,SDRAM具有容量大、速度快、价格低的特点,同时还具有较低的功耗,因此目前已经广泛地应用于实时系统中。
基于FPGA的SDRAM存储器接口实现摘要随着信息科学的飞速发展,人们面临的信号处理任务越来越繁重,对数据采集处理系统的要求也越来越高。
单片机、DSP等微处理器内部RAM 有限,这就需要在微处理器的外部扩展存储器。
同步动态随机访问存储器具有价格低廉、密度高、数据读写速度快的优点,从而成为数据缓存的首选存储介质,在数据采集系统和图像处理系统等方面中有着重要和广泛的应用。
SDRAM 的读写逻辑复杂,最高时钟频率达100MHz 以上,普通单片机无法实现复杂的SDRAM 控制操作。
复杂可编程逻辑器件CPLD具有编程方便,集成度高,速度快,价格低等优点。
因此选用CPLD 设计SDRAM 接口控制模块, 简化主机对SDRAM 的读写控制。
通过设计基于CPLD 的SDRAM 控制器接口,可以在STM系列、ARM系列、STC系列等单片机和DSP等微处理器的外部连接SDRAM,增加系统的存储空间。
论文开始介绍了SDRAM接口设计研究的背景和研究的目的及意义,引出对SDRAM的研究,详细介绍了SDRAM的基本原理、内部结构、基本操作和工作时序,以及设计的重点及难点。
在这些理论基础上对SDRAM 接口进行模块化设计,了解设计中所使用的硬件和软件。
最后用Verilog语言在软件QuartusⅡ设计CPLD芯片,通过在硬件和软件上的调试基本实现了SDRAM接口的设计。
关键词SDRAM;接口;Verilog;CPLDThe Implementation of SDRAM MemoryInterface Based on the EPM570AbstractWith the rapid development of information science, people face more and more onerous task of signal processing, the requirements of data acquisition and processing system are getting higher and higher. Microprocessor such as single-chip microprocessor, DSP etc, their RAM is limited, which requires external expansion in the microprocessor memory. Synchronous Dynamic Random Access Memory has a low cost, high density, fast read and write data on the merits, thereby becoming the first choice for data cache storage medium, which paly an important role and widely used in the data acquisition system and image processing systems.SDRAM read and write logic is complex, the maximum clock frequency reaches above 100MHz, the ordinary microcontroller can not achieve complex SDRAM control operation. Complex programmable logic device has advantages such as programming convenience, high integrity, high speed and low cost etc. Therefore select CPLD to design control module of SDRAM interface , to simplify the host to read and write control of the SDRAM. Through the design of SDRAM controller interface based on CPLD, you can connect SDRAM in the external of STM series, ARM series, STC series single chip microprocessor and the DSP, increase system storage space.At the beginning of paper introduces the research background, research purpose and significance of the study of SDRAM interface design, leads to the study of SDRAM, detailed introduces information of SDRAM about the basic principles, the internal structure, the basic operation and timing of work, and the design emphasis and difficulty. Based on these theories, modularing the designof SDRAM interface, understanding hardware and software used in the design. Finally, it uses Verilog language in Quartus Ⅱsoftware to design CPLD chip, Through the hardware and the software realization SDRAM the commissioning of the basic design of the interface.Keywords SDRAM; Interface; Verilog; CPLD目录摘要 (I)Abstract (II)第1章绪论 (1)1.1 课题背景 (1)1.2 课题研究的目的及意义 (1)1.3 同步动态随机存储器简介 (2)1.4 论文的结构和框架 (3)第2章SDRAM的工作原理 (4)2.1 存储器的概述 (4)2.1.1 存储器的分类 (4)2.1.2 存储器的技术指标 (5)2.1.3 存储器的比较 (5)2.2 SDRAM的工作原理 (6)2.2.1 SDRAM存储的基本原理 (6)2.2.2 SDRAM的内部结构 (7)2.3 本章小结 (8)第3章SDRAM的基本操作 (9)3.1 SDRAM的基本操作 (9)3.1.1 芯片初始化 (9)3.1.2 行有效 (9)3.1.3 列读写 (10)3.1.4 读操作 (11)3.1.5 写操作 (12)3.2 SDRAM的工作特性 (13)3.2.1 模式寄存器的设置 (13)3.2.2 预充电 (14)3.2.3 刷新 (15)3.3 SDRAM接口设计的要求 (16)3.3.1 存储器接口解决数据存取的难点 (17)3.3.2 存储器接口在工作方式上的初步优化 (17)3.4 本章小结 (18)第4章系统结构及硬件设计 (19)4.1 SDRAM接口设计的整体结构 (19)4.1.1 控制接口模块 (19)4.1.2 CAS延迟模块 (20)4.1.3 突发长度模块 (22)4.1.4 地址转换模块 (22)4.2 EPM570芯片简介 (23)4.2.1 MAXⅡ系列芯片功能简介 (24)4.2.2 逻辑阵列 (25)4.2.3 全局时钟 (25)4.2.4 I/O端口结构 (26)4.3 MT48LC系列芯片简介 (26)4.4 本章小结 (28)第5章软件设计与实现 (30)5.1 利用QuartusⅡ进行设计的流程 (30)5.2 软件的设计 (31)5.2.1 Verilog语言的特点 (31)5.2.2 采用Verilog设计综合的过程 (32)5.2.3 SDRAM接口设计的仿真 (34)5.3 本章小结 (36)结论 (37)致谢 (38)参考文献 (39)附录A (41)附录B (46)附录C (51)第1章绪论1.1课题背景数据采集处理技术是现代信号处理的基础,广泛应用于雷达、声纳、软件无线电、瞬态信号测试等领域。
基于FPGA的DDR2SDRAM控制器设计钱素琴,刘晶华(东华大学信息科学与技术学院,上海,201600)摘要:基于高速数据传输与存储的数据釆集记录仪对缓存模块高性能的需求,选择了读写速度快、低成本、大容量、运行稳定的DDR2SDRAM作为本地存储器,在其存储寻址原理和IP核的读写控制逻辑的基础上,借助硬件描述语言设计了一个DDR2存储控制器方案。
在Intel的FPGA Cyclone IV系列开发板上进行了整体方案的功能验证,完成了用户接口和控制器之间的多数据宽度、多突发长度的高效数据传输和读写操作,在166.7MHz时钟频率下实现了稳定读写的目标。
关键词:FPGA;DDR2SDRAM;IP核Design of DDR2SDRAM controller based on FPGAQian Suqin,Liu Jinghua(College of information science and technology,Donghua University,Shanghai,201600) Abstract;Based on the requirement of high-speed data transmission and storage data acquisition recorder for high performance of cache module,DDR2SDRAM with high read-write speed,low cost, large capacity and stable operation is selected as the local memory.Based on its storage addressing principle and the read-write control logic of IP core,a DDR2storage controller scheme is designed with the help of hardware description language.The functional verifiestion of the overall scheme is carried out on the FPGA cyclone IV series development board of Intel.The efficient datQ transmission and read-write operation of multipie data widths and burst lengths between the user interface and the cont r oller are comple t ed.The st a ble read-wr ite t a rge t is achieved a/t166.7MHz clock frequency. Keywords:FPGA;DDR2SDRAM;IP coreo引言随着数据采集系统的发展,应用于图像采集和数据传输等领域的产品对存储器的速度要求越来越高。
基于FPGA AD数据采集存储处理项目报告(XILINX ALTEARA 都可用)组员:华、文、杰一、实验目的本次实验利用Basys2开发板完成一个开发小项目,即开发AD数据采集存储处理系统,旨在掌握FPGA开发基本方法以及锻炼解决开发过程中出现问题的能力。
二、关键词Basys2、FPGA、AD转换、RAM、串口通信、MATLAB处理三、方案设计要实现本次项目,首先确定器件,其次根据器件时序写出模块的使用程序,最后综合成一个工程,然后进行仿真,上板实验。
本次实验的器件:32M8位模数转换器、Basys2开发板、串口转RS232cp2102模块、基于三极管的电平转换电路。
选择好器件后,根据器件的时序完成模块的代码书写。
写好AD模块、串口通信模块后,现在就需要处理采样速率与串口通讯速率不匹配的问题了。
根据香农采样定理,采样频率得高于信号频率的两倍才能完成信号复现,我们这里使用25M的高速采样频率,而串口dps9600传送一个位104us 明显比采样慢许多。
所以这里需要解决速率不匹配的问题。
我们想到可以利用FPGA的RAM先存储采样来的数据,然后再提取数据经过串口通信送至PC经由MATLAB处理。
本次小项目最为关键的是控制好采样与串口通信的时序问题。
关于时序的控制,留到模块介绍里面说明。
方案小结:本次实验基于片内RAM存储AD采样过来的数据,然后待采样完成后提取数据串口通信至PC,最后经由matlab处理。
四、模块介绍1.Verilog开发程序介绍如下给出基于QuartusII绘制出的Block Diagram图,涵盖了所有的模块以及模块之间的连线。
图4.1 综合模块图如下给出程序目录(txt格式):现在分别介绍各个模块的端口以及功能。
AD外设:电路图、实物图、接口这个外设提供最大32M采样速率,包括一个模拟信号输入和一个采样时钟输入以及八个数字信号输出。
在每个采样时钟的上升沿输出相应的采样数字信号。
ddrsdram(mt46v4m16)的fpga控制代码`timescale 1ns / 1psmodule mt46v4m16 (Dq, Dqs, Addr, Ba, Clk, Clk_n, Cke, Cs_n, Ras_n, Cas_n, We_n, Dm); parameter addr_bits = 12;parameter data_bits = 16;parameter col_bits = 8;parameter mem_sizes = 1048575;inout [data_bits - 1 : 0] Dq;inout Dqs;input [addr_bits - 1 : 0] Addr;input [1 : 0] Ba;input Clk;input Clk_n;input Cke;input Cs_n;input Ras_n;input Cas_n;input We_n;input [1 : 0] Dm;reg [data_bits - 1 : 0] Bank0 [0 : mem_sizes];reg [data_bits - 1 : 0] Bank1 [0 : mem_sizes];reg [data_bits - 1 : 0] Bank2 [0 : mem_sizes];reg [data_bits - 1 : 0] Bank3 [0 : mem_sizes];reg [1 : 0] Bank_addr [0 : 6];reg [col_bits - 1 : 0] Col_addr [0 : 6];reg [3 : 0] Command [0 : 6];reg [addr_bits - 1 : 0] B0_row_addr, B1_row_addr, B2_row_addr, B3_row_addr;reg [addr_bits - 1 : 0] Mode_reg;reg [data_bits - 1 : 0] Dq_dm, Dq_out;reg [col_bits - 1 : 0] Col_temp, Burst_counter;reg Act_b0, Act_b1, Act_b2, Act_b3;reg Pc_b0, Pc_b1, Pc_b2, Pc_b3;reg Dqs_int, Dqs_out;reg [1 : 0] Bank_precharge [0 : 6]; // Precharge Command Bankreg A10_precharge [0 : 6]; // Addr[10] = 1 (All Banks)reg Auto_precharge [0 : 3]; // RW AutoPrecharge Bankreg Read_precharge [0 : 3]; // R AutoPrecharge Commandreg Write_precharge [0 : 3]; // W AutoPrecharge Commandinteger Count_precharge [0 : 3]; // RW AutoPrecharge Counterreg Data_in_enable;reg Data_out_enable;reg [3 : 0] Rw_command;reg [1 : 0] Bank, Bank_dqs, Previous_bank;reg [addr_bits - 1 : 0] Row, Row_dqs;reg [col_bits - 1 : 0] Col, Col_dqs;reg [col_bits - 1 : 0] Col_brst, Col_brst_dqs;reg Dll_enable;reg CkeZ, Sys_clk;// Commands Decodewire Active_enable = ~Cs_n & ~Ras_n & Cas_n & We_n;wire Aref_enable = ~Cs_n & ~Ras_n & ~Cas_n & We_n;wire Burst_term = ~Cs_n & Ras_n & Cas_n & ~We_n;wire Ext_mode_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n & Ba[0] & ~Ba[1];wire Mode_reg_enable = ~Cs_n & ~Ras_n & ~Cas_n & ~We_n & ~Ba[0] & ~Ba[1]; wire Prech_enable = ~Cs_n & ~Ras_n & Cas_n & ~We_n;wire Read_enable = ~Cs_n & Ras_n & ~Cas_n & We_n;wire Write_enable = ~Cs_n & Ras_n & ~Cas_n & ~We_n;// Burst Length Decodewire Burst_length_2 = ~Mode_reg[2] & ~Mode_reg[1] & Mode_reg[0];wire Burst_length_4 = ~Mode_reg[2] & Mode_reg[1] & ~Mode_reg[0];wire Burst_length_8 = ~Mode_reg[2] & Mode_reg[1] & Mode_reg[0];// CAS Latency Decodewire Cas_latency_2 = ~Mode_reg[6] & Mode_reg[5] & ~Mode_reg[4];wire Cas_latency_25 = Mode_reg[6] & Mode_reg[5] & ~Mode_reg[4];wire Cas_latency_3 = ~Mode_reg[6] & Mode_reg[5] & Mode_reg[4];wire Debug = 0; // Turn on Debug messageswire Dq_in = Dqs & Data_in_enable; // For checking Data-in Setup/Hold timeassign Dq = Dq_out;assign Dqs = Dqs_out;//Commands Operation`define ACT 0`define NOP 1`define READ 2`define READ_A 3`define WRITE 4`define WRITE_A 5`define PRECH 6`define A_REF 7`define BST 8`define LMR 9`define EMR 10// Timing Parametersparameter tMRD = 2; // 2 Clk Cycles parameter tRC = 70;parameter tRAS = 50;parameter tRCD = 20;parameter tRRD = 20;parameter tRP = 20;parameter tWR = 4; // 2 Clk Cycles (4 Dqs) parameter tWTR = 2; // 1 Clk Cycles (2 Dqs)// Timing Checkinteger MRD_chk, WTR_chk;integer WR_chk[0 : 3];time RC_chk, RRD_chk;time RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3; time RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3; time RP_chk, RP_chk0, RP_chk1, RP_chk2, RP_chk3;initial beginCkeZ = 1'b0;Sys_clk = 1'b0;{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b0000;Dqs_out = 1'bz;Dq_out = {data_bits{1'bz}};{Data_in_enable, Data_out_enable} = 2'b0;{MRD_chk, WTR_chk, RC_chk, RRD_chk} = 4'b0;{RAS_chk0, RAS_chk1, RAS_chk2, RAS_chk3} = 4'b0;{RCD_chk0, RCD_chk1, RCD_chk2, RCD_chk3} = 4'b0;{RP_chk, RP_chk0, RP_chk1, RP_chk2, RP_chk3} = 4'b0;{WR_chk[0], WR_chk[1], WR_chk[2], WR_chk[3]} = 4'b0;//$readmemh("bank0.txt", Bank0);//$readmemh("bank1.txt", Bank1);//$readmemh("bank2.txt", Bank2);//$readmemh("bank3.txt", Bank3);$timeformat (-9, 1, " ns", 12);end// System Clockalways begin@ (posedge Clk) beginSys_clk = CkeZ;CkeZ = Cke;end@ (negedge Clk) beginSys_clk = 1'b0;endendalways @ (Sys_clk) begin// Internal Commamd PipelinedCommand[0] = Command[1]; Command[1] = Command[2]; Command[2] = Command[3]; Command[3] = Command[4]; Command[4] = Command[5];Command[5] = Command[6]; Command[6] = `NOP;Col_addr[0] = Col_addr[1]; Col_addr[1] = Col_addr[2];Col_addr[2] = Col_addr[3];Col_addr[3] = Col_addr[4];Col_addr[4] = Col_addr[5];Col_addr[5] = Col_addr[6];Col_addr[6] = 0;Bank_addr[0] = Bank_addr[1];Bank_addr[1] = Bank_addr[2];Bank_addr[2] = Bank_addr[3];Bank_addr[3] = Bank_addr[4];Bank_addr[4] = Bank_addr[5];Bank_addr[5] = Bank_addr[6];Bank_addr[6] = 2'b0;// Precharge PipelineBank_precharge[0] = Bank_precharge[1];Bank_precharge[1] = Bank_precharge[2]; Bank_precharge[2] = Bank_precharge[3]; Bank_precharge[3] =Bank_precharge[4]; Bank_precharge[4] = Bank_precharge[5]; Bank_precharge[5] = Bank_precharge[6]; Bank_precharge[6] = 2'b0;A10_precharge[0] = A10_precharge[1];A10_precharge[1] = A10_precharge[2];A10_precharge[2] = A10_precharge[3];A10_precharge[3] = A10_precharge[4];A10_precharge[4] = A10_precharge[5];A10_precharge[5] = A10_precharge[6];A10_precharge[6] = 1'b0;// tWR counterWR_chk[0] = WR_chk[0] + 1;WR_chk[1] = WR_chk[1] + 1;WR_chk[2] = WR_chk[2] + 1;WR_chk[3] = WR_chk[3] + 1;WTR_chk = WTR_chk + 1;// Commands Operation decodeif (Sys_clk === 1'b1) begin// Read or Write with Auto Precharge Counterif (Auto_precharge[0] === 1'b1) beginCount_precharge[0] = Count_precharge[0] + 1;endif (Auto_precharge[1] === 1'b1) beginCount_precharge[1] = Count_precharge[1] + 1;endif (Auto_precharge[2] === 1'b1) beginCount_precharge[2] = Count_precharge[2] + 1;endif (Auto_precharge[3] === 1'b1) beginCount_precharge[3] = Count_precharge[3] + 1;end// tMRD CounterMRD_chk = MRD_chk + 1;// Auto Refreshif (Aref_enable === 1'b1) beginif (Debug) $display ("at time %t AREF : Auto Refresh", $time);// Auto Refresh to Auto Refreshif ($time - RC_chk < tRC) begin$display ("at time %t ERROR: tRC violation during Auto Refresh", $time);end// Precharge to Auto Refreshif ($time - RP_chk < tRP) begin$display ("at time %t ERROR: tRP violation during Auto Refresh", $time);end// Precharge to Auto Refreshif (Pc_b0 === 1'b0 || Pc_b1 === 1'b0 || Pc_b2 === 1'b0 || Pc_b3 === 1'b0) begin$display ("at time %t ERROR: All banks must be Precharge before Auto Refresh", $time);end// Record Current tRC timeRC_chk = $time;end// Extended Mode Registerif (Ext_mode_enable === 1'b1) beginif (Pc_b0 === 1'b1 && Pc_b1 === 1'b1 && Pc_b2 === 1'b1 && Pc_b3 === 1'b1) beginif (Addr[0] === 1'b0) beginDll_enable = 1'b1;if (Debug) $display ("at time %t EMR : Enable DLL", $time);end else beginDll_enable = 1'b0;if (Debug) $display ("at time %t EMR : Disable DLL", $time);end// LMR/EMR to LMR/EMRif (MRD_chk < tMRD) begin$display ("at time %t ERROR: tMRD violation during Extended Mode Register", $time);end// Record current tMRD timeMRD_chk = 0;end else begin$display ("at time %t ERROR: all banks must be Precharge before Extended Mode Register", $time); endend// Load Mode Registerif (Mode_reg_enable === 1'b1) begin// Decode DLL, CAS Latency, Burst Type, and Burst Lengthif (Pc_b0 === 1'b1 && Pc_b1 === 1'b1 && Pc_b2 === 1'b1 && Pc_b3 === 1'b1) begin Mode_reg = Addr;if (Debug) begin$display ("at time %t LMR : Load Mode Register", $time);// Operating modeif (Addr [11 : 7] === 5'b00000)$display (" Normal Operation");else if (Addr [11 : 7] === 5'b00010)$display (" Normal Operation / Reset DLL");else$display (" Invalid Operating Mode");// CAS Latencyif (Addr[6 : 4] === 3'b010)$display (" CAS Latency = 2");else if (Addr[6 : 4] === 3'b110)$display (" CAS Latency = 2.5");else if (Addr[6 : 4] === 3'b011)$display (" CAS Latency = 3");else$display (" CAS Latency not supported");// Burst Lengthif (Addr[2 : 0] === 3'b001)$display (" Burst Length = 2");else if (Addr[2 : 0] === 3'b010)$display (" Burst Length = 4");else if (Addr[2 : 0] === 3'b011)$display (" Burst Length = 8");else$display (" Burst Length not supported");// Burst Typeif (Addr[3] === 1'b0)$display (" Burst Type = Sequential");else$display (" Burst Type = Interleaved");endend else begin$display ("at time %t ERROR: all banks must be Precharge before Load Mode Register", $time); end// LMR/EMR to LMR/EMRif (MRD_chk < tMRD) begin$display ("at time %t ERROR: tMRD violation during Load Mode Register", $time);endMRD_chk = 0;end// Active Block (Latch Bank Address and Row Address)if (Active_enable === 1'b1) beginif (Ba === 2'b00 && Pc_b0 === 1'b1) begin{Act_b0, Pc_b0} = 2'b10;B0_row_addr = Addr [addr_bits - 1 : 0];RCD_chk0 = $time;RAS_chk0 = $time;if (Debug) $display ("at time %t ACT : Bank = 0 Row = %d",$time, Addr);// Precharge to Activate Bank 0if ($time - RP_chk0 < tRP) begin$display ("at time %t ERROR: tRP violation during Activate bank 0", $time);endend else if (Ba === 2'b01 && Pc_b1 === 1'b1) begin{Act_b1, Pc_b1} = 2'b10;B1_row_addr = Addr [addr_bits - 1 : 0];RCD_chk1 = $time;RAS_chk1 = $time;if (Debug) $display ("at time %t ACT : Bank = 1 Row = %d",$time, Addr);// Precharge to Activate Bank 1if ($time - RP_chk1 < tRP) begin$display ("at time %t ERROR: tRP violation during Activate bank 1", $time);endend else if (Ba === 2'b10 && Pc_b2 === 1'b1) begin{Act_b2, Pc_b2} = 2'b10;B2_row_addr = Addr [addr_bits - 1 : 0];RCD_chk2 = $time;RAS_chk2 = $time;if (Debug) $display ("at time %t ACT : Bank = 2 Row = %d",$time, Addr);// Precharge to Activate Bank 2if ($time - RP_chk2 < tRP) begin$display ("at time $t ERROR: tRP violation during Activate bank 2", $time);endend else if (Ba === 2'b11 && Pc_b3 === 1'b1) begin{Act_b3, Pc_b3} = 2'b10;B3_row_addr = Addr [addr_bits - 1 : 0];RCD_chk3 = $time;RAS_chk3 = $time;if (Debug) $display ("at time %t ACT : Bank = 3 Row = %d",$time, Addr);// Precharge to Activate Bank 3if ($time - RP_chk3 < tRP) begin$display ("at time $t ERROR: tRP violation during Activate bank 3", $time);endend else if (Ba === 2'b00 && Pc_b0 === 1'b0) begin$display ("at time %t ERROR: Bank 0 is not Precharged.", $time);end else if (Ba === 2'b01 && Pc_b1 === 1'b0) begin$display ("at time %t ERROR: Bank 1 is not Precharged.", $time);end else if (Ba === 2'b10 && Pc_b2 === 1'b0) begin$display ("at time %t ERROR: Bank 2 is not Precharged.", $time);end else if (Ba === 2'b11 && Pc_b3 === 1'b0) begin$display ("at time %t ERROR: Bank 3 is not Precharged.", $time);end// Activate Bank A to Activate Bank Bif ((Previous_bank != Ba) && ($time - RRD_chk < tRRD)) begin$display ("at time %t ERROR: tRRD violation during Activate bank = %0d", $time, Ba); end// AutoRefresh to Activateif ($time - RC_chk < tRC) begin$display ("at time %t ERROR: tRC violation during Activate bank %d", $time, Ba);end// Record variable for checking violationRRD_chk = $time;Previous_bank = Ba;end// Precharge Blockif (Prech_enable === 1'b1) beginif (Addr[10] === 1'b1) begin{Pc_b0, Pc_b1, Pc_b2, Pc_b3} = 4'b1111;{Act_b0, Act_b1, Act_b2, Act_b3} = 4'b0000;RP_chk0 = $time;RP_chk1 = $time;RP_chk2 = $time;RP_chk3 = $time;if (Debug) $display ("at time %t PRE : Bank = ALL",$time);// Activate to Precharge all banksif (($time - RAS_chk0 < tRAS) || ($time - RAS_chk1 < tRAS) ||($time - RAS_chk2 < tRAS) || ($time - RAS_chk3 < tRAS)) begin$display ("at time %t ERROR: tRAS violation during Precharge all bank", $time); end// tWR violation check for Writeif ((WR_chk[0] < tWR) || (WR_chk[1] < tWR) ||(WR_chk[2] < tWR) || (WR_chk[3] < tWR)) begin$display ("at time %t ERROR: tWR violation during Precharge all bank", $time); endend else if (Addr[10] === 1'b0) beginif (Ba === 2'b00) begin{Pc_b0, Act_b0} = 2'b10;RP_chk0 = $time;if (Debug) $display ("at time %t PRE : Bank = 0",$time);// Activate to Precharge Bank 0if ($time - RAS_chk0 < tRAS) begin$display ("at time %t ERROR: tRAS violation during Precharge bank 0", $time); endend else if (Ba === 2'b01) begin{Pc_b1, Act_b1} = 2'b10;RP_chk1 = $time;if (Debug) $display ("at time %t PRE : Bank = 1",$time);// Activate to Precharge Bank 1if ($time - RAS_chk1 < tRAS) begin$display ("at time %t ERROR: tRAS violation during Precharge bank 1", $time); endend else if (Ba === 2'b10) begin{Pc_b2, Act_b2} = 2'b10;RP_chk2 = $time;if (Debug) $display ("at time %t PRE : Bank = 2",$time);// Activate to Precharge Bank 2if ($time - RAS_chk2 < tRAS) begin$display ("at time %t ERROR: tRAS violation during Precharge bank 2", $time); endend else if (Ba === 2'b11) begin{Pc_b3, Act_b3} = 2'b10;RP_chk3 = $time;if (Debug) $display ("at time %t PRE : Bank = 3",$time);// Activate to Precharge Bank 3if ($time - RAS_chk3 < tRAS) begin$display ("at time %t ERROR: tRAS violation during Precharge bank 3", $time);。
普通本科毕业设计题目:基于FPGA的DDR SDRAM控制器的设计摘要随着半导体技术的发展,A/D采样的速率越来越高,相应需要越来越大容量的存储器。
存储器是目前数字系统中的关键部件之一,DDR SDRAM(Double Data Rate SDRAM,双倍数据率同步动态随机存储器)以其大容量、高速率和良好的兼容性以及低成本在计算机、消费类电子、通信等领域得到了相当广泛的应用。
DDR控制器实际上就是用户端与DDR存储器之间进行数据传输的一个桥梁,通过DDR控制器,用户端命令被转化成DDR 存储器所支持的命令格式,从而实现用户端对DDR的访问。
本文对DDR SDRAM及其控制器的结构、接口和时序进行了深入研究与分析,得出一些DDR SDRAM控制器的关键技术特性,然后基于Altera公司Cyclone II系列的FPGA芯片EP2C8Q208C8平台,利用Verilog硬件描述语言设计实现了DDR SDRAM存储控制器。
编写自动生成自加数据的模块,将自加数据写入到SDRAM中,再从SDRAM中读回,从UART 发送出去并在串口调试工具上显示。
【关键词】可编程逻辑门阵列DDR SDRAM 存储控制器通用异步收发器AbstractAlong with the development of semiconductor technology, A/D sampling rate is higher and higher, requiring more capacity of corresponding. Storage of memory is one of the crucial devices in the digital system at present, the DDR (Double Data Rate) SDRAM has many advantages for it's large capacity, high speed and the low cost, it has been used in quite a number of fields, such as the Server, the WorkStation, the Personal computer and the consumer electronics, the communication and other areas. DDR controller actually is a bridge between client and DDR memory for data transmission, through the DDR controller, client command was converted into the DDR memory which support command format, so as to realize the visit of DDR clients.The pivotal technologies of DDR SDRAM and memory controller, such as Structure, Interface and Timing are explored in this article, after a research on the main feature inside the DDR controller, several functional modules of the controller are designed out, and then based on FPGA chip Cyclone II Altera company EP2C8Q208C8 platform series used Verilog hardware description language. Write automatic generation and add data modules, with data from the data written to add SDRAM, and again read back from SDRAM, send it out from UART and display on serial port debugging tools.【Key words】FPGA; DDR SDRAM; Memory Controller; UART目录1 绪论 (2)1.1 DDR SDRAM的现状及发展趋势 (2)1.1.1 DDR内存的现状 (2)1.1.2 DDR内存的发展趋势 (3)1.2 课题研究的意义 (3)1.3 课题研究的要求 (2)1.4 本文的安排 (2)2 DDR SDRAM技术介绍 (4)2.1 DDR SDRAM的分类 (4)2.2 DDR SDRAM的基本概念 (4)2.2.1 DRAM存储原理 (5)2.2.2 DDR SDRAM的逻辑BANK与芯片位宽 (5)2.2.3 DDR SDRAM芯片容量 (5)2.2.4 DDR SDRAM内存刷新 (6)2.3 DDR SDRAM的命令 (6)2.3.1 初始化 (6)2.3.2 DDR SDRAM指令 (7)2.4 DDR SDRAM读写操作时序 (8)2.4.1 读操作时序 (8)2.4.2 写操作时序 (8)3 FPGA和Quartus II简介 (10)3.1 FPGA技术简介 (10)3.1.1 FPGA基本结构 (10)3.1.2 FPGA的基本特点 (10)3.1.3 FPGA芯片的选择 (11)3.2 Quartus Ⅱ简介 (11)3.3 Quartus II的设计流程 (11)4 系统硬件设计 (13)4.1 系统整体框架 (13)4.2 自动累加数据产生模块 (13)4.3 DDR SDRAM控制器模块 (14)4.3.1 DDR SDRAM控制器整体状态分析 (14)4.3.2 DDR SDRAM控制器总体架构 (15)4.3.3 输入/输出FIFO模块 (16)4.3.4 控制接口模块设计 (17)4.3.5 控制接口模块设计 (19)4.3.6 数据通路模块设计 (21)4.4 串口读数据模块 (23)5 系统控制器的功能验证 (26)5.1 系统控制器的功能仿真 (26)5.1.1 系统控制器Testbench设计 (26)5.1.2 系统控制器Testbench总体架构 (26)5.1.3 DDR SDRAM Controller Testbench顶层模块设计 (26)5.1.4 DDR SDRAM Controller Testbench仿真波形 (27)5.2 串口读取数据验证 (28)6 总结 (29)参考文献 (30)致谢 (31)1 绪论1.1 DDR SDRAM的现状及发展趋势1.1.1 DDR内存的现状目前DDR内存市场占有量非常大,尤其是近些年随着市场需求的高速增长使得加入该行业和研究该技术的人员也越来越多,DDR控制技术处于高速发展阶段。
`define SRAM_SIZE 8`timescale 1ns/1ns//FOR SRAM INTERFACE CONTROLmodule SRAM_INTERFACE(in_data,//INPUT DATAout_data,//OUTPUT DATAfiford,//FIFO READ CONTROL LOW VOLTAGEfifowr,//FIFO WRITE CONTROL LOW VOLTAGEnfull,nempty,address,//SENT SRAM ADDRESS BUSsram_data,//SRAM DATA BUSrd,//SRAM READ SINGAL ENABLE LOW VOLTAGEwr,//SRAM WRITE ENABLE LOW VOLTAGEclk,//system clkrst);//global reset singal,low voltageinput fiford,fifowr,clk,rst;input[7:0] in_data;output[7:0] out_data;reg[7:0] in_data_buf,out_data_buf;//input and output buffer output reg nfull,nempty;output rd,wr;inout[7:0] sram_data;output reg [10:0]address;reg[10:0] fifo_wp,fifo_rp;reg[10:0]fifo_wp_next,fifo_rp_next;reg near_full,near_empty;reg[3:0] state;parameter idle=4'b0000,read_ready='b0100,read='b0101,read_over='b0111,write_ready='b1000,write='b1001,write_over='b1011;always@(posedge clk or negedge rst)beginif(!rst)state<=idle;else case(state)idle:beginif(fifowr==0&&nfull)state<=write_ready;else if(fiford==0&&nempty)state<=read_ready;elsestate<=idle;endread_ready:state<=read;read:beginif(fiford==1)state<=read_over;elsestate<=read;endread_over:state<=idle;write_ready:state<=write;write:beginif(fifowr==1)state<=write_over;elsestate<=write;endwrite_over:state<=idle;default:state<=idle;endcaseendassign rd=~state[2];assign wr=(state==write)?fifowr:1'b1;always@(posedge clk)beginif(~fifowr)in_data_buf<=in_data;end//=============================================== ==============always@(state or fiford or fifowr or fifo_wp or fifo_rp)beginif(state[2]||~fiford)address=fifo_rp;else if(state[3]||~fifowr)elseaddress='bz;end//=============================================== ==================assign out_data=(state[2])?sram_data:8'bz;always@(posedge clk)beginif(state==read)out_data_buf<=sram_data;end//=============================================== ===always@(posedge clk or negedge rst)beginif(!rst)fifo_rp<=0;else if(state==read_over)fifo_rp<=fifo_rp_next;end//=============================================== ====always@(fifo_rp)beginif(fifo_rp==`SRAM_SIZE-1)fifo_rp_next=0;elsefifo_rp_next=fifo_rp+1;end//=============================================== ======always@(posedge clk or negedge rst)beginif(!rst)fifo_wp<=0;else if(state==write_over)fifo_wp<=fifo_wp_next;end//=============================================== ===always@(fifo_wp)beginif(fifo_wp==`SRAM_SIZE-1)elsefifo_wp_next=fifo_wp+1;end//=============================================== ====always@(posedge clk or negedge rst)beginif(!rst)near_empty<=1'b0;else if(fifo_wp==fifo_rp_next)near_empty<=1'b1;elsenear_empty<=1'b0;end//=============================================== ========always@(posedge clk or negedge rst)beginif(!rst)nempty<=1'b0;else if(near_empty&&state==read)nempty<=1'b0;else if(state==write)nempty<=1'b1;end//=============================================== =======always@(posedge clk or negedge rst)beginif(!rst)near_full<=1'b0;else if(fifo_rp==fifo_wp_next)near_full<=1'b1;elsenear_full<=1'b0;end//=============================================== =====always@(posedge clk or negedge rst)beginif(!rst)nfull<=1'b1;else if(near_full&&state==write)nfull<=1'b0;else if(state==read)nfull<=1'b1;end//=============================================== ============endmodule。
FPGA驱动SDRAM------------verilog语言之前已经对初始化进行了说明,网上看了资料不少,但是很多挺浪费时间的,希望我写这篇能为大家节省点时间,下面对于总体的控制做一下总结吧,直接放状态机不便以后回顾还是写吧,时序整体如下:初始化完成后(初始化时序见初始化篇);等待信号---自刷新信号、读写信号;1.如果写信号到来:行地址&行有效指令;tRCD最小20ns,具体看手册;列地址&列有效指令、写指令;等待burst长度;tDAL等待预刷新及后续时间4clocks;以上过程完成一次写操作。
2.如果读信号到来:行地址&行有效指令;tRCD最小20ns,具体看手册;列地址&列有效指令、读指令;tCL潜伏期2clocks;等待burst长度;tDAL等待预刷新及后续时间4clocks;以上过程完成一次写操作。
3.如果自刷新信号:优先级最高,同时发生时只进行自刷新命令,其后续等待时间tRFC。
以下是几部分的verilog代码1.自刷新因为SDRAM是动态存储器,内部是电容构成(可能是,有点记不清了),所以需要在一段时间就对其刷新。
每行最大的刷新间隔是64ms,而此SDRAM共有4096行,所以每隔15us(64ms/4096)就需要发出刷新命令.就是定时产生高电平。
module sdram_auto_refresh(clk,rst_n,init_done,auto_refresh);input clk;input rst_n;input init_done;output auto_refresh;reg[10:0]cnt_clk;reg auto_refresh;always@(posedge clk or negedge rst_n)beginif(!rst_n)begincnt_clk<=11'd0;auto_refresh<=1'b0;endelse if(cnt_clk==11'd1500&&init_done)beginauto_refresh<=1'b1;cnt_clk<=11'd0;endelsebegincnt_clk<=cnt_clk+11'd1;auto_refresh<=1'b0;endendendmodule2.读写时序控制。
module sdr_test(clk,rst_n,sdram_clk,sdram_cke,sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n,sdram_ba,sdram_addr,sdram_data,//sdram_udqm,sdram_ldqmrs232_tx,/* sdram_rd_req,sdram_wr_ack,sdram_rd_ack,sys_data_out,sdram_busy,sys_data_in,sys_dout_rdy,*/ rdf_dout/*,rdf_rdreq*/);input clk; //系统时钟,100MHzinput rst_n; //复位信号,低电平有效// FPGA与SDRAM硬件接口output sdram_clk; // SDRAM时钟信号output sdram_cke; // SDRAM时钟有效信号output sdram_cs_n; // SDRAM片选信号output sdram_ras_n; // SDRAM行地址选通脉冲output sdram_cas_n; // SDRAM列地址选通脉冲output sdram_we_n; // SDRAM写允许位output[1:0] sdram_ba; // SDRAM的L-Bank地址线output[11:0] sdram_addr; // SDRAM地址总线//output sdram_udqm; // SDRAM高字节屏蔽//output sdram_ldqm; // SDRAM低字节屏蔽inout[15:0] sdram_data; // SDRAM数据总线output rs232_tx; //RS232发送数据信号////////////////////////////////////////////////// SDRAM的封装接口测试引出/*output sdram_rd_req; //系统读SDRAM请求信号output sdram_wr_ack; //系统写SDRAM响应信号output sdram_rd_ack; //系统读SDRAM响应信号output[15:0] sys_data_in; //写SDRAM时数据暂存器,4个突发读写字数据,默认为00地址bit15-0;01地址bit31-16;10地址bit47-32;11地址bit63-48output[15:0] sys_data_out; //读SDRAM时数据暂存器,(格式同上)output sdram_busy; // SDRAM忙标志,高表示SDRAM处于工作中output sys_dout_rdy; // SDRAM数据输出完成标志*/output[15:0] rdf_dout; //sdram数据读出缓存FIFO输出数据总线//output rdf_rdreq; //sdram数据读出缓存FIFO数据输出请求,高有效////////////////////////////////////////////////// SDRAM的封装接口wire sdram_wr_req; //系统写SDRAM请求信号wire sdram_rd_req; //系统读SDRAM请求信号wire sdram_wr_ack; //系统写SDRAM响应信号,作为wrFIFO的输出有效信号wire sdram_rd_ack; //系统读SDRAM响应信号,作为rdFIFO的输写有效信号wire[21:0] sys_addr; //读写SDRAM时地址暂存器,(bit21-20)L-Bank地址:(bit19-8)为行地址,(bit7-0)为列地址wire[15:0] sys_data_in; //写SDRAM时数据暂存器wire[15:0] sys_data_out; //sdram数据读出缓存FIFO输入数据总线wire sdram_busy; // SDRAM忙标志,高表示SDRAM处于工作中wire sys_dout_rdy; // SDRAM数据输出完成标志//wrFIFO输入控制接口wire[15:0] wrf_din; //sdram数据写入缓存FIFO输入数据总线wire wrf_wrreq; //sdram数据写入缓存FIFO数据输入请求,高有效//rdFIFO输出控制接口wire[15:0] rdf_dout; //sdram数据读出缓存FIFO输出数据总线wire rdf_rdreq; //sdram数据读出缓存FIFO数据输出请求,高有效//系统控制相关信号接口wire clk_25m; //PLL输出25MHz时钟wire clk_100m; //PLL输出100MHz时钟wire sys_rst_n; //系统复位信号,低有效//------------------------------------------------//例化系统复位信号和PLL控制模块sys_ctrl uut_sysctrl(.clk(clk),.rst_n(rst_n),.sys_rst_n(sys_rst_n),.clk_25m(clk_25m),.clk_100m(clk_100m),.sdram_clk(sdram_clk));//------------------------------------------------//例化SDRAM封装控制模块sdram_top uut_sdramtop( // SDRAM.clk(clk_100m),.rst_n(sys_rst_n),.sdram_wr_req(sdram_wr_req),.sdram_rd_req(sdram_rd_req),.sdram_wr_ack(sdram_wr_ack),.sdram_rd_ack(sdram_rd_ack),.sys_addr(sys_addr),.sys_data_in(sys_data_in),.sys_data_out(sys_data_out),.sys_dout_rdy(sys_dout_rdy),//.sdram_clk(sdram_clk),.sdram_busy(sdram_busy),.sdram_cke(sdram_cke),.sdram_cs_n(sdram_cs_n),.sdram_ras_n(sdram_ras_n),.sdram_cas_n(sdram_cas_n),.sdram_we_n(sdram_we_n),.sdram_ba(sdram_ba),.sdram_addr(sdram_addr),.sdram_data(sdram_data)// .sdram_udqm(sdram_udqm),// .sdram_ldqm(sdram_ldqm));//------------------------------------------------//读写SDRAM数据缓存FIFO模块例化sdfifo_ctrl uut_sdffifoctrl(.clk_25m(clk_25m),.clk_100m(clk_100m),.wrf_din(wrf_din),.wrf_wrreq(wrf_wrreq),.sdram_wr_ack(sdram_wr_ack),//.sys_addr(sys_addr),.sys_data_in(sys_data_in),.sdram_wr_req(sdram_wr_req),.sys_data_out(sys_data_out),.rdf_rdreq(rdf_rdreq),.sdram_rd_ack(sdram_rd_ack),.rdf_dout(rdf_dout),.sdram_rd_req(sdram_rd_req),.syswr_done(syswr_done),.tx_start(tx_start));//------------------------------------------------//例化模拟写入数据到sdram模块wire syswr_done; //所有数据写入sdram完成标志位datagene uut_datagene(.clk(clk_25m),.rst_n(sys_rst_n),.wrf_din(wrf_din),.wrf_wrreq(wrf_wrreq),.moni_addr(sys_addr),.syswr_done(syswr_done),.sdram_rd_ack(sdram_rd_ack));//------------------------------------------------//例化串口数据发送控制模块wire tx_start; //串口发送数据启动标志位,高有效uart_ctrl uut_uartctrl(.clk(clk_25m),.rst_n(sys_rst_n),.tx_data(rdf_dout[7:0]),.tx_start(tx_start), ///////////.fifo232_rdreq(rdf_rdreq),.rs232_tx(rs232_tx));Endmodulemodule datagene(clk,rst_n,wrf_din,wrf_wrreq,moni_addr,syswr_done,sdram_rd_ack);input clk; //FPAG输入时钟信号25MHzinput rst_n; //FPGA输入复位信号//wrFIFO输入控制接口output[15:0] wrf_din; //sdram数据写入缓存FIFO输入数据总线output wrf_wrreq; //sdram数据写入缓存FIFO数据输入请求,高有效output[21:0] moni_addr; //sdram读写地址产生output syswr_done; //所有数据写入sdram完成标志位input sdram_rd_ack; //系统读SDRAM响应信号,作为rdFIFO的输写有效信号,这里捕获它的下降沿作为读地址自增加标志位reg sdr_rdackr1,sdr_rdackr2;//------------------------------------------//捕获sdram_rd_ack下降沿标志位always @(posedge clk or negedge rst_n)if(!rst_n) beginsdr_rdackr1 <= 1'b0;sdr_rdackr2 <= 1'b0;endelse beginsdr_rdackr1 <= sdram_rd_ack;sdr_rdackr2 <= sdr_rdackr1;endwire neg_rdack = ~sdr_rdackr1 & sdr_rdackr2;//------------------------------------------//上电500us延时等待sdram就绪reg[13:0] delay; //500us延时计数器always @(posedge clk or negedge rst_n)if(!rst_n) delay <= 14'd0;else if(delay < 14'd12500) delay <= delay+1'b1;wire delay_done = (delay == 14'd12500); //1ms延时结束//------------------------------------------//每640ns写入8个16bit数据到sdram,//上电后所有地址写入完毕时间需要不到360ms时间reg[5:0] cntwr; //写sdram定时计数器always @(posedge clk or negedge rst_n)if(!rst_n) cntwr <= 6'd0;else if(delay_done) cntwr <= cntwr+1'b1;//------------------------------------------//读写sdram地址产生reg[18:0] addr; //sdram地址寄存器always @(posedge clk or negedge rst_n)if(!rst_n) addr <= 19'd0;else if(!wr_done && cntwr == 6'h3f) addr <= addr+1'b1;//写地址产生else if(wr_done && neg_rdack) addr <= addr+1'b1; //读地址产生////////////testassign moni_addr = {addr,3'b000};reg wr_done; //所有数据写入sdram完成标志位always @(posedge clk or negedge rst_n)if(!rst_n) wr_done <= 1'b0;else if(addr == 19'h7ffff) wr_done <= 1'b1;assign syswr_done = wr_done;//------------------------------------------//写sdram请求信号产生,即wrfifo的写入有效信号reg wrf_wrreqr; //wrfifo的写入有效信号reg[15:0] wrf_dinr; //wrfifo的写入数据always @(posedge clk or negedge rst_n)if(!rst_n) wrf_wrreqr <= 1'b0;else if(!wr_done) begin //上电0.5ms延时完成if(cntwr == 6'h05) wrf_wrreqr <= 1'b1; //写请求信号产生else if(cntwr == 6'h0d) wrf_wrreqr <= 1'b0; //请求信号撤销endalways @(posedge clk or negedge rst_n)if(!rst_n) wrf_dinr <= 16'd0;else if(!wr_done && ((cntwr > 6'h05) && (cntwr <= 6'h0d))) begin //上电0.5ms延时完成wrf_dinr <= wrf_dinr+1'b1; //写入数据递增endassign wrf_wrreq = wrf_wrreqr;assign wrf_din = wrf_dinr;endmodulemodule sdram_ctrl(clk,rst_n,/*sdram_udqm,sdram_ldqm,*/sdram_wr_req,sdram_rd_req,sdram_wr_ack,sdram_rd_ack,sdram_busy,sys_dout_rdy,init_state,work_state,cnt_clk);//系统信号接口input clk; //系统时钟,50MHzinput rst_n; //复位信号,低电平有效// SDRAM硬件接口//output sdram_udqm; // SDRAM高字节屏蔽//output sdram_ldqm; // SDRAM低字节屏蔽// SDRAM封装接口input sdram_wr_req; //系统写SDRAM请求信号input sdram_rd_req; //系统读SDRAM请求信号output sdram_wr_ack; //系统写SDRAM响应信号,作为wrFIFO的输出有效信号output sdram_rd_ack; //系统读SDRAM响应信号//output sdram_ref_w; // SDRAM自刷新请求信号output sdram_busy; // SDRAM忙标志位,高表示忙output sys_dout_rdy; // SDRAM数据输出完成标志// SDRAM内部接口output[4:0] init_state; // SDRAM初始化寄存器output[3:0] work_state; // SDRAM工作状态寄存器output[8:0] cnt_clk; //时钟计数wire done_200us; //上电后200us输入稳定期结束标志位wire sdram_init_done; // SDRAM初始化完成标志,高表示完成wire sdram_busy; // SDRAM忙标志,高表示SDRAM处于工作中reg sdram_ref_req; // SDRAM自刷新请求信号wire sdram_ref_ack; // SDRAM自刷新请求应答信号`include "sdr_para.v" // 包含SDRAM参数定义模块// SDRAM时序延时参数parameter TRP_CLK = 9'd4,//1, //TRP=18ns预充电有效周期TRFC_CLK = 9'd6,//3, //TRC=60ns自动预刷新周期TMRD_CLK = 9'd6,//2, //模式寄存器设置等待时钟周期TRCD_CLK = 9'd2,//1, //TRCD=18ns行选通周期TCL_CLK = 9'd3, //潜伏期TCL_CLK=3个CLK,在初始化模式寄存器中可设置TREAD_CLK = 9'd8, //突发读数据周期256CLKTWRITE_CLK = 9'd8, //突发写数据256CLKTDAL_CLK = 9'd3; //写入等待//------------------------------------------------------------------------------//assign sdram_udqm = 1'b0; // SDRAM数据高字节有效//assign sdram_ldqm = 1'b0; // SDRAM数据低字节有效//------------------------------------------------------------------------------//上电后200us计时,计时时间到,则done_200us=1//------------------------------------------------------------------------------reg[14:0] cnt_200us;always @ (posedge clk or negedge rst_n)if(!rst_n) cnt_200us <= 15'd0;else if(cnt_200us < 15'd20_000) cnt_200us <= cnt_200us+1'b1; //计数assign done_200us = (cnt_200us == 15'd20_000); //条件满足则done_200us=1//------------------------------------------------------------------------------//SDRAM的初始化操作状态机//------------------------------------------------------------------------------reg[4:0] init_state_r; // SDRAM初始化状态always @ (posedge clk or negedge rst_n)if(!rst_n) init_state_r <= `I_NOP;elsecase (init_state_r)`I_NOP: i nit_state_r <= done_200us ? `I_PRE:`I_NOP; //上电复位后200us结束则进入下一状态`I_PRE: init_state_r <= (TRP_CLK == 0) ? `I_AR1:`I_TRP; //预充电状态`I_TRP: init_state_r <= (`end_trp) ? `I_AR1:`I_TRP; //预充电等待TRP_CLK个时钟周期`I_AR1: init_state_r <= (TRFC_CLK == 0) ? `I_AR2:`I_TRF1; //第1次自刷新`I_TRF1: init_state_r <= (`end_trfc) ? `I_AR2:`I_TRF1; //等待第1次自刷新结束,TRFC_CLK个时钟周期`I_AR2: init_state_r <= (TRFC_CLK == 0) ? `I_AR3:`I_TRF2; //第2次自刷新`I_TRF2: init_state_r <= (`end_trfc) ? `I_AR3:`I_TRF2; //等待第2次自刷新结束,TRFC_CLK个时钟周期`I_AR3: init_state_r <= (TRFC_CLK == 0) ? `I_AR4:`I_TRF3; //第3次自刷新`I_TRF3: init_state_r <= (`end_trfc) ? `I_AR4:`I_TRF3; //等待第3次自刷新结束,TRFC_CLK个时钟周期`I_AR4: init_state_r <= (TRFC_CLK == 0) ? `I_AR5:`I_TRF4; //第4次自刷新`I_TRF4: init_state_r <= (`end_trfc) ? `I_AR5:`I_TRF4; //等待第4次自刷新结束,TRFC_CLK个时钟周期`I_AR5: init_state_r <= (TRFC_CLK == 0) ? `I_AR6:`I_TRF5; //第5次自刷新`I_TRF5: init_state_r <= (`end_trfc) ? `I_AR6:`I_TRF5; //等待第5次自刷新结束,TRFC_CLK个时钟周期`I_AR6: init_state_r <= (TRFC_CLK == 0) ? `I_AR7:`I_TRF6; //第6次自刷新`I_TRF6: init_state_r <= (`end_trfc) ? `I_AR7:`I_TRF6; //等待第6次自刷新结束,TRFC_CLK个时钟周期`I_AR7: init_state_r <= (TRFC_CLK == 0) ? `I_AR8:`I_TRF7; //第7次自刷新`I_TRF7: init_state_r <= (`end_trfc) ? `I_AR8:`I_TRF7; //等待第7次自刷新结束,TRFC_CLK个时钟周期`I_AR8: init_state_r <= (TRFC_CLK == 0) ? `I_MRS:`I_TRF8; //第8次自刷新`I_TRF8: init_state_r <= (`end_trfc) ? `I_MRS:`I_TRF8; //等待第8次自刷新结束,TRFC_CLK个时钟周期`I_MRS: init_state_r <= (TMRD_CLK == 0) ? `I_DONE:`I_TMRD;//模式寄存器设置(MRS)`I_TMRD: init_state_r <= (`end_tmrd) ? `I_DONE:`I_TMRD; //等待模式寄存器设置完成,TMRD_CLK个时钟周期`I_DONE: init_state_r <= `I_DONE; // SDRAM的初始化设置完成标志default: init_state_r <= `I_NOP;endcaseassign init_state = init_state_r;assign sdram_init_done = (init_state_r == `I_DONE); // SDRAM初始化完成标志//------------------------------------------------------------------------------//15us计时,每60ms全部4096行存储区进行一次自刷新// ( 存储体中电容的数据有效保存期上限是64ms )//------------------------------------------------------------------------------reg[10:0] cnt_15us; //计数寄存器always @ (posedge clk or negedge rst_n)if(!rst_n) cnt_15us <= 11'd0;else if(cnt_15us < 11'd1499) cnt_15us <= cnt_15us+1'b1; // 60ms(64ms)/4096=15us循环计数else cnt_15us <= 11'd0;always @ (posedge clk or negedge rst_n)if(!rst_n) sdram_ref_req <= 1'b0;else if(cnt_15us == 11'd1498) sdram_ref_req <= 1'b1; //产生自刷新请求else if(sdram_ref_ack) sdram_ref_req <= 1'b0; //已响应自刷新//------------------------------------------------------------------------------//SDRAM的读写以及自刷新操作状态机//------------------------------------------------------------------------------reg[3:0] work_state_r; // SDRAM读写状态reg sys_r_wn; // SDRAM读/写控制信号always @ (posedge clk or negedge rst_n) beginif(!rst_n) work_state_r <= `W_IDLE;elsecase (work_state_r)`W_IDLE: if(sdram_ref_req & sdram_init_done) beginwork_state_r <= `W_AR; //定时自刷新请求sys_r_wn <= 1'b1;endelse if(sdram_wr_req & sdram_init_done) beginwork_state_r <= `W_ACTIVE;//写SDRAMsys_r_wn <= 1'b0;endelse if(sdram_rd_req && sdram_init_done) beginwork_state_r <= `W_ACTIVE;//读SDRAMsys_r_wn <= 1'b1;endelse beginwork_state_r <= `W_IDLE;sys_r_wn <= 1'b1;end//行有效状态`W_ACTIVE: if(TRCD_CLK == 0)if(sys_r_wn) work_state_r <= `W_READ;else work_state_r <= `W_WRITE;else work_state_r <= `W_TRCD;`W_TRCD: if(`end_trcd)if(sys_r_wn) work_state_r <= `W_READ;else work_state_r <= `W_WRITE;else work_state_r <= `W_TRCD;// SDRAM读数据状态`W_READ: work_state_r <= `W_CL;`W_CL: work_state_r <= (`end_tcl) ? `W_RD:`W_CL;`W_RD: work_state_r <= (`end_tread) ? `W_RW AIT:`W_RD; //后面需要添加一个读完成后的预充电等待状态`W_RWAIT: work_state_r <= (`end_trwait) ? `W_IDLE:`W_RWAIT;// SDRAM写数据状态`W_WRITE: work_state_r <= `W_WD;`W_WD: work_state_r <= (`end_twrite) ? `W_TDAL:`W_WD;`W_TDAL: work_state_r <= (`end_tdal) ? `W_IDLE:`W_TDAL;// SDRAM自动刷新状态`W_AR: work_state_r <= (TRFC_CLK == 0) ? `W_IDLE:`W_TRFC;`W_TRFC: work_state_r <= (`end_trfc) ? `W_IDLE:`W_TRFC;default: work_state_r <= `W_IDLE;endcaseendassign work_state = work_state_r; // SDRAM工作状态寄存器assign sdram_busy = (sdram_init_done && work_state_r == `W_IDLE) ? 1'b0:1'b1; // SDRAM忙标志位assign sdram_ref_ack = (work_state_r == `W_AR); // SDRAM自刷新应答信号assign sdram_wr_ack = ((work_state == `W_TRCD) & ~sys_r_wn) | (work_state == `W_WRITE)| ((work_state == `W_WD) & (cnt_clk_r < 9'd6)); //写SDRAM 响应信号,作为wrFIFO的输出有效信号assign sdram_rd_ack = (work_state_r == `W_RD) & (cnt_clk_r > 9'd1) & (cnt_clk_r < 9'd10);//读SDRAM响应信号assign sys_dout_rdy = (work_state_r == `W_RD && `end_tread); // SDRAM数据输出完成标志//------------------------------------------------------------------------------//产生SDRAM时序操作的延时//------------------------------------------------------------------------------reg[8:0] cnt_clk_r; //时钟计数reg cnt_rst_n; //时钟计数复位信号always @ (posedge clk or negedge rst_n)if(!rst_n) cnt_clk_r <= 9'd0; //计数寄存器复位else if(!cnt_rst_n) cnt_clk_r <= 9'd0; //计数寄存器清零else cnt_clk_r <= cnt_clk_r+1'b1; //启动计数延时assign cnt_clk = cnt_clk_r; //计数寄存器引出,内部`define中使用//计数器控制逻辑always @ (init_state_r or work_state_r or cnt_clk_r) begincase (init_state_r)`I_NOP: cnt_rst_n <= 1'b0;`I_PRE: cnt_rst_n <= (TRP_CLK != 0);//预充电延时计数启动`I_TRP: cnt_rst_n <= (`end_trp) ? 1'b0:1'b1; //等待预充电延时计数结束后,清零计数器`I_AR1,`I_AR2,`I_AR3,`I_AR4,`I_AR5,`I_AR6,`I_AR7,`I_AR8:cnt_rst_n <= (TRFC_CLK != 0); //自刷新延时计数启动`I_TRF1,`I_TRF2,`I_TRF3,`I_TRF4,`I_TRF5,`I_TRF6,`I_TRF7,`I_TRF8:cnt_rst_n <= (`end_trfc) ? 1'b0:1'b1; //等待自刷新延时计数结束后,清零计数器`I_MRS: cnt_rst_n <= (TMRD_CLK != 0); //模式寄存器设置延时计数启动`I_TMRD: cnt_rst_n <= (`end_tmrd) ? 1'b0:1'b1; //等待自刷新延时计数结束后,清零计数器`I_DONE:case (work_state_r)`W_IDLE: cnt_rst_n <= 1'b0;`W_ACTIVE: cnt_rst_n <= (TRCD_CLK == 0) ? 1'b0:1'b1;`W_TRCD: cnt_rst_n <= (`end_trcd) ? 1'b0:1'b1;`W_CL: cnt_rst_n <= (`end_tcl) ? 1'b0:1'b1;`W_RD: cnt_rst_n <= (`end_tread) ? 1'b0:1'b1;`W_RWAIT: cnt_rst_n <= (`end_trwait) ? 1'b0:1'b1;`W_WD: cnt_rst_n <= (`end_twrite) ? 1'b0:1'b1;`W_TDAL: cnt_rst_n <= (`end_tdal) ? 1'b0:1'b1;`W_TRFC: cnt_rst_n <= (`end_trfc) ? 1'b0:1'b1;default: cnt_rst_n <= 1'b0;endcasedefault: cnt_rst_n <= 1'b0;endcaseendendmodulemodule sdram_cmd(clk,rst_n,sdram_cke,sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n,sdram_ba,sdram_addr,sys_addr,init_state,work_state);//系统信号input clk; //50MHzinput rst_n; //低电平复位信号// SDRAM硬件接口output sdram_cke; // SDRAM时钟有效信号output sdram_cs_n; // SDRAM片选信号output sdram_ras_n; // SDRAM行地址选通脉冲output sdram_cas_n; // SDRAM列地址选通脉冲output sdram_we_n; // SDRAM写允许位output[1:0] sdram_ba; // SDRAM的L-Bank地址线output[11:0] sdram_addr; // SDRAM地址总线// SDRAM封装接口input[21:0] sys_addr; // 读写SDRAM时地址暂存器,(bit21-20)L-Bank地址:(bit19-8)为行地址,(bit7-0)为列地址// SDRAM内部接口input[4:0] init_state; // SDRAM初始化状态寄存器input[3:0] work_state; // SDRAM读写状态寄存器`include "sdr_para.v" // 包含SDRAM参数定义模块//-------------------------------------------------------------------------------//-------------------------------------------------------------------------------reg[4:0] sdram_cmd_r; // SDRAM操作命令reg[1:0] sdram_ba_r;reg[11:0] sdram_addr_r;assign {sdram_cke,sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} = sdram_cmd_r; assign sdram_ba = sdram_ba_r;assign sdram_addr = sdram_addr_r;//-------------------------------------------------------------------------------//SDRAM命令参数赋值always @ (posedge clk or negedge rst_n) beginif(!rst_n) beginsdram_cmd_r <= `CMD_INIT;sdram_ba_r <= 2'b11;sdram_addr_r <= 12'hfff;endelsecase (init_state)`I_NOP,`I_TRP,`I_TRF1,`I_TRF2,`I_TRF3,`I_TRF4,`I_TRF5,`I_TRF6,`I_TRF7,`I_TRF8,`I _TMRD: beginsdram_cmd_r <= `CMD_NOP;sdram_ba_r <= 2'b11;sdram_addr_r <= 12'hfff;end`I_PRE: beginsdram_cmd_r <= `CMD_PRGE;sdram_ba_r <= 2'b11;sdram_addr_r <= 12'hfff;end`I_AR1,`I_AR2,`I_AR3,`I_AR4,`I_AR5,`I_AR6,`I_AR7,`I_AR8: beginsdram_cmd_r <= `CMD_A_REF;sdram_ba_r <= 2'b11;sdram_addr_r <= 12'hfff;end`I_MRS: begin //模式寄存器设置,可根据实际需要进行设置sdram_cmd_r <= `CMD_LMR;sdram_ba_r <= 2'b00; //操作模式设置sdram_addr_r <= {2'b00, //操作模式设置1'b0, //操作模式设置(这里设置为A9=0,即突发读/突发写)2'b00, //操作模式设置({A8,A7}=00),当前操作为模式寄存器设置3'b011, // CAS潜伏期设置(这里设置为3,{A6,A5,A4}=011)1'b0, //突发传输方式(这里设置为顺序,A3=b0)3'b011 //突发长度(这里设置为8,{A2,A1,A0}=011)};end`I_DONE:case (work_state)`W_IDLE,`W_TRCD,`W_CL,`W_TRFC,`W_RD,`W_WD,`W_TDAL: beginsdram_cmd_r <= `CMD_NOP;sdram_ba_r <= 2'b11;sdram_addr_r <= 12'hfff;end`W_ACTIVE: beginsdram_cmd_r <= `CMD_ACTIVE;sdram_ba_r <= sys_addr[21:20]; //L-Bank地址sdram_addr_r <= sys_addr[19:8]; //行地址end`W_READ: beginsdram_cmd_r <= `CMD_READ;sdram_ba_r <= sys_addr[21:20]; //L-Bank地址sdram_addr_r <= {4'b0100, // A10=1,设置写完成允许预充电sys_addr[7:0] //列地址};end`W_WRITE: beginsdram_cmd_r <= `CMD_WRITE;sdram_ba_r <= sys_addr[21:20]; //L-Bank地址sdram_addr_r <= {4'b0100, // A10=1,设置写完成允许预充电sys_addr[7:0] //列地址};end`W_AR: beginsdram_cmd_r <= `CMD_A_REF;sdram_ba_r <= 2'b11;sdram_addr_r <= 12'hfff;enddefault: beginsdram_cmd_r <= `CMD_NOP;sdram_ba_r <= 2'b11;sdram_addr_r <= 12'hfff;endendcasedefault: beginsdram_cmd_r <= `CMD_NOP;sdram_ba_r <= 2'b11;sdram_addr_r <= 12'hfff;endendcaseendendmodulemodule sdram_wr_data(clk,rst_n,/*sdram_clk,*/sdram_data,sys_data_in,sys_data_out,work_state,cnt_clk);//系统信号input clk; //系统时钟,100MHzinput rst_n; //复位信号,低电平有效// SDRAM硬件接口//output sdram_clk; // SDRAM时钟信号inout[15:0] sdram_data; // SDRAM数据总线// SDRAM封装接口input[15:0] sys_data_in; //写SDRAM时数据暂存器output[15:0] sys_data_out; //读SDRAM时数据暂存器// SDRAM内部接口input[3:0] work_state; //读写SDRAM时数据状态寄存器input[8:0] cnt_clk; //时钟计数`include "sdr_para.v" // 包含SDRAM参数定义模块//assign sdram_clk = ~clk; // SDRAM时钟信号//------------------------------------------------------------------------------//数据写入控制//------------------------------------------------------------------------------reg[15:0] sdr_din; //突发数据写寄存器reg sdr_dlink; // SDRAM数据总线输入输出控制//将待写入数据送到SDRAM数据总线上always @ (posedge clk or negedge rst_n)if(!rst_n) sdr_din <= 16'd0; //突发数据写寄存器复位else if((work_state == `W_WRITE) | (work_state == `W_WD)) sdr_din <= sys_data_in;//连续写入存储在wrFIFO中的256个16bit数据//产生双向数据线方向控制逻辑always @ (posedge clk or negedge rst_n)if(!rst_n) sdr_dlink <= 1'b0;else if((work_state == `W_WRITE) | (work_state == `W_WD)) sdr_dlink <= 1'b1;else sdr_dlink <= 1'b0;assign sdram_data = sdr_dlink ? sdr_din:16'hzzzz;//------------------------------------------------------------------------------//数据读出控制//------------------------------------------------------------------------------reg[15:0] sdr_dout; //突发数据读寄存器//将数据从SDRAM读出always @ (posedge clk or negedge rst_n)if(!rst_n) sdr_dout <= 16'd0; //突发数据读寄存器复位else if((work_state == `W_RD) & (cnt_clk > 9'd0) & (cnt_clk < 9'd10)) sdr_dout <= sdram_data; //连续读出256B的16bit数据存储到rdFIFO中assign sys_data_out = sdr_dout;//------------------------------------------------------------------------------Endmodulemodule sys_ctrl(clk,rst_n,sys_rst_n,clk_25m,clk_100m,sdram_clk);input clk; //FPAG输入时钟信号25MHzinput rst_n; //FPGA输入复位信号output sys_rst_n; //系统复位信号,低有效output clk_25m; //PLL输出25MHz时钟output clk_100m; //PLL输出100MHz时钟output sdram_clk; //用于外部SDAM的时钟100Mwire locked; //PLL输出有效标志位,高表示PLL输出有效//----------------------------------------------//PLL复位信号产生,高有效//异步复位,同步释放wire pll_rst; //PLL复位信号,高有效reg rst_r1,rst_r2;always @(posedge clk or negedge rst_n)if(!rst_n) rst_r1 <= 1'b1;else rst_r1 <= 1'b0;always @(posedge clk or negedge rst_n)if(!rst_n) rst_r2 <= 1'b1;else rst_r2 <= rst_r1;assign pll_rst = rst_r2;//----------------------------------------------//系统复位信号产生,低有效//异步复位,同步释放wire sys_rst_n; //系统复位信号,低有效wire sysrst_nr0;reg sysrst_nr1,sysrst_nr2;assign sysrst_nr0 = rst_n & locked; //系统复位直到PLL有效输出always @(posedge clk_100m or negedge sysrst_nr0)if(!sysrst_nr0) sysrst_nr1 <= 1'b0;else sysrst_nr1 <= 1'b1;always @(posedge clk_100m or negedge sysrst_nr0)if(!sysrst_nr0) sysrst_nr2 <= 1'b0;else sysrst_nr2 <= sysrst_nr1;assign sys_rst_n = sysrst_nr2;//----------------------------------------------//例化PLL产生模块PLL_ctrl uut_PLL_ctrl(.areset(pll_rst), //PLL复位信号,高电平复位.inclk0(clk), //PLL输入时钟,25MHz.c0(clk_25m), //PLL输出25MHz时钟.c1(clk_100m), //PLL输出100MHz时钟.e0(sdram_clk), //用于外部SDAM的时钟100M.locked(locked) //PLL输出有效标志位,高表示PLL输出有效);endmodulemodule uart_ctrl(clk,rst_n,tx_data,tx_start,fifo232_rdreq,rs232_tx);input clk; // 25MHz主时钟input rst_n; //低电平复位信号input[7:0] tx_data; //待发送数据input tx_start; //串口发送数据启动标志位,高有效output fifo232_rdreq; //FIFO读请求信号,高有效output rs232_tx; //RS232发送数据信号//----------------------------------------------------------------//串口发送底层模块和串口波特率选择模块接口wire clk_bps; //发送数据标志位,高有效wire bps_start; //波特率时钟计数器启动信号,高有效//----------------------------------------------------------------//例化串口数据发送底层模块uart_tx uut_tx(.clk(clk),.rst_n(rst_n),.tx_data(tx_data),.tx_start(tx_start),.clk_bps(clk_bps),.rs232_tx(rs232_tx),.bps_start(bps_start),.fifo232_rdreq(fifo232_rdreq));//例化串口数据发送波特率控制模块uart_speed_select uut_ss(.clk(clk),.rst_n(rst_n),.bps_start(bps_start),.clk_bps(clk_bps));Endmodulemodule sdfifo_ctrl(clk_25m,clk_100m,wrf_din,wrf_wrreq,sdram_wr_ack,/*sys_addr,*/sys_data_in,sdram_wr_req,sys_data_out,rdf_rdreq,sdram_rd_ack,rdf_dout,sdram_rd_req,syswr_done,tx_start);input clk_25m; //PLL输出25MHz时钟input clk_100m; //PLL输出100MHz时钟//wrfifoinput[15:0] wrf_din; //sdram数据写入缓存FIFO输入数据总线input wrf_wrreq; //sdram数据写入缓存FIFO数据输入请求,高有效input sdram_wr_ack; //系统写SDRAM响应信号,作为wrFIFO的输出有效信号//output[21:0] sys_addr; //读写SDRAM时地址暂存器,(bit21-20)L-Bank地址:(bit19-8)为行地址,(bit7-0)为列地址output[15:0] sys_data_in; //sdram数据写入缓存FIFO输出数据总线,即写SDRAM时数据暂存器output sdram_wr_req; //系统写SDRAM请求信号//rdfifoinput[15:0] sys_data_out; //sdram数据读出缓存FIFO输入数据总线input rdf_rdreq; //sdram数据读出缓存FIFO数据输出请求,高有效input sdram_rd_ack; //系统读SDRAM响应信号,作为rdFIFO的输写有效信号output[15:0] rdf_dout; //sdram数据读出缓存FIFO输出数据总线output sdram_rd_req; //系统读SDRAM请求信号input syswr_done; //所有数据写入sdram完成标志位output tx_start; //串口发送数据启动标志位,高有效//------------------------------------------------wire[8:0] wrf_use; //sdram数据写入缓存FIFO已用存储空间数量wire[8:0] rdf_use; //sdram数据读出缓存FIFO已用存储空间数量//assign sys_addr = 22'h1a9e21; //测试用assign sdram_wr_req = ((wrf_use >= 9'd8) & ~syswr_done); //FIFO(8个16bit数据)即发出写SDRAM请求信号assign sdram_rd_req = ((rdf_use <= 9'd256) & syswr_done); //sdram写入完成且FIFO半空(256个16bit数据)即发出读SDRAM请求信号assign tx_start = ((rdf_use != 9'd0) & syswr_done); //启动串口发送数据//------------------------------------------------//例化SDRAM写入数据缓存FIFO模块wrfifo uut_wrfifo(.data(wrf_din),.rdclk(clk_100m),.rdreq(sdram_wr_ack),.wrclk(clk_25m),.wrreq(wrf_wrreq),.q(sys_data_in),.wrusedw(wrf_use));//------------------------------------------------//例化SDRAM读出数据缓存FIFO模块rdfifo uut_rdfifo(.data(sys_data_out),.rdclk(clk_25m),.rdreq(rdf_rdreq),.wrclk(clk_100m),.wrreq(/*rdf_wrreq*/sdram_rd_ack),.q(rdf_dout),.wrusedw(rdf_use));endmodule。
2014年第27卷第1期Electronic Sci.&Tech./Jan.15,2014收稿日期:2013-07-06作者简介:张刚(1989—),男,硕士研究生。
研究方向:电子系统设计与仿真。
E-mail :jiachao2007@ 。
贾建超(1988—),男,硕士研究生。
研究方向:高速并行信号处理。
赵龙(1989—),男,硕士研究生。
研究方向:雷达信号处理与仿真。
基于FPGA 的DDR3SDRAM 控制器设计及实现张刚,贾建超,赵龙(西安电子科技大学电子工程学院,陕西西安710071)摘要DDR3SDRAM 是第三代双倍数据传输速率同步动态随机存储器,以其大容量、高速率和良好的兼容性得到了广泛应用。
文中介绍了DDR3的特点和操作原理,以及利用MIG 软件工具在Virtex -6系列FPGA 中实现DDR3SDRAM 控制器的设计方法,并进行硬件测试。
验证了DDS3控制器的可行性,其工作稳定、占用资源少、可植性强等。
关键词FPGA ;DDR3SDRAM 控制器;MIG中图分类号TN79文献标识码A文章编号1007-7820(2014)01-070-04Design and Realization of DDR3SDRAM Controller Based on FPGAZHANG Gang ,JIA Jianchao ,ZHAO Long(School of Electronic Engineering ,Xidian University ,Xi'an 710071,China )AbstractThe DDR3SDRAM is the third-generation double data rate synchronous dynamic random accessmemory ,which has been widely used in many fields because of its large capacity ,high speed and good compatibili-ty.This paper briefly introduces the characteristics and operating principles of DDR3,and the realization of DDR3SDRAM controller in the Virtex-6FPGA series with MIG software tools ,and gives the hardware test results.The feasibility of the controller is verified.It has the advantages of stable operation ,small requirement on resources and good portability.KeywordsFPGA ;DDR3SDRAM controller ;MIGDDR3SDRAM 是从DDR、DDR2发展而来的一种高速同步动态随机访问存储器。
基于FPGA的CMOS摄像机图像采集一、数据采集系统概述数据采集是指将以各种形式输入的被测信号,包括语音信号、温度信号、湿度信号、图像信号等经过适当处理,成为计算机可以识别的数字信号,从而送入计算机进行存储处理的过程,数据采集卡就是典型的基于数据采集系统原理的集成计算机扩展卡。
如图1所示,在数据采集过程中主要有几个关键部分:(1)输入信号的幅度较小或者过大,需要经过放大器单元将输入信号幅度放大或者缩小;(2)输入信号带有较大的噪声,需要经过一个硬件的模拟滤波单元,将信号滤波整形;(3)将信号送到AD进行模数转换;(4)将信号传输到计算机;(5)存储记录和处理数据。
例如在一个具有两个Bank的SDRAM的模组中,其中一个Bank在进行预充电期间,另一个Bank却马上可以被读取,这样当进行一次读取后,又马上去读取已经预充电Bank的数据时,就无需等待而是可以直接读取了,这也就大大提高了存储器的访问速度。
其优点是设计相对简单、不许考虑传输时转换总线的问题、较为可靠,缺点是SDRAM容量有限、传输时序需要计算准确、SDRAM经常刷新等。
根据综合分析和考虑,我们选用相对简单方便的方案2,选择器件如下:FPGA采用Altera 的Cyclone EP2C35F484C8,视频采集芯片用飞利浦的SAA7113作为A/D转换单元,两块型号为K4S641632E的SDRAM和FPGA构成图像帧存储及传输处理系统,ADV7125是数模转换芯片,和计算机VGA显示器相连作为显示终端,系统整体框图如图2所示。
图2 视频监控系统整体框图以上图像视频监视系统的大部分设计工作都集中在对FPGA的编程开发上,通过分析可以确定出FPGA需要包含如下几个功能模块。
(1)视频接口配置模块:视频采集芯片SAA7113具有多种采集方式,这里FPGA通过I²C 总线对其内部寄存器进行配置,使其按照一定的格式进行采样。
(2)异步FIFO模块:当FPGA接收A/D采样的视频数据时,由于SAA7113和FPGA一般在不同的时钟频率下,这就会出现通常所说的异步时钟问题,处理不当就容易出现亚稳态,常用方法是在两者之间添加一块异步FIFO。
Sdram控制器的Verilog的实现⽬前,在很多通信芯⽚及系统的开发中,常常需要⽤到存储容量⼤、读写速度⾼的存储器。
在各种随机存储器件中,SDRAM 的价格低、体积⼩、速度快、容量⼤,是⽐较理想的器件。
但是,与SRAM相⽐较,SDRAM的控制逻辑复杂,使⽤很不⽅便。
为了解决这个⽭盾,需要设计专⽤的SDRAM控制器,使系统⽤户象使⽤SRAM⼀样⽅便的使⽤SDRAM是⼗分必要的。
本⽂介绍了SDRAM控制器的Verilog设计,并给出了实现结果。
⼀、 Sdram简介1、 Sdram的接⼝信号2、 Sdram启动和初始化系统商上电后,Sdram 必须经过初始化才能使⽤,初始化过程必须经过以下⼏个步骤:(1)发出NOP指令,等待1ms(2)执⾏PreChargeAll命令(3)执⾏8次AutoRefresh命令(4)设置模式寄存器(Mode Register)(5)等待Tmrd时钟,Sdram就可以正常读写了。
3、 Sdram的模式寄存器Mode Register ⽤于定义Sdram的运⾏模式。
在PC133规范中,Mode Register中包括了突发长度(Burst Length)、突发类型(Burst Type)和CASs延迟(CAS Latency)。
⽤过Mode Register Set 命令进⾏编程,这组信息将会保存知道Sdram掉电为⽌(具体的Mode Register定义和SDRAM的命令看对应Sdram的数据⼿册)。
⼆、 Sdram的命令解析1、 Bank Active 命令在进⾏任何的Read和Write 命令之前,Sdram⾸先要选择进⾏操作的Bank,并且还要打开这个Bank中相应的⾏,这个通过Bank Active 命令来实现,Bank Active打开BA指定的Bank,同时锁存⾏地址信号。
每个Bank 最长激活时间位 Tras,当Bank Active命令执⾏完毕以后,需要进⾏操作的的Bank中的⾏就会被打开,经过Trcd的延时之后,才可以进⾏Read或Write命令。
基于Xilinx FPGA实现的DDR SDRAM控制器工作过程详解1 引言在高速信号处理系统中,需要缓存高速、大量的数据,存储器的选择与应用已成为系统实现的关键所在。
DDR SDRAM是一种高速CMOS、动态随机访问存储器,它采用双倍数据速率结构来完成高速操作。
SDR SDRAM一个时钟周期只能传输一个数据位宽的数据,因此在相同的数据总线宽度和工作频率下,DDR SDRAM的总线带宽比SDR SDRAM的总线带宽提高了一倍。
Xilinx VirtexTM- 4 FPGA 具备ChipSync 源同步技术等优势。
它的输入输出模块(IOB)提供了封装引脚与内部可配置逻辑之间的接口,无论是输入路径还是输出路径都提供了一个可选的SDR 和DDR 寄存器。
VirtexTM- 4 的IOB 专门针对源同步设计进行了优化,包括每一位的偏移校正、数据的串行化和解串行化、时钟分频以及专用的本地时钟资源等,而且它在每一个I/O 模块中都提供了64- 阶延迟线。
这些特性使得VirtexTM- 4 FPGA 能够更好的实现DDR SDRAM控制器的逻辑设计,准确可靠的捕获数据。
实验板选择专为DSP 应用而优化的Virtex- 4 SX35 作为DDR SDRAM控制器的实现平台,选用Micron MT46V8M16P-75Z DDR SDRAM。
2 DDR SDRAM 控制器工作原理DDR SDRAM控制器的主要功能就是完成对DDR SDRAM的初始化,将DDR SDRAM复杂的读写时序转化为用户简单的读写时序,以及将DDR SDRAM接口的双时钟沿数据转换为用户的单时钟沿数据,使用户像操作普通的RAM一样控制DDR SDRAM; 同时,控制器还要产生周期性的刷新命令来维持DDR SDRAM内的数据而不需要用户的干预。
该控制器的模块化表示如图1。
应用层接口是DDR 控制器与FPGA 用户设计的接口。
对于DDR 控制器的用户来说,只需要了解如何使用应用层接口,通过应用层接口给DDR 控制器发出指令、数据,并且接收数据。
计算机测量与控制!"#"$!$%!%#"!!"#$%&'()'*+%('#',&-!",&(".!!#&'!#收稿日期 "#"$#$#&$!修回日期 "#"$#(%"%作者简介 谢树平!%)*&"&男&硕士&工程师%引用格式 谢树平&毛源豪!基于+,-.的//01/0.2测试平台设计'3(!计算机测量与控制&"#"$&$%!%#")&''4!文章编号 %&'%(4)* "#"$ %###&'#)!!/56 %#!%&4"& 7!89:;!%%<('&" =>!"#"$!%#!#%%!!中图分类号 ?,"'(!!文献标识码 .基于/012的3345342)测试平台设计谢树平 毛源豪!湖南艾科诺维科技有限公司&长沙!(%####"摘要 //01/0.2是+,-.板卡中的重要组成部分&其可靠性与带宽决定了设备能否正常工作$为了测试//01/0.2的性能是否符合预期&开发了一种基于+,-.的//01/0.2测试平台&平台包含一个基于//01/0.2控制器的测试器6,核&具有数据校验*带宽测量的功能$编写了控制测试器6,核的?@A脚本&用于配置测试参数*控制测试流程与读取测试结果$在,B=C D9语言下使用,B E=4开发库设计了图形界面程序&能够根据用户操作生成并执行对应的?@A脚本$最终实现了一个操作简单*测试流程可配置*自动输出测试结果的//01/0.2测试平台$测试结果表明&测试平台能够正确地进行//0 1/0.2测试并输出统计结果$对比26-的示例工程&测试平台额外增加了带宽测试*结果统计*循环测试等功能&且使用的+,-.资源下降了$#F&测试用时缩短了'#F以上%关键词 //01/0.2$+,-.$?@A脚本$测试平台$,B E=43'+67,"83345342)9'+&0.*&8"(#:*+';",/012G6H1C I>;9J&2.5K I L9C L D!M I9L9.8N9D O L?P8C9D Q D J B@D R&A=S R&@C L9J T C L!(%####&@C;9L"2<+&(*=&)//01/0.2;T L9;U>D V=L9=8D U>D9P9=D W+,-.X D L V S T&L9S;=T V P Q;L X;Q;=B L9S X L9S Y;S=C S P=P V U;9PY C P=C P V=C P S P Z O;8P8L9W I98=;D9>V D>P V Q B R?DO P V;W B=C L==C P>P V W D V U L98PD W=C P//01/0.2U P P=TP[>P8=L=;D9T&L//01/0.2=P T=>Q L=W D V U X L T P SD9+,-.;T S P O P Q D>P S R?C P>Q L=W D V U;98D V>D V L=P T L=P T=P V6,8D V P&Y C;8C;T X L T P S D9L//01/0.28D9=V D Q Q P V L9SC L T=C P8L Z >L X;Q;=B=DO P V;W B S L=L L9SU P L T I V PX L9S Y;S=C R?@AT8V;>=T L V PI T P S=D8D9=V D Q=C P=P T=P V6,8D V P&;98Q I S;9J T P==;9J=P T=>L V L U P=P V T& U L9L J;9J=P T=>V D8P T T P T&L9S V P=V;P O;9J=P T=V P T I Q=T R.S S;=;D9L Q Q B&L J V L>C;8L Q;9=P V W L8P>V D J V L U;T S P T;J9P SI T;9J=C P,B E=4S P O P Q D>Z U P9=Q;X V L V B;9,B=C D9&Y C;8C J P9P V L=P T L9SP[P8I=P T8D V V P T>D9S;9J?@AT8V;>=TX L T P SD9I T P V;9>I=R.T L V P T I Q=&L//01/0.2 =P T=;9J>Q L=W D V U;T;U>Q P U P9=P S=C L=;T X D=CI T P V Z W V;P9S Q B L9S W Q P[;X Q P;9=P V U T D W=C P=P T=;9J>V D8P T T&Y C;Q P L Q T D>V D O;S;9J L I=D U L=;8 V P T I Q=T D I=>I=R?P T=V P T I Q=T S P U D9T=V L=P=C L==C P>Q L=W D V UL88I V L=P Q B=P T=T//01/0.2L9SD I=>I=T T=L=;T=;8L Q V P T I Q=T R2D V P D O P V& 8D U>L V P S=D=C P P[L U>Q P S P T;J9D W26-&=C P=P T=;9J>Q L=W D V U;98Q I S P T X L9S Y;S=C=P T=;9J&V P T I Q=T=L=;T=;8T&L9S L I=D U L=;88D9=V D Q W I98Z =;D9T&I Q=;U L=P Q B V P S I8;9J+,-.V P T D I V8PI T L J PX B$#F L9S8I==;9J=P T==;U PX B U D V P=C L9'#F R>'@"(;+)//01/0.2$+,-.$?@AT8V;>=$=P T=>Q L=W D V U$,B E=4A!引言现场可编程逻辑门阵列!+,-.&W;P Q S>V D J V L U U L X Q PJ L=P L V V L B"是一种半定制芯片&因其独特的电路可编程特性区别于其他器件%随着近年+,-.芯片的快速发展&其内部的资源数量与丰富度显著提升'%(%+,-.在通信*图像处理'"(*深度学习'$(*人工智能'((与数据中心'4(等领域发挥着重要的作用%双倍数据传输速率同步动态随机存储器!//01/0.2&S D I X Q P S L=L V L=P T B98C V D9D I TS B9L U;8V L9ZS D UL88P T TU P U D V B"是+,-.板卡中最常用的高速缓存解决方案%//01/0.2的工作情况直接影响到整个设备能否正常运作&所以//01/0.2测试也是+,-.板卡测试中最重要的测试项目之一%此前对//01/0.2的测试主要通过//01/0.2控制器的调试端口进行%然而这种测试方案存在操作人员学习门槛高*测试流程不灵活*无法自动生成测试报告等缺点%操作人员在测试前需要充分了解调试端口中约"##个信号的定义*各控制信号间的逻辑关系以及操作//01/0.2的相关知识%此类方案在生成比特流后测试内容相对固定&可在线配置的测试参数有限&无法设置测试队列并自动完成%且没有生成测试报告的功能&相关数据需要操作人员手动记录%降低了工作效率&增加了出错风险%在+,-.与//01/0.2的数据交互设计中&设计者通常使用+,-.厂家提供的//01/0.2控制器%比如G;Q;9[公司为旗下的+,-.提供了成熟的存储器接口生成器!26-&U P U D V B;9=P V W L8P J P9P V L=D V"%26-内包含控制器和物理层&设计者可以通过用户接口或先进可扩展接口!.G6&L S O L98P S P G=P9T;X Q P;9=P V W L8P"访问//01/0.2%文献'&(提出了一种基于26-用户接口的应用&在26-用户接口的基础上设计了先入先出!+6+5&W;V T=;9W;V T=D I="接口&使其既拥有+6+5缓存简单易用的特点&又有//01/0.2存储空间大的优势%文献''(在数据+6+5!投稿网址 Y Y Y!7T78Q B:\!8D UCopyright©博看网. All Rights Reserved.!!计算机测量与控制!第$%""""""""""""""""""""""""""""""""""""""""""""""""""""卷#&*!#接口的基础上增设了一个命令+地址+6+5&实现了随机读写功能%在//01/0.2控制器的测试技术中&通常使用的方案是向//01/0.2写入特定的>L ==P V 9&然后读取数据并校验数据一致性%文献'*(提出了一种包含内部自测!]61?&X I ;Q =Z ;9T P Q W Z =P T ="模块的//01/0.2控制器%该模块将来自随机数发生器的数据写入//01/0.2中&并将读出的数据与写入的数据在数据比较器中进行对比&从而实现自监测的功能%文献')(提出了一种基于在线逻辑分析仪!6A .&;9=P J V L =P SQ D J ;8L 9L Q B \P V "知识产权!6,&;9=P Q Q P 8=I L Q >V D >P V =B "核验证//01/0.2控制器的方法%使用.G 6?V L W W ;8J P 96,核产生.G 6总线的读写事务&并用6A .抓取.G 6总线上的信号&分析其时序与数据正确性%实际应用中&通常使用标准3?.-接口实现,@上位机与+,-.之间的通信%文献'%#(设计了一种基于+,-.的//01/0.2通用测试电路%该设计使用3?.-接口启动测试电路&电路自动完成整个测试过程并将测试结果从3?.-接口传回,@上位机%文献'%%(提出了一种使用工具命令语言!@A &=D D Q 8D U U L 9S Q L 9J I L J P "脚本语言测试数字电路的方法%该方法通过在^;O L S D 软件中执行?@A 脚本实现自动对调试核虚拟输入输出!^65&O ;V =I L Q ;9>I =D I =>I ="的修改与读取&从而达成高效率的测试%文献'%"(提出了一种基于A L X ^6H _软件调用?@A 脚本的测试方法&将^;O L S D 软件的启动与执行?@A 脚本的命令封装为批处理文件&实现了自动化测试与生成报表%文献'%$(提出了一种+,-.的.G 6总线接口调试方法&通过使用3?.-=D.G 66,核&允许用户通过执行?@A 脚本来对.G 6总线上的从设备进行访问%为了解决当前+,-.板卡中//01/0.2测试工作复杂及效率低下的问题&本设计做了如下工作)%"设计了//01/0.2控制器的测试器6,核26-P T =P V %该6,核具有生成读写事务*校验数据*记录数据读写用时等功能%同时26-?P T =P V 支持对数据位宽*>L =Z =P V 9类型*起始地址*测试地址范围*突发长度等参数的在线配置&具有高度的灵活性%""设计了?@A 脚本%用于控制^65*6A .*3?.-=D .G 6等6,核&从而实现对整个测试流程的控制以及测试结果信息的读取%$"设计了上位机图形界面程序%将测试流程中各个阶段需要执行的@A 脚本封装%通过文本框打印测试信息&同时自动生成测试报告&便于操作人员使用%B !测试平台架构及原理测试平台架构主要由两个部分构成)+,-.板卡与,@上位机%+,-.板卡内包含+,-.与//01/0.2&二者通过板卡上的//01/0.2接口相连接%,@上位机与+,Z -.通过3?.-接口实现通讯%用户在,@上位机操作图形界面程序&完成测试流程与输出测试结果'%(%4(%所述架构如图%所示%图%!测试平台架构框图//01/0.2是待测的目标器件&由+,-.中的26-控制%在对//01/0.2的测试中&重点关注的是//01/0.2的读写正确性与带宽两项性能'%&(%+,-.与//01/0.2通过//01/0.2接口相连接&+,-.内例化的26-控制//01/0.2的初始化与数据读写%26-?P T =P V 可以通过26-的.G 6T Q L O P 接口对//01/0.2进行数据读写%26-?P T =P V 的功能是测试读写正确性与带宽%26-?P T =P V 有两个主要接口)一个是.G 6T Q L O P 接口&作为控制接口与3?.-=D.G 6相连&?@A 脚本控制3?.-=D.G 6来与26-?P T =P V 进行通信&控制测试流程与读回测试结果$另一个是.G 6U L T =P V 接口&作为数据读写接口与26-相连&测试过程中对26-的数据传输均由此接口实现%此外26-?P T =P V 还有一个块随机存取存储器!]0.2&X Q D 8:V L 9S D UL 88P T TU P U D V B "主接口&用于向]0.2写入错误数据对应的地址信息&便于后续对错误数据的溯源分析%+,-.内例化的^65*3?.-=D.G 6和6A .调试核互相配合下起到控制26-初始化*控制26-P T =P V *抓取.G 6总线信号的作用&这些调试核均受,@上位机控制'%'%*(%,@上位机通过3?.-接口与+,-.进行通信%通过在,@上位机的^;O L S D ?8Q 1C P Q Q 程序中执行?@A 脚本&可以对+,-.中调试核的信息读取与控制%图形界面程序将^;O L S D ?8Q 1C P Q Q 作为子进程运行&并将测试相关的?@A 脚本封装为对应的按钮%操作人员可以通过图形界面程序便捷地控制整个测试流程&提高了测试效率&降低了学习门槛'%)"#(%C !/012工程设计测试板卡使用的+,-.产自G ;Q ;9[公司&型号为[8':$"4=W W J)##Z "&使用的//01/0.2型号为2?*3?+"Z 4&&(M `Z %-&2%%C D B !/012工程主要模块工程主要包含3?.-=D.G 6*26-?P T =P V *.G 61U L V =Z!投稿网址 Y Y Y!7T 78Q B:\!8D U Copyright ©博看网. All Rights Reserved.第%#期谢树平&等)基于+,-.的//01/0.2""""""""""""""""""""""""""""""""""""""""""""""""""""测试平台设计#&)!#@D 99P 8=*26-*.G 6]V L U @D 9=V D Q Q P V 等6,%模块之间主要通过.G 6总线进行连接&所有.G 6总线通过.G 61U L V =Z @D 99P 8=互联6,连接在一起%地址空间分配中&26-基地址被设为#[*#######&可被26-?P T =P V 和3?.-=D.G 6访问%26-?P T =P V 基地址设为#[((.#####&.G 6]0.2@D 9=V D Q Q P V 基地址设为#[########&两者都只能被3?.-=D .G 6访问%]0.2的类型为真双口]0.2&其中一个接口受.G 6]0.2@D 9=V D Q Q P V 控制&另一个接口供26-?P T =P V的]0.2主接口写入数据'"%""(%C D C !)'#"(E,&'(8*='1','(*&"(26-是由G ;Q ;9[官方提供的存储器接口成熟的解决方案&是可靠的//01/0.2控制器%26-由一个控制器与//0物理层接口组成%26-将复杂的//0物理接口封装为被广泛使用的.G 6接口&简化了用户的设计%在+,-.工程设计中&26-的.G 6T Q L O P 接口与26-?P T =P V 的.G 6U L T =P V 接口相连接&在测试过程中完成数据传输%26-的复位信号控制着26-初始化的开始&由^65驱动%26-的初始化完成信号是高电平时表示26-完成了初始化&由^65监听%根据//01/0.2型号与具体电路&对26-进行了如下配置)使能.G 6接口&并设置数据位宽为4%"&以适配26-?P T =P V 的.G 6主接口$工作时钟频率设为*##2M \&参考时钟输入设为"##2M \&以适配板卡上的参考时钟晶振%C D F !)'#"(E,&'(8*='1','(*&"(9'+&'(26-?P T =P V 是自主设计的26-专用测试6,核&主要包含以下模块).G 6T Q L O P 接口*控制器*写数据生成器*.G 6U L T =P V 接口*数据校验器*预期数据生成器*错误计数器*计时器与]0.2主接口%26-?P T =P V 的框架如图"所示%图"!26-?P T =P V 框架图.G 6T Q L O P 接口是控制接口&通过.G 6T Q L O P 接口可以读写控制器中寄存器的值&各寄存器与地址的映射关系与详细描述如表%所示%.G 6T Q L O P 接口的寄存器位宽均为$"位%其中偏移为#[#!#[%*的寄存器是可读可写的&主要包括可配置的测试参数与测试控制%偏移为#["#!#[$(的寄存器是只读的&主要包括测试结果以及固定测试参数%表%!.G 6T Q L O P 接口寄存器地址映射关系寄存器名偏移描述]L T P .S S V P T T #[#测试起始地址]I V T =A P 9J =C #[(读写突发长度]I V T =a I U X P V #[*单次测试突发数量?P T =@D 9=V D Q #[@启动测试与清除中断P T =1=L =I T #[%#26-?P T =P V 状态,L ==P V 91Y ;=8C#[%(固定,L ==P V 9功能开关,L ==P V 9#[%*,L ==P V 9设定0P T P V O P #[%@保留_V ;=P @B 8Q P #["#写数据所用时钟周期数0P L S @B 8Q P #["(读数据所用时钟周期数H V V D V a I U X P V #["*读写数据校验错误数0P T P V O P #["@保留/L =L _;S =C #[$#26-数据位宽+V P N I P 98B#[$(计时时钟频率写数据生成器在控制器的控制下&生成所设地址范围与所设>L ==P V 9的写数据事务%//01/0.2测试的地址范围由测试起始地址*读写突发长度*单次测试突发数量与26-数据位宽(个参数共同确定%公式如下)!=P T ="#S L =L $%X I V T =$&X I V T =*!%"'C ;JC "'X L T P (!=P T =!""式中&!=P T =是测试地址范围大小&'C ;JC 是测试终止地址&'X L T =是测试起始地址&#S L =L 是数据位宽&%X I V T =是突发长度&&X I V T =是突发数量%测试中写入//01/0.2的数据默认是*X ;=长的递增数>L ==P V 9&当固定>L ==P V 9开关被使能后&//01/0.2写入的>L ==P V 9将和#[%*地址寄存器内的数据保持一致%.G 6U L T =P V 接口是数据传输接口&与26-的.G 6T Q L O P 接口相连接%写数据生成器生成的写数据事务和数据校验器生成的读数据事务均由此接口完成具体的数据传输%数据校验器用于校验读回的数据与预期数据的一致性%当两者数据不相符时&错误标志信号P V V D V ,W Q L J 置-%.&使错误计数器计数加一&并将错误数据对应的地址写入]0.2%错误计数器接收数据校验器的错误标志信号进行计数%在完成测试后把错误计数写入H V V D V a I U X P V 寄存器%每次开始测试时错误计数器清零%计时器用于计算.G 6总线读写数据所用时钟周期%在完成测试过程后计时器会将读写数据用时分别写入0P L S @B Z 8Q P 寄存器与_V ;=P @B8Q P 寄存器%根据这两项测试结果以及计时时钟频率得出读写数据用时以及平均带宽%公式如下))Y V ;=P "*Y V ;=P+=;U P V!$",Y V ;=P "!=P T =)Y V ;=P!("式中&)Y V ;=P 是写数据实际所用时长&*Y V ;=P 是从寄存器中读取的写数据所用时钟周期数&+=;U P V 是计时器频率&,Y V ;=P 是写数!投稿网址 Y Y Y!7T 78Q B:\!8D U Copyright ©博看网. All Rights Reserved.!!计算机测量与控制!第$%""""""""""""""""""""""""""""""""""""""""""""""""""""卷#'#!#据平均带宽%读数据所用时间和平均带宽的计算方式类似&不再赘述%图$为26-?P T =P V 控制器的状态机示意图%当P T =@D 9=V D Q 寄存器的启动位被写入-%.时&处于空闲状态下的控制器进入写数据状态%.G 6U L T =P V 接口开始对指定地址范围写入所设>L ==P V 9%在完成指定地址范围的数据写入后&控制器进入读数据与数据校验状态%.G 6U L T =P V 接口读取指定地址范围的数据并校验%在完成指定范围数据的读取与比较后&进入测试完成状态&测试结果被写入.G 6T Q L O P 接口的测试结果寄存器中&同时完成中断信号置-%.%测试结果写入完成后&控制器回到空闲状态%图$!控制器状态机C D G !:."=H )'#"(?1','(*&"(]Q D 8:2P U D V B -P 9P V L =D V 可以使用+,-.内的]0.2资源生成性能优秀的存储器&这类存储器一般就被称为]0.2%在设计中]0.2被设置为真双口模式&用于存储读写校验发生错误的错误数据对应的地址信息%C D I !2J E:42)!",&("..'(.G 6]0.2@D 9=V D Q Q P V 提供了可供访问本地]0.2的.G 6T Q L O P 接口&支持突发事务&性能优秀%在设计中.G 6]0.2@D 9=V D Q Q P V 控制真双口]0.2的其中一个端口%3?.-=D.G 6可以通过此6,读取]0.2中的数据%C D K !L 6(&%*.E ,$%&M %&$%&^65用于在线监测或驱动+,-.内部的信号%本设计中主要使用^65驱动26-的复位信号&以及监测26-的初始化完成信号%^65由,@上位机通过3?.-接口控制%C D N !2J E &"O 921.G 6=D 3?.-用于生成.G 6接口事务%本设计中主要使用.G 6=D3?.-控制26-?P T =P V &并读回测试结果%.G 6=D 3?.-由,@上位机通过3?.-接口控制%C D P !E ,&'7(*&';Q "76=2,*.?R '(6A .用于捕获+,-.内部信号%本设计中主要使用6A .捕获读写数据校验错误时26-的.G 6接口的数据&并通过@A 命令将数据保存至,@上位机%6A .由,@上位机通过3?.-接口控制%C D S !2J E 5#*(&!",,'=&.G 61U L V =@D 99P 8=是由G ;Q ;9[官方提供的.G 6总线互联6,&可以将一个或多个.G 6内存映射主设备连接到一个或多个.G 6内存映射从设备%本设计中主要使用.G 61U L V =@D 99P 8=将各.G 6设备互联%F !0!上位机软件设计,@上位机软件的设计主要包括?@A 脚本设计与图形界面程序设计两个部分%F D B !9!Q 脚本设计@A 作为一门具有简明高效*便于移植的脚本语言&应用于众多H /.软件%^;O L S D 软件在?@A 语言的基础上增添了许多命令&以帮助开发者提高生产力%在本设计中&通过@A 脚本编程控制+,-.中的$个调试6,&配合完成初始化测试与读写测试两种测试功能%$R %R %!^65控制脚本通过在^;O L S D 软件中执行?@A 脚本&,@上位机可以控制^65的驱动值或读取^65探针的电平%需要修改^65输出探针驱动值时&使用T P =,>V D >P V =B 命令修改对应探针的5b ?,b ?,^.A b H 值&之后使用8D U U ;=,C Y ,O ;D 命令执行驱动值的修改%需要读取^65输入探针电平时&使用V P W V P T C ,C Y ,O ;D 命令刷新^65输入探针的电平&然后使用J P =,>V D >P V =B 命令获取对应探针的6a ,b ?,^.A b H 数值%$R %R "!.G 6=D 3?.-控制脚本,@上位机可以通过执行?@A 脚本来控制.G 6=D3?.-发起.G 6总线读写事务&从而访问目标设备%当需要对.G 6设备进行读操作时&使用8V P L =P ,C Y ,L [;,=[9命令创建读数据事务&执行V I 9,C Y ,L [;命令运行该事务%随后使用V P >D V =,C Y ,L [;,=[9命令报告读取数据%在完成传输数据事务后&使用S P Q P =P ,C Y ,L [;,=[9命令删除该事务%写.G 6设备数据的过程与读数据过程类似&区别在于生成写事务时需要指定事务类型为写&并增加一个写入数据作为参数%$R %R $!6A .控制脚本?@A 脚本可以控制6A .执行信号抓取任务&并将抓取的数据展示或保存下来%需要通过6A .抓取特定信号时&首先使用T P =,>V D >P V =B 命令修改需要抓取的信号以及触发方式&然后使用V I 9,C Y ,;Q L 命令开始执行抓取信号%抓取到信号后&使用I >Q D L S ,C Y ,;Q L ,S L =L 命令更新数据&并用Y V ;=P ,C Y ,;Q L ,S L =L 命令将抓取到的信号数据保存为;Q L 文件和8T O 文件&便于后续进行分析%$R %R (!初始化测试脚本初始化测试的原理是&对26-重复进行复位与初始化&记录该过程中26-是否能在限定时间内完成初始化%?@A 脚本编程的//01/0.2初始化测试流程如图(所示%在开始//01/0.2初始化测试后&首先控制^65驱动26-复位信号U ;J ,V T =,9为#&以确保26-处于复位状态%之后控制^65驱动26-复位信号U ;J ,V T =,9为%&26-开始一次初始化过程%之后^65监测的;9;=,8D U Z >Q P =P 信号的值&如果在指定时间内检测到高电平&则视为初始化成功&反之则视为初始化失败%完成测试结果记录后&判断已测试次数是否已达到指定的测试次数&如果已满足则输出测试结果&反之则返回第一步继续进行测试%!投稿网址 Y Y Y!7T 78Q B:\!8D U Copyright ©博看网. All Rights Reserved.第%#期谢树平&等)基于+,-.的//01/0.2""""""""""""""""""""""""""""""""""""""""""""""""""""测试平台设计#'%!#图(!初始化测试流程图$R %R 4!读写测试脚本读写测试的原理是&将测试参数写入26-?P T =P V&控制26-?P T =P V 开始读写测试&并将每次测试结果进行记录与统计%@A 脚本控制的读写测试流程如图4所示%首先控制3?.-=D.G 6向26-?P T =P V 写入读写测试的起止地址*写操作的>L ==P V 9与读写的突发数等测试参数%随后设置6A .的触发信号为错误标志信号P V V D V ,W Q L J 信号的高电平%写P T =@D 9=V D Q 寄存器启动26-?P T =P V %通过^65监控测试完成信号;9=V ,S D 9P 直到它变为高电平%至此一次测试完成&由3?.-=D.G 6读出测试结果并保存%随后判断测试次数是否以达到目标&若已达到则统计所有测试结果并输出&反之则再次启动测试%图4!读写测试流程图F D C !图形界面程序设计图形界面程序在,B E =4框架下进行开发%,B E =4衍生自@cc 的E ?库&具有能够跨平台兼容多种环境&功能强大&开源免费等优势%图形界面程序通过创建子进程的方式运行命令行程序&并在命令行程序中打开@A 模式的^;O L S D %点击程序中的功能按钮即可执行对应的^;O L S D 指令或者@A 脚本%图形界面程序的界面如图&所示&主要功能包括)%"人机交互)操作人员可以根据测试需求&在图形界面程序中调整测试参数*执行测试任务和读取测试信息%""器件控制)程序可以通过3?.-接口完成连接+,Z -.器件*状态检测*下载比特流*控制调试核等操作%$"统计结果)程序自动重复并统计测试结果&在测试循环完成后输出测试统计报告并保存为日志文件%图&!应用程序界面程序界面主要分为(个区域%区域%主要包括连接器件以及下载比特流文件功能%区域"包括初始化测试的参数设置与执行%区域$包括读写测试的参数设置与执行%区域(是一个文本框&输出文本信息%首先需要在区域%中完成器件的连接与比特流文件的下载%程序启动后将自动运行^;O L S D 子进程&并在文本框处提示-^;O L S D 启动中.%待^;O L S D 启动完成&文本框处打印-启动完成.信息&-连接器件.按钮变为可用%点击-连接器件.&^;O L S D 进程将打开硬件管理器&并尝试连接+,-.器件%如果未检测到+,-.器件&则打印-连接失败.信息&如果检测到+,-.器件&则在-当前器件.标签处显示检测到的器件型号*连接状态与编程状态%-器件型号.下拉选项和-比特流选择.下拉选项会自动筛选出符合当前器件的选项%用户需要在这一步自行选择适用的比特流文件并点击-下载比特流.按钮%等待文本框提示-比特流下载完成.&即可在区域"或区域$中执行后续测试%!投稿网址 Y Y Y!7T 78Q B:\!8D U Copyright ©博看网. All Rights Reserved.!!计算机测量与控制!第$%""""""""""""""""""""""""""""""""""""""""""""""""""""卷#'"!#区域"中&初始化时间限制即是?@A 脚本中判定初始化是否成功的界限&初始化测试次数是本次执行初始化测试的总测试数%执行测试后&测试结果打印在文本框中&并在完成一轮测试后生成日志文件%日志文件内容如图'所示&日志内容包括)测试日期*测试项目名*测试序号*初始化测试结果以及完成本轮次的测试后的统计数据%图'!初始化测试结果输出区域$中&软件将根据设置的起始地址*结束地址以及.G 6总线突发数量等参数&计算出对应的配置参数&并写入到26-?P T =P V 的配置寄存器中%可以勾选下方的测试>L ==P V 9复选框来选定本次测试需要测试的>L ==P V 9%勾选了自定义>L ==P V 9的情况下需要将自定义的>L ==P V 9填入后方的文本框内%设置好>L ==P V 9测试次数后点击-执行读写测试.按钮&软件将依次执行每个选定>L ==P V 9的测试%测试结果将打印在下方的文本框中&并在一轮测试完成后将生成日志文件%日志文件内容如图*所示&输出的内容包括)测试日期*测试项目名*测试序号*读写平均带宽*错误数据数量以及本轮次的测试的统计数据%图*!读写测试结果输出如果在读写测试过程中发生了读数据与预期数据不符的情况&6A .将抓取错误发生时.G 6总线上的信号并保存到硬盘上%在需要分析信号时&可以在^;O L S D 程序中使用V P L S ,C Y ,;Q L ,S L =L 命令读取数据&并用S ;T >Q L B ,CY ,;Q L ,S L =L 命令绘制信号波形图%如图)所示&图中标记的部分P V V D V ,W Q L J 信号为-%.&表示该位置出现了读写错误%图)!数据错误发生时的信号波形图同时]0.2接口写使能&将错误数据对应的地址信息写入]0.2中%程序可以通过3?.-=D.G 6访问26-中这些地址并读回数据&从而生成错误数据列表%如图%#所示&L S S V 是错误数据对应的地址%P [,S L =L 是期望数据&也就是读写功能正常情况下应读回的数据%V S ,S L =L 则是实际读回的数据%操作人员可以根据该报告分析可能存在的问题%图%#!错误数据记录文件G !实验结果与分析G D B !)E 19'+&'(功能验证使用^;O L S D 软件的仿真功能对26-?P T =P V 进行功能验证%配置.G 6^P V ;W ;8L =;D 96,为从模式&连接至26-?P T =P V 的.G 6U L T =P V 接口&在仿真中关注.G 6总线的读写事务以及相关信号的变化%在单次读写测试中&.G 6总线上先后发生的写事务与读事务%为了缩短仿真时间&测试的地址范围设置为#[#!#[&$+++%在通过控制接口启动测试后&26-?P T =P V 先对整个测试地址范围顺序写入一次>L ==P V 9&然后进入读取数据状态&并将读取的数据与预期数据进行校验%完成整个过程后&完成中断信号将被置-%.%在.G 6总线的写通道中&写地址L Y L S S V 在每次握手写!投稿网址 Y Y Y!7T 78Q B:\!8D U Copyright ©博看网. All Rights Reserved.第%#期谢树平&等)基于+,-.的//01/0.2""""""""""""""""""""""""""""""""""""""""""""""""""""测试平台设计#'$!#入后增加突发传输所占的地址大小&实现对测试地址范围内所有地址的写入%当设置的>L ==P V 9是递增数时&写数据Y S L =L 每写入一次数据后递增%%写突发结束计数器Y Q L T =,8D I 9=P V 在Y Q L T =信号置位时计数加一&用于控制数据的突发传输%Y V ;=P ,=;U P V 信号是写状态计时器&从测试进入写>L ==P V 9过程开始计时&直到进入读数据状态停止计时%在.G 6总线的读通道中&读地址L V L S S V 在每次握手写入后增加突发传输所占的地址大小&实现对测试地址范围内所有地址的读取%读数据V S L =L 是读回的数据%当设置的>L ==P V 9是递增数&预期数据P [>P 8=P S ,S L =L 每写入一次数据后发生递增%错误标志信号P V V D V ,W Q L J 的特征是在预期数据与读取数据V S L =L 不同时置%&由于读取过程中预期数据与读取数据相符&所以错误标志保持为#%读突发结束计数器V Q L T =,8D 9=P V 在每次V Q L T =信号置位时计数加一&用于控制状态机的转换%V P L S ,=;U P V 是读状态计时器&从状态机进入读数据状态开始计时&直到进入测试完成状态停止计时%然后人为插入错误数据验证数据校验模块功能是否正常%插入错误数据的方式如下)选择>L ==P V 9为递增数&并且当写入数据为.4时&将其替换为4.%在读数据时&读回数据V S L =L 为4.&与其对应的预期数据.4不符合&所以错误标志信号P V V D V ,W Q L J 置-%.&且错误计数器加一%证明数据校验功能正常%经过上述功能验证&可以确认测试6,核26-?P T =P V 逻辑功能符合预期&可以将其用于//01/0.2的测试%G D C !/012资源使用对比+,-.测试平台工程设计完毕后&在软件^;O L Z S D "#"#R "默认设置下执行生成比特文件%作为对比&打开26-的示例工程并生成比特文件%26-的示例工程常作为//01/0.2的测试调试工程使用%对比测试平台工程与示例工程的资源使用数量&结果如表"所示%测试平台工程资源使用量对比示例工程显著减少%其中作为+,-.主要资源的查找表!A b ?&Q D D :Z I >Z =L X Q P "的使用减少了$$R ""F &触发器!++&+Q ;>+Q D >"的使用减少了$*R (#F %表"!+,-.资源使用数量对比+,-.资源名测试平台工程示例工程A b ?%'(%4"&#*%A b ?0.2$)"&("%#++"#$'%$$#'#]0.2$)(*R 4G D F !/012板卡测试测试板卡使用的+,-.产自G ;Q ;9[公司&型号为[8':$"4=W W J )##Z "&使用的//01/0.2型号为2?*3?+"Z 4&&(M `Z %-&2%%(R $R %!测试流程//01/0.2测试基本流程如下)%"设计+,-.工程&生成比特流文件与Q =[文件!调试核信息文件"&并拷贝到图形界面程序目录下的X ;=T =V P L U 文件夹中%""使用仿真器将+,-.板卡连接至,@上位机并上电%打开图形界面程序&待启动完成后点击-连接器件.&等待连接完成&标签栏处出现+,-.器件名称与状态%$"选择与+,-.对应的比特流&点击-下载比特流.&等待比特流下载完成&标签栏处显示-已连接&已编程.%("在文本框中设置测试参数&根据测试需求执行相应的测试%在测试完成后&将在程序目录下生成测试结果报告%(R $R "!初始化测试根据赛灵思官方手册提供的数据&设置初始化时间限制为%###U T %执行%##次初始化测试%初始化测试结果如表$所示%在%##次初始化测试中&//01/0.2的初始化均在%###U T 以内完成%结果说明&测试板卡中的//01/0.2能够正常初始化%表$!初始化测试结果总初始化次数超时次数成功次数%###%##(R $R $!读写测试设置读写测试起始地址为#&结束地址为#['++++Z +++&即测试整个"-]的地址空间%设置.G 6总线突发数为&(&测试,L ==P V 9栏目中勾选递增数##*++*44*..&每个>L ==P V 9测试%##次%数据读写测试测试结果如表(所示%写平均带宽和读平均带宽分别达到了理论带宽的*$R )F 和**R %F &且没有出现过读写数据校验错误%证明了在测试环境下//01/0.2读写数据功能正常&带宽性能良好%表(!数据读写测试结果-]+T ,L ==P V 9写平均带宽读平均带宽理论带宽校验错误数递增数)R ))'%#R 4#"%%R )"%###)R ))'%#R 4#"%%R )"%#++)R ))'%#R 4#"%%R )"%#44)R ))'%#R 4#"%%R )"%#..)R ))'%#R 4#"%%R )"%#平均值)R ))'%#R 4#"%%R )"%#(R $R (!测试时长对比表4是两类测试的测试平均时长对比%对于初始化测试&示例工程的测试方法如下)操作人员使用^;O L S D 软件的硬件管理器控制^65输出的复位信号失效&之后通过^65观察26-输出的初始化完成信号是否置-%.&据此判断26-是否完成了初始化%在此过程中&操作人员需要不断重复上述过程%一方面存在操作人员操作或记录失误的可能性$另一方面手动操作效率低下&且无法准确判断初始化所用时长%对于读写测试&选用测试##*++*44*..与递增数物种>L ==P V 9的情况进行对比%示例工程的测试方!投稿网址 Y Y Y!7T 78Q B:\!8D U Copyright ©博看网. All Rights Reserved.。
// megafunction wizard: %ALTPLL%// GENERATION: STANDARD// VERSION: WM1.0// MODULE: altpll// ============================================================ // File Name: clk_ctrl.v// Megafunction Name(s):// altpll//// Simulation Library Files(s):// altera_mf// ============================================================ // ************************************************************ // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!//// 11.0 Build 208 07/03/2011 SP 1 SJ Full Version// ************************************************************//Copyright (C) 1991-2011 Altera Corporation//Your use of Altera Corporation's design tools, logic functions//and other software and tools, and its AMPP partner logic//functions, and any output files from any of the foregoing//(including device programming or simulation files), and any//associated documentation or information are expressly subject//to the terms and conditions of the Altera Program License//Subscription Agreement, Altera MegaCore Function License//Agreement, or other applicable license agreement, including,//without limitation, that your use is for the sole purpose of//programming logic devices manufactured by Altera and sold by//Altera or its authorized distributors. Please refer to the//applicable agreement for further details.// synopsystranslate_off`timescale 1 ps / 1 ps// synopsystranslate_onmoduleclk_ctrl (areset,inclk0,c0,c1,c2,locked);input areset;input inclk0;output c0;output c1;output c2;output locked;`ifndef ALTERA_RESERVED_QIS// synopsystranslate_off`endiftri0 areset;`ifndef ALTERA_RESERVED_QIS// synopsystranslate_on`endifwire [5:0] sub_wire0;wire sub_wire2;wire [0:0] sub_wire7 = 1'h0;wire [2:2] sub_wire4 = sub_wire0[2:2];wire [0:0] sub_wire3 = sub_wire0[0:0];wire [1:1] sub_wire1 = sub_wire0[1:1];wire c1 = sub_wire1;wire locked = sub_wire2;wire c0 = sub_wire3;wire c2 = sub_wire4;wire sub_wire5 = inclk0;wire [1:0] sub_wire6 = {sub_wire7, sub_wire5};altpll altpll_component (.areset (areset),.inclk (sub_wire6),.clk (sub_wire0),.locked (sub_wire2),.activeclock (),.clkbad (),.clkena ({6{1'b1}}),.clkloss (),.clkswitch (1'b0),.configupdate (1'b0),.enable0 (),.enable1 (),.extclk (),.extclkena ({4{1'b1}}),.fbin (1'b1),.fbmimicbidir (),.fbout (),.fref (),.icdrclk (),.pfdena (1'b1),.phasecounterselect ({4{1'b1}}),.phasedone (),.phasestep (1'b1),.phaseupdown (1'b1),.pllena (1'b1),.scanaclr (1'b0),.scanclk (1'b0),.scanclkena (1'b1),.scandata (1'b0),.scandataout (),.scandone (),.scanread (1'b0),.scanwrite (1'b0),.sclkout0 (),.sclkout1 (),.vcooverrange (),.vcounderrange ());defparamaltpll_component.clk0_divide_by = 1,altpll_component.clk0_duty_cycle = 50,altpll_component.clk0_multiply_by = 5,altpll_component.clk0_phase_shift = "0",altpll_component.clk1_divide_by = 1,altpll_component.clk1_duty_cycle = 50,altpll_component.clk1_multiply_by = 1,altpll_component.clk1_phase_shift = "0",altpll_component.clk2_divide_by = 1,altpll_component.clk2_duty_cycle = 50,altpll_component.clk2_multiply_by = 5,altpll_component.clk2_phase_shift = "5000",altpll_pensate_clock = "CLK0",altpll_component.gate_lock_signal = "NO",altpll_component.inclk0_input_frequency = 50000,altpll_component.intended_device_family = "Cyclone II",altpll_component.invalid_lock_multiplier = 5,altpll_component.lpm_hint = "CBX_MODULE_PREFIX=clk_ctrl", altpll_component.lpm_type = "altpll",altpll_component.operation_mode = "NORMAL",altpll_component.port_activeclock = "PORT_UNUSED",altpll_component.port_areset = "PORT_USED",altpll_component.port_clkbad0 = "PORT_UNUSED",altpll_component.port_clkbad1 = "PORT_UNUSED",altpll_component.port_clkloss = "PORT_UNUSED",altpll_component.port_clkswitch = "PORT_UNUSED",altpll_component.port_configupdate = "PORT_UNUSED", altpll_component.port_fbin = "PORT_UNUSED",altpll_component.port_inclk0 = "PORT_USED",altpll_component.port_inclk1 = "PORT_UNUSED",altpll_component.port_locked = "PORT_USED",altpll_component.port_pfdena = "PORT_UNUSED",altpll_component.port_phasecounterselect = "PORT_UNUSED", altpll_component.port_phasedone = "PORT_UNUSED",altpll_component.port_phasestep = "PORT_UNUSED",altpll_component.port_phaseupdown = "PORT_UNUSED", altpll_component.port_pllena = "PORT_UNUSED",altpll_component.port_scanaclr = "PORT_UNUSED",altpll_component.port_scanclk = "PORT_UNUSED",altpll_component.port_scanclkena = "PORT_UNUSED",altpll_component.port_scandata = "PORT_UNUSED",altpll_component.port_scandataout = "PORT_UNUSED",altpll_component.port_scandone = "PORT_UNUSED",altpll_component.port_scanread = "PORT_UNUSED",altpll_component.port_scanwrite = "PORT_UNUSED",altpll_component.port_clk0 = "PORT_USED",altpll_component.port_clk1 = "PORT_USED",altpll_component.port_clk2 = "PORT_USED",altpll_component.port_clk3 = "PORT_UNUSED",altpll_component.port_clk4 = "PORT_UNUSED",altpll_component.port_clk5 = "PORT_UNUSED",altpll_component.port_clkena0 = "PORT_UNUSED",altpll_component.port_clkena1 = "PORT_UNUSED",altpll_component.port_clkena2 = "PORT_UNUSED",altpll_component.port_clkena3 = "PORT_UNUSED",altpll_component.port_clkena4 = "PORT_UNUSED",altpll_component.port_clkena5 = "PORT_UNUSED",altpll_component.port_extclk0 = "PORT_UNUSED",altpll_component.port_extclk1 = "PORT_UNUSED",altpll_component.port_extclk2 = "PORT_UNUSED",altpll_component.port_extclk3 = "PORT_UNUSED",altpll_component.valid_lock_multiplier = 1;endmodule// ============================================================ // CNX file retrieval info// ============================================================ // Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "0"// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"// Retrieval info: PRIVATE: BANDWIDTH_USE_CUSTOM STRING "0"// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "1"// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8"// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1"// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1"// Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "1"// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"// Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000"// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "100.000000" // Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "20.000000" // Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "100.000000" // Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" // Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "1"// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "20.000"// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II" // Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" // Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg"// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "deg"// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"// Retrieval info: PRIVATE: MIRROR_CLK2 STRING "0"// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "5"// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "1"// Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "5"// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "100.00000000"// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "100.00000000"// Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "100.00000000"// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0"// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "0"// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 STRING "MHz"// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "0" // Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000"// Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "5.00000000"// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0" // Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg"// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "ns"// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1"// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"// Retrieval info: PRIVATE: PLL_ENA_CHECK STRING "0"// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"// Retrieval info: PRIVATE: RECONFIG_FILE STRING "clk_ctrl.mif"// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "0"// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"// Retrieval info: PRIVATE: SPREAD_USE STRING "0"// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"// Retrieval info: PRIVATE: STICKY_CLK2 STRING "1"// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"// Retrieval info: PRIVATE: USE_CLK0 STRING "1"// Retrieval info: PRIVATE: USE_CLK1 STRING "1"// Retrieval info: PRIVATE: USE_CLK2 STRING "1"// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"// Retrieval info: PRIVATE: USE_CLKENA2 STRING "0"// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"// Retrieval info: LIBRARY: altera_mfaltera_mf.altera_mf_components.all// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1"// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "5"// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "1"// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "1"// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"// Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "1"// Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50"// Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "5"// Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "5000"// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"// Retrieval info: CONSTANT: GATE_LOCK_SIGNAL STRING "NO"// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "50000" // Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II"// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL"// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED"// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED"// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" // Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED"// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_USED"// Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"// Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"// Retrieval info: USED_PORT: @clk 0 0 6 0 OUTPUT_CLK_EXT VCC "@clk[5..0]"// Retrieval info: USED_PORT: @extclk 0 0 4 0 OUTPUT_CLK_EXT VCC "@extclk[3..0]" // Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset"// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"// Retrieval info: USED_PORT: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2"// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1// Retrieval info: CONNECT: c2 0 0 0 0 @clk 0 0 1 2// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0// Retrieval info: GEN_FILE: TYPE_NORMAL clk_ctrl.v TRUE// Retrieval info: GEN_FILE: TYPE_NORMAL clk_ctrl.ppf TRUE// Retrieval info: GEN_FILE: TYPE_NORMAL clk_ctrl.inc FALSE// Retrieval info: GEN_FILE: TYPE_NORMAL clk_ctrl.cmp FALSE// Retrieval info: GEN_FILE: TYPE_NORMAL clk_ctrl.bsf FALSE// Retrieval info: GEN_FILE: TYPE_NORMAL clk_ctrl_inst.v TRUE// Retrieval info: GEN_FILE: TYPE_NORMAL clk_ctrl_bb.v TRUE// Retrieval info: LIB_FILE: altera_mf// Retrieval info: CBX_MODULE_PREFIX: ON`timescale 1ns / 1ps////////////////////////////////////////////////////////////////////////////////// Company :/*-----------------------------------------------------------------------------SDRAM接口说明:上电复位时,SDRAM会自动等待200us然后进行初始化,具体模式寄存器的设置参看sdram_ctrl模块。