基于FPGA的verilog源代码数字CMOS摄像机图像采集

基于FPGA的verilog源代码数字CMOS摄像机图像采集
基于FPGA的verilog源代码数字CMOS摄像机图像采集

基于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通过I2C 总线对其内部寄存器进行配置,使其按照一定的格式进行采样。

(2)异步FIFO模块:当FPGA接收A/D采样的视频数据时,由于SAA7113和FPGA一般在不同的时钟频率下,这就会出现通常所说的异步时钟问题,处理不当就容易出现亚稳态,常用方法是在两者之间添加一块异步FIFO。

(3)视频变换模块:对得到的数字视频流进行解码,识别出行、场同步信号,并且根据需要选择采集图像的大小,进而变换成RGB格式的图像数据,以便于后续显示。

(4)图像帧存读写模块:将解码后的数据经由一个乒乓机制依次存放在两片RAM中,每个里面刚好存放一幅图像,通过乒乓机制使得两块存储区域交替进行存储输入和显示输出,避免等待,提高速度。

(5)VGA控制模块:根据VGA的工业参数,产生相应的行同步和场同步信号,并在适当时刻送入数据,经由ADV7125送VGA进行显示。

图3描述了FPGA内部的各个主要功能模块。系统上电时,FPGA首先从外部Flash中读取配置数据,完成自身的程序加载,进入工作模式状态。随后I2C配置接口模块完成对

SAA7113的初始化,初始化结束后,FPGA等待采集图像的命令。FPGA收到采集命令后,启动采集视频数据模块、异步FIFO模块和视频解码模块进行解码,将数据轮换写到两个帧存中,经通信模块送出,以上即为该系统的工作流程。下面主要针对SDRAM控制模块的具体实现过程进行详细分析和介绍。

(1)SDRAM的初始化

SDRAM在上电100~200μs后,必须由一个初始化进程来配置SDRAM的模式存储器,模式存储器的值决定SDRAM的工作模式。

访问存储单位:为减少I/O引脚数量,SDRAM复用地址线,所有在读写SDRAM时,先由ACTIVE命令激活要读写的BANK,并锁存行地址,然后在读写指令有效时锁存列地址。一旦BANK被激活后,只有执行一次预充命令后才能再次激活同一BANK。

(2)刷新和预充

SDRAM的存储单元可以理解为一个电容,总是倾向于放电,因此必须有定时刷新周期以避免数据全失。刷新周期可由(最小刷新周期+时候周期)计算获得。对BANK预充电或者关闭已激活的BANK,可预充特定BANK也可同时作用于所有BANK,A10、BA0和BA1用于选择BANK。

(3)操作控制

SDRAM的具体控制命令由一些专用控制引脚和地址线辅助完成。CS、RAS、CAS和WR在时钟上升沿的状态决定具体操作动作,地址线和BANK选择控制线在部分操作动作中作为辅助参数输入。由于特殊的存储结构,SDRAM操作指令比较多,不像SRAM一样只有简单的读写。根据系统要求,本设计选用SAMSUNG的K4S6432 SDRAM芯片。

3.2SDRAM控制器总体设计

SDRAM控制器与外部的接口示意图由图4给出,控制器右端接口信号均为直接与SDRAM对应管脚相连的信号;控制器左端的接口信号为与FPGA相连的系统控制接口信号,其中,CLK为系统时钟信号,RESET_N为复位信号,ADDR为系统给出的SDRAM地址信号,DAIN是系统用于写入SDRAM的数据信号,FPGA_RD和FPGA_WR为系统读、写请求信号(1为有效,0为无效),SDRAM_FREE是SDRAM的空闲状态标示信号(0为空闲,1为忙碌),FDATA_ENABLE是控制器给系统的数据收发指示信号(为0时,无法对SDRAM 进行数据收发;为1时,若是系统读操作,则系统此时可从DAOUT接收SDRAM的数据,若是写操作,则系统此时可以通过DAIN发送数据给SDRAM)。

图5 SDRAM控制器的结构图

3.3SDRAM系统控制接口子模块设计

该模块主要包括初始化和系统指令分析功能。其工作过程如下:由计数器控制在系统上电约200μs后,先进行SDRAM的初始化配置工作,由一个Precharge all back指令完成对所有BANK的预充,接着是多个Refresh指令,然后是模式配置指令LOADMODE,完成SDRAM 的工作模式设置。之后进行控制器的初始化配置工作,先发出指令LOADREG1给控制器载入模式字,再发出LOADREG2指令载入控制器的刷新计数器值,完成控制器初始化配置。

上述初始化过程结束后,系统指令分析机制才可接收并分析系统的读写信号和地址信息,以及从下个模块反馈回来的CMD_ACK信号,并产生对应的CMD命令和SADDR地址信息给CMD命令解析模块。通过程序设置,实现了根据初始化配置的参数来确定在读写到特定时刻发出Precharge或者Refresh的CMD指令,从而简化了系统的控制。而每当收到CMD_ACK为1时,表示CMD指令已经发出并有效,此时就要发出NOP命令(CMD=000)。要说明的是,SADDR是分时复用的,在初始化载入模式时,SADDR用以传输用户自己定义的模式字内容;而在正常的读写期间,SADDR作为地址线传输SDRAM所需的行、列和块地址。代码示例如附件1.

3.4CMD命令解析和命令相应子模块

该模块首先对CMD指令进行判断,其结果解释输出相应的操作指令进行响应。例如,CMD为001时,则会输出do_read信号为1;CMD为010时,则会输出do_write信号为1,在同一时刻,只会输出一种有效的操作指令。然后该模块根据操作指令,做出符合SDRAM 读写规范的操作动作,来进行用户期望的操作;给出数据选通信号OE,来控制数据通路模块(写操作OE为1,读操作时OE为0)。此外,该模块把系统非复用的地址ADDR处理为SDRAM复用的地址,分时送给SA、BA。程序中地址复用的方法为:

assign raddr=ADDR[ROWSTART+ROWSIZE-1:ROWSTART];//raddr为行地址

assign eaddr=ADDR[COLSTART+COLSIZE-1:COLSTART];//eaddr为列地址

assign baddr=ADDR[BANKSTART+BANKSIZE-1:BANKSTART];//baddr为BANK地址在程序中,WRITEA和READA的CMD指令实际隐含了ACTIVE命令,所以该模块在收到do_write或do_read指令后,会先进行激活动作,经过初始化配置规定的CAS延迟时间之后再进行读写动作。

此外,该模块内含用以预设某些模式参数的模式寄存器,主要包括3类:第1类是SDRAM模式控制寄存器,在LOADMODE指令时,将该寄存器的值送入SDRAM的模式寄存器中,以控制SDRAM的工作模式;第2类是SDRAM控制器的参数寄存器

(LOAD_REG1),使得SDRAM控制器的工作方式与外部的SDRAM器件的工作方式匹配;第3类是SDRAM的刷新周期控制寄存器,该寄存器预设用户定义的自动刷新计数值,用于SDRAM的刷新周期预设。上述3类寄存器的预设值都是系统控制接口模块在初始化时通过SADDR传送给来的。收到各类操作指令后,该模块会反馈给CMD命令解析模块cmdack 信号为1,并最终反馈到系统控制接口模块的CMDACK信号为1,如果没有收到任何操作指令,则cmdack=0,CMDACK信号为0。代码示例如附件2.

3.5数据通路子模块

该模块受OE信号的控制,使数据的进出和相应的操作指令在时序上同步。OE为1时,数据可由DQ脚写入SDRAM,OE为0时,数据可从SDRAM的DQ脚读出。因为是内部模块,所以应该尽量避免使用双向端口,因此在这里DQ的输入输出作用分别用端口DQIN 和DQOUT代替,在顶层模块调用时再使用OE信号实现三态双向传输。代码示例如附件3.

3.6SDRAM控制器顶层模块

实际上在大型工程开发过程中很少用到图形编辑工具,因为连接线较多不易连接,容易显得杂乱,可读性和可移植性都不强。因此大多数模块调用都是通过代码形式来调用的,读者要熟悉并习惯使用在程序中调用另一个子模块的方式。附件4是SDRAM控制器顶层模块代码示例,通过这种调用方式将其他子模块融合在一个统一的大工程下。

附件1:

module control_interface (CLK, RESET_N, CMD, ADDR, REF_ACK, CM_ACK, NOP, READA, WRITEA, REFRESH,PRECHARGE, LOAD_MODE, SADDR, SC_CL, SC_RC, SC_RRD, SC_PM, SC_BL, REF_REQ, CMD_ACK);

parameter ASIZE = 32;

input CLK;

input RESET_N;

input[2:0] CMD;

input[ASIZE - 1:0] ADDR;

input REF_ACK;

input CM_ACK;

output NOP;

reg NOP;

output READA;

reg READA;

output WRITEA;

reg WRITEA;

output REFRESH;

reg REFRESH;

output PRECHARGE;

reg PRECHARGE;

output LOAD_MODE;

reg LOAD_MODE;

output[ASIZE - 1:0] SADDR;

wire[ASIZE - 1:0] SADDR;

output[1:0] SC_CL;

wire[1:0] SC_CL;

output[1:0] SC_RC;

wire[1:0] SC_RC;

output[3:0] SC_RRD;

wire[3:0] SC_RRD;

output SC_PM;

wire SC_PM;

output[3:0] SC_BL;

wire[3:0] SC_BL;

output REF_REQ;

wire REF_REQ;

output CMD_ACK;

wire CMD_ACK;

reg LOAD_REG1;

reg LOAD_REG2;

wire[15:0] REF_PER;

wire[15:0] timer;

wire timer_zero;

reg[ASIZE - 1:0] SAADR_int;

wire CMD_ACK_int;

wire[3:0] SC_BL_int;

always @(posedge CLK or negedge RESET_N)

begin

if (RESET_N == 1'b0)

begin

NOP <= 1'b0 ;

READA <= 1'b0 ;

WRITEA <= 1'b0 ;

REFRESH <= 1'b0 ;

PRECHARGE <= 1'b0 ;

LOAD_MODE <= 1'b0 ;

LOAD_REG1 <= 1'b0 ;

LOAD_REG2 <= 1'b0 ;

SAADR_int <= {ASIZE - 1-(0)+1{1'b0}} ;

end

else

begin

SAADR_int <= ADDR ;

if (CMD == 000)

begin

NOP <= 1'b1 ;

end

else

begin

NOP <= 1'b0 ;

end

if (CMD == 001)

begin

READA <= 1'b1 ;

end

else

begin

READA <= 1'b0 ;

end

if (CMD == 010)

begin

WRITEA <= 1'b1 ;

end

else

begin

WRITEA <= 1'b0 ;

end

if (CMD == 011)

begin

REFRESH <= 1'b1 ;

end

else

begin

REFRESH <= 1'b0 ;

end

if (CMD == 100)

begin

PRECHARGE <= 1'b1 ; end

else

begin

PRECHARGE <= 1'b0 ; end

if (CMD == 101)

begin

LOAD_MODE <= 1'b1 ; end

else

begin

LOAD_MODE <= 1'b0 ; end

if ((CMD == 110) & (LOAD_REG1 == 1'b0)) begin

LOAD_REG1 <= 1'b1 ; end

else

begin

LOAD_REG1 <= 1'b0 ; end

if ((CMD == 111) & (LOAD_REG2 == 1'b0)) begin

LOAD_REG2 <= 1'b1 ; end

else

begin

LOAD_REG2 <= 1'b0 ; end

end

end

endmodule

附件2:

module command (CLK, RESET_N, SADDR, NOP, READA, WRITEA, REFRESH, PRECHARGE, LOAD_MODE, SC_CL, SC_RC, SC_RRD, SC_PM, SC_BL, REF_REQ, REF_ACK, CM_ACK, OE, SA, BA, CS_N, CKE, RAS_N, CAS_N, WE_N);

parameter ASIZE = 23;

parameter DSIZE = 32;

parameter ROWSIZE = 12;

parameter COLSIZE = 9;

parameter BANKSIZE = 2;

parameter ROWSTART = 9;

parameter COLSTART = 0;

parameter BANKSTART = 20;

input CLK;

input RESET_N;

input[ASIZE - 1:0] SADDR;

input NOP;

input READA;

input WRITEA;

input REFRESH;

input PRECHARGE;

input LOAD_MODE;

input[1:0] SC_CL;

input[1:0] SC_RC;

input[3:0] SC_RRD;

input SC_PM;

input[3:0] SC_BL;

input REF_REQ;

output REF_ACK;

wire REF_ACK;

output CM_ACK;

wire CM_ACK;

output OE;

reg OE;

output[11:0] SA;

wire[11:0] SA;

output[1:0] BA;

wire[1:0] BA;

output[1:0] CS_N;

wire[1:0] CS_N;

output CKE;

wire CKE;

output RAS_N;

wire RAS_N;

output CAS_N;

wire CAS_N;

output WE_N;

wire WE_N;

reg do_nop;

reg do_reada;

reg do_writea;

reg do_writea1;

reg do_refresh;

reg do_precharge;

reg do_load_mode;

reg command_done;

reg[7:0] command_delay;

wire[3:0] rw_shift;

wire do_act;

reg rw_flag;

wire do_rw;

reg[7:0] oe_shift;

reg oe1;

reg oe2;

reg oe3;

reg oe4;

reg[3:0] rp_shift;

reg rp_done;

wire[ROWSIZE - 1:0] rowaddr;

wire[COLSIZE - 1:0] coladdr;

wire[BANKSIZE - 1:0] bankaddr;

wire REF_REQ_int;

assign rowaddr = SADDR[ROWSTART + ROWSIZE - 1:ROWSTART] ; assign coladdr = SADDR[COLSTART + COLSIZE - 1:COLSTART] ; assign bankaddr = SADDR[BANKSTART + BANKSIZE - 1:BANKSTART] ;

always @(posedge CLK or negedge RESET_N)

begin

if (RESET_N == 1'b0)

begin

do_nop <= 1'b0 ;

do_reada <= 1'b0 ;

do_writea <= 1'b0 ;

do_refresh <= 1'b0 ;

do_precharge <= 1'b0 ;

do_load_mode <= 1'b0 ;

command_done <= 1'b0 ;

command_delay <= {8{1'b0}} ;

rw_flag <= 1'b0 ;

rp_shift <= {4{1'b0}} ;

rp_done <= 1'b0 ;

do_writea1 <= 1'b0 ;

end

else

begin

if ((REF_REQ == 1'b1 | REFRESH == 1'b1) & command_done == 1'b0 & do_refresh == 1'b0 & rp_done == 1'b0 & do_reada == 1'b0 & do_writea == 1'b0)

begin

do_refresh <= 1'b1 ;

end

else

begin

do_refresh <= 1'b0 ;

end

if ((READA == 1'b1) & (command_done == 1'b0) & (do_writea == 1'b0) & (rp_done == 1'b0) & (REF_REQ == 1'b0))

begin

do_reada <= 1'b1 ;

end

else

begin

do_reada <= 1'b0 ;

end

if ((WRITEA == 1'b1) & (command_done == 1'b0) & (do_writea == 1'b0) & (rp_done == 1'b0) & (REF_REQ == 1'b0))

begin

do_writea <= 1'b1 ;

do_writea1 <= 1'b1 ;

end

else

begin

do_writea <= 1'b0 ;

do_writea1 <= 1'b0 ;

end

if ((PRECHARGE == 1'b1) & (command_done == 1'b0) & (do_writea == 1'b0) & (do_precharge == 1'b0))

begin

do_precharge <= 1'b1 ;

end

else

begin

do_precharge <= 1'b0 ;

end

if ((LOAD_MODE == 1'b1) & (command_done == 1'b0) & (do_load_mode == 1'b0))

begin

do_load_mode <= 1'b1 ;

end

else

begin

do_load_mode <= 1'b0 ;

end

if ((do_refresh == 1'b1) | (do_reada == 1'b1) | (do_writea == 1'b1) | (do_precharge == 1'b1) | (do_load_mode == 1'b1))

begin

command_delay <= 11111111 ;

command_done <= 1'b1 ;

rw_flag <= do_reada ;

end

else

begin

command_done <= command_delay[0] ;

command_delay[6:0] <= command_delay[7:1] ;

command_delay[7] <= 1'b0 ;

end

if ((command_delay[0]) == 1'b0 & command_done == 1'b1)

begin

rp_shift <= 1111 ;

rp_done <= 1'b1 ;

end

else

begin

rp_done <= rp_shift[0] ;

rp_shift[2:0] <= rp_shift[3:1] ;

rp_shift[3] <= 1'b0 ;

end

end

end

always @(posedge CLK or negedge RESET_N)

begin

if (RESET_N == 1'b0)

begin

oe_shift <= {8{1'b0}} ;

oe1 <= 1'b0 ;

oe2 <= 1'b0 ;

oe3 <= 1'b0 ;

oe4 <= 1'b0 ;

OE <= 1'b0 ;

end

else

begin

if (SC_PM == 1'b0)

begin

if (do_writea1 == 1'b1)

begin

if (SC_BL == 0001)

begin

oe_shift <= {8{1'b0}} ;

end

else if (SC_BL == 0010)

begin

oe_shift <= 00000001 ;

end

else if (SC_BL == 0100)

begin

oe_shift <= 00000111 ;

end

else if (SC_BL == 1000)

begin

oe_shift <= 01111111 ;

end

oe1 <= 1'b1 ;

end

else

begin

oe_shift[6:0] <= oe_shift[7:1] ;

oe_shift[7] <= 1'b0 ;

oe1 <= oe_shift[0] ;

oe2 <= oe1 ;

oe3 <= oe2 ;

oe4 <= oe3 ;

if (SC_RC == 2'b10)

begin

OE <= oe3 ;

end

else

begin

OE <= oe4 ;

end

end

end

else

begin

if (do_writea1 == 1'b1)

begin

oe4 <= 1'b1 ;

end

else if (do_precharge == 1'b1 | do_reada == 1'b1 | do_refresh == 1'b1)

begin

oe4 <= 1'b0 ;

end

OE <= oe4 ;

end

end

end

endmodule

附件3:

module sdr_data_path (CLK, RESET_N, OE, DA TAIN, DM, DATAOUT, DQIN, DQOUT, DQM);

parameter DSIZE = 32;

input CLK;

input RESET_N;

input OE;

input[DSIZE - 1:0] DA TAIN;

input[DSIZE / 8 - 1:0] DM;

output[DSIZE - 1:0] DA TAOUT;

wire[DSIZE - 1:0] DA TAOUT;

input[DSIZE - 1:0] DQIN;

output[DSIZE - 1:0] DQOUT;

wire[DSIZE - 1:0] DQOUT;

output[DSIZE / 8 - 1:0] DQM;

reg[DSIZE / 8 - 1:0] DQM;

reg[DSIZE - 1:0] DIN1;

reg[DSIZE - 1:0] DIN2;

reg[DSIZE / 8 - 1:0] DM1;

always @(posedge CLK or negedge RESET_N)

begin

if (RESET_N == 1'b0)

begin

DIN1 <= {DSIZE - 1-(0)+1{1'b0}} ;

DIN2 <= {DSIZE - 1-(0)+1{1'b0}} ;

DM1 <= {DSIZE / 8 - 1-(0)+1{1'b0}} ;

end

else

begin

DIN1 <= DA TAIN ;

DIN2 <= DIN1 ;

DM1 <= DM ;

DQM <= DM1 ;

end

end

assign DA TAOUT = DQIN ;

assign DQOUT = DIN2 ;

endmodule

附件4:

module sdr_sdram (CLK, RESET_N, ADDR, CMD, CMDACK, DATAIN, DATAINOUT, DM, SA, BA, CS_N, CKE, RAS_N, CAS_N, WE_N, DQ, DQM);

parameter ASIZE = 23;

parameter DSIZE = 32;

parameter ROWSIZE = 12;

parameter COLSIZE = 9;

parameter BANKSIZE = 2;

parameter ROWSTART = 9;

parameter COLSTART = 0;

parameter BANKSTART = 20;

input CLK;

input RESET_N;

input[ASIZE - 1:0] ADDR;

input[2:0] CMD;

output CMDACK;

wire CMDACK;

input[DSIZE - 1:0] DA TAIN;

output[DSIZE - 1:0] DA TAINOUT;

wire[DSIZE - 1:0] DA TAINOUT;

input[DSIZE / 8 - 1:0] DM;

output[11:0] SA;

reg[11:0] SA;

output[1:0] BA;

reg[1:0] BA;

output[1:0] CS_N;

reg[1:0] CS_N;

output CKE;

reg CKE;

output RAS_N;

reg RAS_N;

output CAS_N;

reg CAS_N;

output WE_N;

reg WE_N;

inout[DSIZE - 1:0] DQ;

wire[DSIZE - 1:0] DQ;

wire[DSIZE - 1:0] DQ_xhdl0;

output[DSIZE / 8 - 1:0] DQM;

wire[DSIZE / 8 - 1:0] DQM;

// <> Unsupported Construct - attribute (source line 115) // <> Unsupported Construct - attribute (source line 124)) wire[11:0] ISA;

wire[1:0] IBA;

wire[1:0] ICS_N;

wire ICKE;

wire IRAS_N;

wire ICAS_N;

wire IWE_N;

reg[DSIZE - 1:0] DQIN;

wire[DSIZE - 1:0] IDA TAOUT;

wire[DSIZE - 1:0] DQOUT;

wire[ASIZE - 1:0] saddr;

wire[1:0] sc_cl;

wire[1:0] sc_rc;

wire[3:0] sc_rrd;

wire sc_pm;

wire[3:0] sc_bl;

wire load_mode;

wire nop;

wire reada;

wire writea;

wire refresh;

wire precharge;

wire oe;

wire ref_req;

wire ref_ack;

wire cm_ack;

wire CLK133;

wire CLK133B;

wire clklocked;

assign DQ = DQ_xhdl0;

control_interface #(ASIZE)

control1(

.CLK(CLK133), .RESET_N(RESET_N), .CMD(CMD), .ADDR(ADDR),

.REF_ACK(ref_ack), .CM_ACK(cm_ack), .NOP(nop), .READA(reada), .WRITE A(writea),

.REFRESH(refresh), .precharge(precharge), .LOAD_MODE(load_mode), .SADDR(saddr),

.SC_CL(sc_cl), .SC_RC(sc_rc), .SC_RRD(sc_rrd), .SC_PM(sc_pm), .SC_BL(sc_bl),

.REF_REQ(ref_req), .CMD_ACK(CMDACK)

);

command #(ASIZE, DSIZE, ROWSIZE, COLSIZE, BANKSIZE, COLSTART, BANKSTART)//重新定义模块里的常量声明

command1(

.CLK(CLK133), .RESET_N(RESET_N), .SADDR(saddr), .NOP(nop), .READA(reada),

.WRITEA(writea), .REFRESH(refresh), .PRECHARGE(precharge), .LOAD_MODE(load_mode),

.SC_CL(sc_cl), .SC_RC(sc_rc), .SC_RRD(sc_rrd), .SC_PM(sc_pm), .SC_BL(sc_bl),

.REF_REQ(ref_req), .REF_ACK(ref_ack), .CM_ACK(cm_ack), .OE(oe), .SA(ISA), .BA(IBA),

.CS_N(ICS_N), .CKE(ICKE), .RAS_N(IRAS_N), .CAS_N(ICAS_N), .WE_N(IWE_N)

);

sdr_data_path #(DSIZE)

data_path1(

.CLK(CLK133), .RESET_N(RESET_N), .OE(oe), .DATAIN(DATAIN), .DM(DM),

.DA TAOUT(IDATAOUT), .DQM(DQM), .DQIN(DQIN), .DQOUT(DQOUT)

);

// <> Can't find translated component 'pll1'. Port and module names may not match

//pll u1(.clk(CLK), .locked(clklocked), .clock(CLK133),.reset(RESET_N));

always @(posedge CLK133)

begin

SA <= ISA ;

BA <= IBA ;

CS_N <= ICS_N ;

CKE <= ICKE ;

RAS_N <= IRAS_N ;

CAS_N <= ICAS_N ;

WE_N <= IWE_N ;

DQIN <= DQ ;

DA TAINOUT <= IDATAOUT ; // end

assign DQ = (oe == 1'b1) ? DQOUT : {0{1'bz}} ; endmodule

VerilogHDL经典程序非常适合新手

一、2线-4线译码器 module counter4(q1,q0,ncr,cp); input cp,ncr; output q1,q0; reg q1,q0; always@(posedge cp or negedge ncr) begin if(~ncr){q1,q0}<=2'b00; else{q1,q0}<={q1,q0}+1'b1; end endmodule 二、4选1数据选择器 module selector4_1(i0,i1,i2,i3,a1,a0,y); input i0,i1,i2,i3,a1,a0; output y; reg y; always@(a1or a0) begin case({a1,a0}) 2'b00:y=i0; 2'b01:y=i1; 2'b10:y=i2; 2'b11:y=i3; default:y=0; 一、2线-4线译码器 module counter4(q1,q0,ncr,cp); input cp,ncr; output q1,q0; reg q1,q0; always@(posedge cp or negedge ncr) begin if(~ncr){q1,q0}<=2'b00; else{q1,q0}<={q1,q0}+1'b1; end endmodule 二、4选1数据选择器 module selector4_1(i0,i1,i2,i3,a1,a0,y); input i0,i1,i2,i3,a1,a0; output y; reg y; always@(a1or a0) begin case({a1,a0}) 2'b00:y=i0;

基于FPGA的Verilog HDL数字钟设计 -

基于FPGA的Verilog HDL数字钟设计 专业班级姓名学号 一、实验目的 1.掌握可编程逻辑器件的应用开发技术——设计输入、编译、仿真和器件编程; 2.熟悉一种EDA软件使用; 3.掌握Verilog设计方法; 4.掌握分模块分层次的设计方法; 5.用Verilog完成一个多功能数字钟设计; 6.学会FPGA的仿真。 二、实验要求 ?功能要求: 利用实验板设计实现一个能显示时分秒的多功能电子钟,基本功能: 1)准确计时,以数字形式显示时、分、秒,可通过按键选择当前显示时间范围模式; 2)计时时间范围00:00:00-23:59:59 3)可实现校正时间功能; 4)可通过实现时钟复位功能:00:00:00 扩展功能: 5)定时报:时间自定(不要求改变),闹1分钟(1kHz)---利用板上LED或外接电路实现。 6)仿广播电台正点报时:XX:59:[51,53,55,57(500Hz);59(1kHz)] ---用板上LED或外接 7)报整点时数:XX:00:[00.5-XX.5](1kHz),自动、手动---用板上LED或外接 8)手动输入校时; 9)手动输入定时闹钟; 10)万年历; 11)其他扩展功能; ?设计步骤与要求: 1)计算并说明采用Basys2实验板时钟50MHz实现系统功能的基本原理。 2)在Xilinx ISE13.1 软件中,利用层次化方法,设计实现模一百计数及显示的电路系 统,设计模块间的连接调用关系,编写并输入所设计的源程序文件。 3)对源程序进行编译及仿真分析(注意合理设置,以便能够在验证逻辑的基础上尽快 得出仿真结果)。 4)输入管脚约束文件,对设计项目进行编译与逻辑综合,生成下载所需.bit文件。 5)在Basys2实验板上下载所生成的.bit文件,观察验证所设计的电路功能。

智造工坊verilog代码规范

Verilog 代码规范 陈永/Jon chen 2015.12.16

FPGA项目规范体系 智造工坊FPGA项目的执行需要严格按照完整的规范体系完成,代码规范只是一个组成部分。 智造工坊FPGA项目规范 流程规范工 程 规 范 文 档 规 范 代 码 规 范 实 现 规 范 仿 真 规 范 测 试 规 范 验 收 规 范 维 护 规 范

代码规范声明 本课程所述的Verilog代码规范是根据本公司近20年来数百个FPGA项目经验总结出的规范,旨在提高内部工程师工作效率和工作质量。 不同公司根据自身的业务类型和管理理念,具有不同的代码风格和代码规范。本课程仅阐述本公司的代码规范,供初学者参考学习。本课程如有不合理之处或对课程中的规范有更好的建议,请及时提出,一经确认采纳,定有重谢! 联系方式: 邮箱:Jonchen@https://www.360docs.net/doc/c016780049.html, QQ : 517343565

Verilog 代码规范作用 增加代码可读性,复用性,统一性,维护性 提升编码效率,降低语法出错率和逻辑出错率 提高代码实现效率,优化FPGA 逻辑资源,提高设计可靠性和稳定性 初级规范 中级规范 高级规范 (外在形式,基本规范,风格统一即可) (基本保障,建议统一执行) (经验总结,建议在项目中体会)

初级规范 文件名与模块名定义文件头 注释 模块内部结构 端口定义 参数定义 信号定义对齐方式缩进方式模块例化顶层要求

初级(文件名,模块名) 文件名,模块名 1)文件名和模块名保持一致 2)文件以小写.v为后缀名 3)文件名和模块名由小写字母a-z,数字0-9,下划线组成 4)文件名和模块名长度不超过16个字符 5)文件名和模块名中的几个词组以下划线隔开 6)文件名和模块名要有一定含义,和模块功能保持一致 7) Altera公司的Ipcore以ALT开头,Xilinx芯片的Ipcore以XIL开头(一个项目多家芯片) 8)时钟复位控制模块统一用clk_rst,寄存器模块统一用reg_ctrl 9)单芯片项目FPGA顶层模块名统一用fpga_top 10)多板卡多芯片项目FPGA顶层模块名用xx_fpgan_top命名(xx:板卡名,n:FPGA编号)

Verilog编码风格

Verilog编码风格 嵌入式开发2010-05-03 15:28:13 阅读14 评论0 字号:大中小订阅 这是以前公司的对fpga代码编写的要求 良好代码编写风格的通则概括如下: (1)对所有的信号名、变量名和端口名都用小写,这样做是为了和业界的习惯保持一致;对常量名和用户定义的类型用大写; (2)使用有意义的信号名、端口名、函数名和参数名; (3)信号名长度不要太长; (4)对于时钟信号使用clk 作为信号名,如果设计中存在多个时钟,使用clk 作为时钟信号的前缀; (5)对来自同一驱动源的信号在不同的子模块中采用相同的名字,这要求在芯片总体设计时就定义好顶层子模块间连线的名字,端口和连接端口的信号尽可能采用相同的名字; (6)对于低电平有效的信号,应该以一个下划线跟一个小写字母b 或n 表示。注意在同一个设计中要使用同一个小写字母表示低电平有效; (7)对于复位信号使用rst 作为信号名,如果复位信号是低电平有效,建议使用rst_n; (8)当描述多比特总线时,使用一致的定义顺序,对于verilog 建议采用bus_signal[x:0]的表示; (9)尽量遵循业界已经习惯的一些约定。如*_r 表示寄存器输出,*_a 表示异步信号,*_pn 表示多周期路径第n 个周期使用的信号,*_nxt 表示锁存前的信号,*_z 表示三态信号等; (10)在源文件、批处理文件的开始应该包含一个文件头、文件头一般包含的内容如下例所示:文件名,作者,模块的实现功能概述和关键特性描述,文件创建和修改的记录,包括修改时间,修改的内容等; (11)使用适当的注释来解释所有的always 进程、函数、端口定义、信号含义、变量含义或信号组、变量组的意义等。注释应该放在它所注释的代码附近,要求简明扼要,只要足够说明设计意图即可,避免过于复杂; (12)每一行语句独立成行。尽管VHDL 和Verilog 都允许一行可以写多个语句,当时每个语句独立成行可以增加可读性和可维护性。同时保持每行小于或等于72 个字符,这样做都是为了提高代码得可读性; (13)建议采用缩进提高续行和嵌套语句得可读性。缩进一般采用两个空格,如西安交通大学SOC 设计中心 2 如果空格太多则在深层嵌套时限制行长。同时缩进避免使用TAB 键,这样可以避免不同机器TAB 键得设置不同限制代码得可移植能力; (14)在RTL 源码的设计中任何元素包括端口、信号、变量、函数、任务、模块等的命名都不能取Verilog 和VHDL 语言的关键字; (15)在进行模块的端口申明时,每行只申明一个端口,并建议采用以下顺序:

(免费)[VHDL+Verilog]良好的代码编写风格(二十五条)

[VHDL+Verilog]良好的代码编写风格(二十五条) 良好代码编写风格可以满足信、达、雅的要求。在满足功能和性能目标的前提下,增强代码的可读性、可移植性,首要的工作是在项目开发之前为整个设计团队建立一个命名约定和缩略语清单,以文档的形式记录下来,并要求每位设计人员在代码编写过程中都要严格遵守。良好代码编写风格的通则概括如下: (1)对所有的信号名、变量名和端口名都用小写,这样做是为了和业界的习惯保持一致;对常量名和用户定义的类型用大写; (2)使用有意义的信号名、端口名、函数名和参数名; (3)信号名长度不要太长; (4)对于时钟信号使用clk 作为信号名,如果设计中存在多个时钟,使用clk 作为时钟信号的前缀; (5)对来自同一驱动源的信号在不同的子模块中采用相同的名字,这要求在芯片总体设计时就定义好顶层子模块间连线的名字,端口和连接端口的信号尽可能采用相同的名字; (6)对于低电平有效的信号,应该以一个下划线跟一个小写字母b 或n 表示。注意在同一个设计中要使用同一个小写字母表示低电平有效; (7)对于复位信号使用rst 作为信号名,如果复位信号是低电平有效,建议使用rst_n; (8)当描述多比特总线时,使用一致的定义顺序,对于verilog 建议采用bus_signal[x:0]的表示; (9)尽量遵循业界已经习惯的一些约定。如*_r 表示寄存器输出,*_a 表示异步信号,*_pn 表示多周期路径第n 个周期使用的信号,*_nxt 表示锁存前的信号,*_z 表示三态信号等; (10)在源文件、批处理文件的开始应该包含一个文件头、文件头一般包含的内容如下例所示:文件名,作者,模块的实现功能概述和关键特性描述,文件创建和修改的记录,包括修改时间,修改的内容等; (11)使用适当的注释来解释所有的always 进程、函数、端口定义、信号含义、变量含义或信号组、变量组的意义等。注释应该放在它所注释的代码附近,要求简明扼要,只要足够说明设计意图即可,避免过于复杂; (12)每一行语句独立成行。尽管VHDL 和V erilog 都允许一行可以写多个语句,当时每个语句独立成行可以增加可读性和可维护性。同时保持每行小于或等于72 个字符,这样做都是为了提高代码得可读性;

74LS138Verilog源码

`timescale 1ns / 1ps ////////////////////////////////////////////////////////////////////////////////// // Company: // Engineer: // // Create Date: 2020/02/28 13:40:03 // Design Name: // Module Name: _74ls138 // Project Name: // Target Devices: // Tool Versions: // Description: // // Dependencies: // // Revision: // Revision 0.01 - File Created // Additional Comments: // ////////////////////////////////////////////////////////////////////////////////// module _74ls138(nE1,nE2,E3,B,nY); input nE1,nE2,E3; input [2:0]B; output[7:0]nY; reg[7:0]nY; always@(nE1,nE2,E3,B) if(!nE1 && !nE2 && E3) begin case(B) 3'b000: nY = 8'b1111_1110; 3'b001: nY = 8'b1111_1101; 3'b010: nY = 8'b1111_1011; 3'b011: nY = 8'b1111_0111; 3'b100: nY = 8'b1110_1111; 3'b101: nY = 8'b1101_1111; 3'b110: nY = 8'b1011_1111; 3'b111: nY = 8'b0111_1111; default:nY = 8'b1111_1111; endcase end

(完整版)Verilog实现的基于FPGA的五层楼电梯运行控制逻辑毕业设计论文

五层楼电梯运行控制逻辑设计 摘要:电梯是高层建筑不可缺少的运输工具,用于垂直运送乘客和货物,传统的电梯控制系统主要采用继电器,接触器进行控制,其缺点是触点多,故障率高、可靠性差、维修工作量大等,本设计根据电梯自动控制的要求利用Verilog语言编写并完成系统设计,在利用软件仿真之后,下载到了FPGA上进行硬件仿真。FPGA(Field-Programmable Gate Array),即现场可编程门阵列,它是在PAL、GAL、CPLD等可编程器件的基础上进一步发展的产物。它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了之前的可编程器件门电路数有限及速度上的缺点。 关键词:电梯控制FPGA Verilog软件设计硬件设计 在当今社会,随着城市建设的不断发展,高层建筑的不断增多,电梯作为高层建筑中垂直运行的交通工具已与人们的日常生活密不可分。目前电梯控制系统主要有三种控制方式:继电路控制系统(早期安装的电梯多位继电器控制系统),FPGACPLD [1] 的控制系统、微机控制系统。继电器控制系统由于故障率高、可靠性差、控制方式不灵活以及消耗功率大等缺点,目前已逐渐被淘汰,而微机控制系统虽在智能控制方面有较强的功能,但也存在抗扰性差,系统设计复杂,一般维修人员难以掌握其维修技术等缺陷。而FPGACPLD控制系统由于运行可靠性高,使用维修方便,抗干扰性强,设计和调试周期较短等优点 [2] ,倍受人们重视等优点,已经成为目前在电梯控制系统中使用最多的控制方式,目前也广泛用于传

统继电器控制系统的技术改造。 随着现代化城市的高度发展,每天都有大量人流及物流需要输送,因此在实际工程应用中电梯的性能指标相当重要,主要体现在:可靠性,安全性,便捷快速性。电梯的可靠性非常重要,直接或间接的影响着人们的生产,生活,而电梯的故障主要表现在电力拖动控制系统中,因此要提高可靠性也要从电力拖动控制系统入手。 本次设计尝试用Verilog实现电梯控制器部分,进行了多层次的电梯控制,也进行了软件及硬件上的仿真验证,时序分析以保证设计的正确。在设计中先用软件进行模拟仿真,然后又下载到FPGA开发板上进行硬件仿真,以确保设计的正确性。 1电梯的设计分析 1.1 系统的需求分析及系统描述 设计一个电梯运行控器,该电梯有5层楼,设计的电梯调度算法满足提高服务质量、降低运行成本的原则;电梯的内部有一个控制面板,它负责按下请求到的楼层,并且显示当前尚未完成的目的地请求,当到达该楼层以后自动撤销本楼层的请求,即将面板灯熄灭;除1层和5层分别只有上和下按钮外,其余每个楼层(电梯门口旁)的召唤面板都有两个按钮,分别指示上楼和下楼请求。当按下后,对应按钮灯亮。如果电梯已经到达该楼层,按钮灯熄灭;电梯的外部面板会显示电梯当前所在的楼层,及上行还是下行(暂停显示刚才运行时的状态);电梯向一个方向运行时,只对本方向前方的请求进行应答,直到本方向前方无请求时,才对反方向的请求进行应答。当前内部控制面板上有的请求,只要经过所在楼层均会立即响应.

Verilog试题 A答案

北京航空航天大学 2011 ~2012 学年第二学期 数字EDA 期末考试试卷 ( 2012 年 5 月 23 日) 班级:__________;学号:______________;姓名:__________________;成绩:___________ 注意事项:1、填空题与选择题直接在试题上作答 2、设计题在答题纸上作答 正题: 一、填空题(共30分,每道题3分) 1. 写出表达式以实现对应电路的逻辑功能。 F 2. 根据图中输入输出关系将Verilog 模块定义补充完整,其中信号A 为5比特宽度,其余信号为1比特宽度。 A 宽 3. IEEE 标准的硬件描述语言是 verilog HDL 和 VHDL 。 4. 你所知道的可编程逻辑器件有(至少两种): FPGA, CPLD, GAL, PAL (任写其二) 。 5. 假定某4比特位宽的变量a 的值为4’b1011,计算下列运算表达式的结果 6. Verilog 语言规定了逻辑电路中信号的4种状态,分别是0,1,X 和Z 。其中0表示低电平状态,1表示高电平状态,X 表示 不定态(或未知状态) ,Z 表示 高阻态 。 assign F= E ^ ( (A&B) | (!(C&D))) module tblock( A,B,C ) ; output [4:0] A; input B; inout C; …… //省略了功能描述 endmodule //模块结束 &a = 1’b0 ~a = 4’b0100 {3{a}} = 12’b101110111011 {a[2:0],a[3]} = 4’b0111 (a<4’d3) || (a>=a) = 1’b1 !a = 1’b0

全数字锁相环的verilog源代码讲解

支持论坛发展帖出全数字锁相环的verilog源代码,仿真已通过 module dpll(reset,clk,signal_in,signal_out,syn; parameter para_K=4; parameter para_N=16; input reset; input clk; input signal_in; output signal_out; output syn; reg signal_out; reg dpout; reg delclk; reg addclk; reg add_del_clkout; reg [7:0]up_down_cnt; reg [2:0]cnt8; reg [8:0]cnt_N; reg syn; reg dpout_delay; reg [8:0]cnt_dpout_high; reg [8:0]cnt_dpout_low; /******phase detector*****/ always@(signal_in or signal_out begin dpout<=signal_in^signal_out; end /******synchronization establish detector*****/ always@(posedge clk or negedge reset begin if(!reset dpout_delay<='b0; else dpout_delay<=dpout; end always@(posedge clk or negedge reset begin if(!reset begin cnt_dpout_high<='b0; cnt_dpout_low<='b0; end else if(dpout if(dpout_delay==0 cnt_dpout_high<='b0; else if(cnt_dpout_high==8'b11111111 cnt_dpout_high<='b0; else cnt_dpout_high<=cnt_dpout_high+1; else if(!dpout if(dpout_delay==1 cnt_dpout_low<='b0; else if(cnt_dpout_low==8'b11111111 cnt_dpout_low<='b0; else cnt_dpout_low<=cnt_dpout_low+1; end always@(posedge clk or negedge reset begin if(!reset syn<='b0; else if((dpout&&!dpout_delay||(!dpout&&dpout_delay if(cnt_dpout_high[8:0]-cnt_dpout_low[8:0]<=4||cnt_dpout_low[8:0]- cnt_dpout_high[8:0]<=4 syn<='b1; else syn<='b0; end /****up down couter with mod=K****/ always@(posedge clk or negedge reset begin if(!reset begin delclk<='b0; addclk<='b0; up_down_cnt<='b00000000; end else begin if(!dpout begin delclk<='b0; if(up_down_cnt==para_K-1 begin up_down_cnt<='b00000000; addclk<='b0; end else begin up_down_cnt<=up_down_cnt+1; addclk<='b0; end end else begin addclk<='b0; if(up_down_cnt=='b0 begin up_down_cnt<=para_K-1; delclk<='b0; end else if(up_down_cnt==1 begin delclk<='b1; up_down_cnt<=up_down_cnt-1; end else up_down_cnt<=up_down_cnt-1; end end end /******add and delete clk*****/ always@(posedge clk or negedge reset begin if(!reset begin cnt8<='b000; end else begin if(cnt8=='b111 begin cnt8<='b000; end else if(addclk&&!syn begin cnt8<=cnt8+2; end else if(delclk&&!syn

基于FPGA的verilog的电子密码锁设计

一、概述 1.1 电子密码锁的现状 随着我国对外开放的不断深入,高档建筑发展很快,高档密码锁具市场的前景乐观。我国密码锁具行业对密码锁具高新技术的投入正逐年增大,高档密码锁的市场需求也逐年增加。在安防工程中,锁具产品是关系到整个系统安全性的重要设备,所以锁具产品的优劣也关系了整个安防工程的质量和验收。 目前,市场上比较先进的智能电子密码锁分别有:IC卡电子密码锁、射频卡式电子密码锁、红外遥控电子密码锁、指纹识别电子密码锁和瞳孔识别电子密码锁等。IC卡电子密码锁成本低,体积小,卡片本身无须电源等优点占领了一定的市场份额,但是由于有机械接触,会产生接触磨损,而且使用不太方便,在一定程度上限制了它的应用;射频卡式电子密码锁是非接触式电子密码锁,成本也不太高,体积跟IC卡密码锁相当,卡片使用感应电源,重量很轻,技术成熟,受到了广泛的欢迎,但是与IC卡电子密码锁相比,成本偏高;指纹识别电子密码锁和瞳孔识别电子密码锁可靠性很高,安全性是目前应用系统中最高的,但是成本高昂,还没进入大众化使用阶段。 在国外,美国、日本、德国的电子密码锁保密性较好,并结合感应卡技术,生物识别技术,使电子密码锁系统得到了飞跃式的发展。这几个国家的密码锁识别的密码更复杂,并且综合性比较好,已经进入了成熟期,出现了感应卡式密码锁,指纹式密码锁,虹膜密码锁,面部识别密码锁,序列混乱的键盘密码锁等各种技术的系统,它们在安全性,方便性,易管理性等方面都各有特长,新型的电子密码锁系统的应用也越来越广。 基于FPGA的电子密码锁是新型现代化安全管理系统,它集微机自动识别技术和现代安全管理措施为一体,它涉及电子,机械,计算机技术,通讯技术,生物技术等诸多新技术。它是解决重要部门出入口实现安全防范管理的有效措施,适用各种场合,如银行、宾馆、机房、军械库、机要室、办公间、智能化小区、工厂、家庭等。 在数字技术网络技术飞速发展的今天,电子密码锁技术得到了迅猛的发展。它早已超越了单纯的门道及钥匙管理,逐渐发展成为一套完整的出入管理系统。它在工作环境安全、人事考勤管理等行政管理工作中发挥着巨大的作用。在该系统的基础上增加相应的辅助设备可以进行电梯控制、车辆进出控制,物业消防监控、餐饮收费、私家车库管理等,真正实现区域内一卡智能管理。

verilog有限状态机实验报告(附源代码)

有限状态机实验报告 一、实验目的 ●进一步学习时序逻辑电路 ●了解有限状态机的工作原理 ●学会使用“三段式”有限状态机设计电路 ●掌握按键去抖动、信号取边沿等处理技巧 二、实验内容 用三段式有限状态机实现序列检测功能电路 a)按从高位到低位逐位串行输入一个序列,输入用拨动开关实现。 b)每当检测到序列“1101”(不重叠)时,LED指示灯亮,否则灭,例如 i.输入:1 1 0 1 1 0 1 1 0 1 ii.输出:0 0 0 1 0 0 0 0 0 1 c)用八段数码管显示最后输入的四个数,每输入一个数,数码管变化一次 d)按键按下的瞬间将拨动开关状态锁存 i.注意防抖动(按键按下瞬间可能会有多次的电平跳变) 三、实验结果 1.Rst_n为0时数码管显示0000,led灯不亮,rst_n拨为1,可以开始输入,将输 入的开关拨到1,按下按钮,数码管示数变为0001,之后一次类推分别输入1, 0,1,按下按钮后,数码管为1101,LED灯亮,再输入1,LED灯灭,之后再输 入0,1(即共输入1101101使1101重叠,第二次LED灯不亮),之后单独输入

1101,LED灯亮 2.仿真图像 刚启动时使用rst_n 一段时间后 其中Y代表输出,即控制led灯的信号,sel表示数码管的选择信号,seg表示数码管信号 四、实验分析 1、实验基本结构

其中状态机部分使用三段式结构: 2、整体结构为:

建立一下模块: Anti_dither.v 输入按键信号和时钟信号,输出去除抖动的按键信号生成的脉冲信号op 这一模块实现思路是利用按钮按下时会持续10ms以上而上下抖动时接触时间不超过10ms来给向下接触的时间计时,达到上限时间才产生输出。 Num.v 输入op和序列输入信号A,时钟信号clk和复位信号,复位信号将num置零,否则若收到脉冲信号则将num左移一位并将输入存进最后一位。输出的num即为即将在数码管上显示的值 Scan.v 输入时钟信号,对其降频以产生1ms一次的扫描信号。 Trigger.v 这一模块即为状态机模块,按三段式书写。 整个模块的输入为时钟信号,脉冲信号,序列输入变量,复位信号,输出LED灯控制信号Y。 第一段是状态转换模块,为时序逻辑电路,功能是描述次态寄存器迁移到现态寄存器。即如果收到复位信号将现态置零,否则将上次得到的next_state赋给current_state。

基于FPGA的VerilogHDL数字钟设计

基于FPGA的Verilog-HDL数字钟设计--

————————————————————————————————作者:————————————————————————————————日期:

基于FPGA的Verilog HDL数字钟设计 专业班级姓名学号 一、实验目的 1.掌握可编程逻辑器件的应用开发技术——设计输入、编译、仿真和器件编程; 2.熟悉一种EDA软件使用; 3.掌握Verilog设计方法; 4.掌握分模块分层次的设计方法; 5.用Verilog完成一个多功能数字钟设计; 6.学会FPGA的仿真。 二、实验要求 功能要求: 利用实验板设计实现一个能显示时分秒的多功能电子钟,基本功能: 1)准确计时,以数字形式显示时、分、秒,可通过按键选择当前显示时间范围模式; 2)计时时间范围00:00:00-23:59:59 3)可实现校正时间功能; 4)可通过实现时钟复位功能:00:00:00 扩展功能: 5)定时报:时间自定(不要求改变),闹1分钟(1kHz)---利用板上LED或外接电路实现。 6)仿广播电台正点报时:XX:59:[51,53,55,57(500Hz);59(1kHz)] ---用板上LED或外接 7)报整点时数:XX:00:[00.5-XX.5](1kHz),自动、手动---用板上LED或外接

8)手动输入校时; 9)手动输入定时闹钟; 10)万年历; 11)其他扩展功能; 设计步骤与要求: 1)计算并说明采用Basys2实验板时钟50MHz实现系统功能的基本原理。 2)在Xilinx ISE13.1 软件中,利用层次化方法,设计实现模一百计数及显示的电路系 统,设计模块间的连接调用关系,编写并输入所设计的源程序文件。 3)对源程序进行编译及仿真分析(注意合理设置,以便能够在验证逻辑的基础上尽快 得出仿真结果)。 4)输入管脚约束文件,对设计项目进行编译与逻辑综合,生成下载所需.bit文件。 5)在Basys2实验板上下载所生成的.bit文件,观察验证所设计的电路功能。 三、实验设计 功能说明:实现时钟,时间校时,闹铃定时,秒表计时等功能 1.时钟功能:完成分钟/小时的正确计数并显示;秒的显示用LED灯的闪烁做指示; 时钟利用4位数码管显示时分; 2.闹钟定时:实现定时提醒及定时报时,利用LED灯代替扬声器发出报时声音; 3.时钟校时:当认为时钟不准确时,可以分别对分钟和小时位的值进行调整; 4.秒表功能:利用4个数码管完成秒表显示:可以实现清零、暂停并记录时间等功能。 秒表利用4位数码管计数; 方案说明:本次设计由时钟模块和译码模块组成。时钟模块中50MHz的系统时钟clk分频产

Verilog的135个经典设计实例

【例3.1】4位全加器 module adder4(cout,sum,ina,inb,cin); output[3:0] sum; output cout; input[3:0] ina,inb; input cin; assign {cout,sum}=ina+inb+cin; endmodule 【例3.2】4位计数器 module count4(out,reset,clk); output[3:0] out; input reset,clk; reg[3:0] out; always @(posedge clk) begin if (reset) out<=0; //同步复位 else out<=out+1; //计数 end endmodule 【例3.3】4位全加器的仿真程序 `timescale 1ns/1ns `include "adder4.v" module adder_tp; //测试模块的名字 reg[3:0] a,b; //测试输入信号定义为reg型 reg cin; wire[3:0] sum; //测试输出信号定义为wire型 wire cout; integer i,j; adder4 adder(sum,cout,a,b,cin); //调用测试对象 always #5 cin=~cin; //设定cin的取值 initial begin a=0;b=0;cin=0; for(i=1;i<16;i=i+1) #10 a=i; //设定a的取值 end - 1 -

initial begin for(j=1;j<16;j=j+1) #10 b=j; //设定b的取值 end initial//定义结果显示格式 begin $monitor($time,,,"%d + %d + %b={%b,%d}",a,b,cin,cout,sum); #160 $finish; end endmodule 【例3.4】4位计数器的仿真程序 `timescale 1ns/1ns `include "count4.v" module coun4_tp; reg clk,reset; //测试输入信号定义为reg型 wire[3:0] out; //测试输出信号定义为wire型 parameter DELY=100; count4 mycount(out,reset,clk); //调用测试对象 always #(DELY/2) clk = ~clk; //产生时钟波形 initial begin//激励信号定义 clk =0; reset=0; #DELY reset=1; #DELY reset=0; #(DELY*20) $finish; end //定义结果显示格式 initial $monitor($time,,,"clk=%d reset=%d out=%d", clk, reset,out); endmodule 【例3.5】“与-或-非”门电路 module AOI(A,B,C,D,F); //模块名为AOI(端口列表A,B,C,D,F) input A,B,C,D; //模块的输入端口为A,B,C,D output F; //模块的输出端口为F - 2 -

第10章例题verilog源代码(夏宇闻版)

第十章例题 module add_4( X, Y, sum, C); input [3 : 0] X, Y; output [3: 0] sum; output C; assign {C, Sum } = X + Y; endmodule //而16位加法器只需要扩大位数即可,见下例: module add_16( X, Y, sum, C); input [15 : 0] X, Y; output [15 : 0] sum; output C; assign {C, Sum } = X + Y; endmodule 快速乘法器常采用网格形式的迭带阵列结构,图10.3示出两个四位二进制数相乘的结构图,//用Verilog HDL来描述乘法器是相当容易的,只需要把运算表达式写出就可以了,见下例。module mult_4( X, Y, Product); input [3 : 0] X, Y; output [7 : 0] Product; assign Product = X * Y; endmodule // 而8位乘法器只需要扩大位数即可,见下例: module mult_8( X, Y, Product); input [7 : 0] X, Y; output [15 : 0] Product; assign Product = X * Y; endmodule

// 下面就是一个位数可以由用户定义的比较电路模块: module compare_n ( X, Y, XGY, XSY, XEY); input [width-1:0] X, Y; output XGY, XSY, XEY; reg XGY, XSY, XEY; parameter width = 8; always @ ( X or Y ) // 每当X 或Y 变化时 begin if ( X = = Y ) XEY = 1; // 设置X 等于Y的信号为1 else XEY = 0; if (X > Y) XGY = 1; // 设置X 大于Y的信号为1 else XGY = 0; if (X < Y) XSY = 1; // 设置X 小于Y的信号为1 else XSY = 0; end endmodule //下面就是带使能控制信号(nCS)的数据位宽可以由用户定义的(8位)八路数据通道选择器模块: module Mux_8( addr,in1, in2, in3, in4, in5, in6, in7, in8, Mout, nCS); input [2:0] addr; input [width-1:0] in1, in2, in3, in4, in5, in6, in7, in8; input nCS; output [width-1:0] Mout; parameter width = 8; always @ (addr or in1 or in2 or in3 or in4 or in5 or in6 or in7 or in8 or nCS) begin if (!nCS) //nCS 低电平使多路选择器工作 case(addr) 3’b000: Mout = in1; 3’b001: Mout = in2; 3’b010: Mout = in3; 3’b011: Mout = in4;

基于FPGA的SDRAM实验Verilog源代码

// 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_on moduleclk_ctrl ( areset, inclk0, c0, c1, c2,

基于FPGA的verilog频率计设计

电子科技大学 (基于FPGA的频率计设计) 题目:简易频率计的设计 指导教师:皇晓辉 姓名:张旗 学号:2905201003 专业:光电学院一专业

摘要 本文主要介绍了基于FPGA 的简易多量程频率计的设计,使用硬件描述语言verilog来实现对硬件的控制,在软件ISE上实现编程的编译综合,在系统时钟48Mhz下可正常工作。该数字频率计采用测频的方法,能准确的测量频率在10Hz到100MHz之间的信号。使用ModelSim仿真软件对Verilog程序做了仿真,并完成了综合布局布线,通过ISE下载到Spartan3A开发板上完成测试。 关键词:FPGA ,verilog,ISE,测频方法

Abstract This paper mainly introduces the simple more range based on FPGA design of frequency meter,Use hardware description language verilog to realize the control of hardware,In the software realize the compilation of the programming ISE on comprehensive,In the system clock can work normally under 48 Mhz。The digital frequency meter frequency measurement method used, can accurate measurement frequency in 10 Hz to 100 MHz of signals between。Use ModelSim simulation software Verilog program to do the simulation, and completed the overall layout wiring,Through the ISE downloaded to Spartan3A development board complete test。 Keywords: FPGA, Verilog, ISE, F requency M easurement

ADDA等一些芯片的verilog程序

/* AD0809 module v1.0 work up to 5M sample = 25us 40khz for normal clk = 2.5M sample = 30us 33khz */ module ad0809( clkin, adclk, eoc, st, ale, datain, oe, dataout ); input clkin; input eoc; input [7:0]datain; output st; output ale; output oe; output adclk; output [7:0]dataout; reg adclk; reg [7:0]dataout; reg st; reg oe; reg ale; //frequence divider for AD parameter Div_adclk = 8'd9;//(9+1)*2=20 adclk=2.5M parameter Div_clk_state = 4'd4;//(4+1)*2=10 clk_state=5M

reg [8:0]div_cnt_ad;//frequence div cnt reg [3:0]div_cnt_state; reg clk_state; always@(negedge clkin)begin if(div_cnt_ad != Div_adclk) div_cnt_ad <= div_cnt_ad + 1'b1; else begin div_cnt_ad <= 0; adclk <= ~adclk; end if(div_cnt_state != Div_clk_state) div_cnt_state <= div_cnt_state + 1'b1; else begin div_cnt_state <= 0; clk_state <= ~clk_state; end end /*AD convert*/ reg [3:0]state; reg [7:0]delay; initial begin state <= 4'd0; end always@(negedge clk_state)begin case(state) 4'd0:begin //clear all st <= 1'b0; oe <= 1'b0; ale <= 1'b0;

相关文档
最新文档