文档库 最新最全的文档下载
当前位置:文档库 › 串口通信Verilog代码

串口通信Verilog代码

串口通信Verilog代码
串口通信Verilog代码

Verilog串口通信代码

module ck(clk,rst_n,rs232_rx,rs232_tx);

input clk; // 50MHz主时钟

input rst_n; //低电平复位信号

input rs232_rx; // RS232接收数据信号

output rs232_tx; // RS232发送数据信号

wire bps_start; //接收到数据后,波特率时钟启动信号置位

wire clk_bps; // clk_bps的高电平为接收或者发送数据位的中间采样点

wire[7:0] rx_data; //接收数据寄存器,保存直至下一个数据来到

wire rx_int; //接收数据中断信号,接收到数据期间始终为高电平

//----------------------------------------------------

speed_select speed_select( .clk(clk), //波特率选择模块,接收和发送模块复用,不支持全双工通信

.rst_n(rst_n),

.bps_start(bps_start),

.clk_bps(clk_bps)

);

my_uart_rx my_uart_rx( .clk(clk), //接收数据模块

.rst_n(rst_n),

.rs232_rx(rs232_rx),

.clk_bps(clk_bps),

.bps_start(bps_start),

.rx_data(rx_data),

.rx_int(rx_int)

);

my_uart_tx my_uart_tx( .clk(clk), //发送数据模块

.rst_n(rst_n),

.clk_bps(clk_bps),

.rx_data(rx_data),

.rx_int(rx_int),

.rs232_tx(rs232_tx),

.bps_start(bps_start)

);

endmodule

module speed_select(clk,rst_n,bps_start,clk_bps);

input clk; // 50MHz主时钟

input rst_n; //低电平复位信号

input bps_start; //接收到数据后,波特率时钟启动信号置位

output clk_bps; // clk_bps的高电平为接收或者发送数据位的中间采样点

parameter bps9600 = 5207, //波特率为9600bps

bps19200 = 2603, //波特率为19200bps

bps38400 = 1301, //波特率为38400bps

bps57600 = 867, //波特率为57600bps

bps115200 = 433; //波特率为115200bps

parameter bps9600_2 = 2603,

bps19200_2 = 1301,

bps38400_2 = 650,

bps57600_2 = 433,

bps115200_2 = 216;

reg[12:0] bps_para; //分频计数最大值

reg[12:0] bps_para_2; //分频计数的一半

reg[12:0] cnt; //分频计数

reg clk_bps_r; //波特率时钟寄存器

//----------------------------------------------------------

reg[2:0] uart_ctrl; // uart波特率选择寄存器,怎样配置uart_ctr??

//----------------------------------------------------------

always @ (posedge clk or negedge rst_n) begin

if(!rst_n) begin

uart_ctrl <= 3'd0; //默认波特率为9600bps

end

else begin

case (uart_ctrl) //波特率设置

3'd0: begin

bps_para <= bps9600;

bps_para_2 <= bps9600_2;

end

3'd1: begin

bps_para <= bps19200;

bps_para_2 <= bps19200_2;

end

3'd2: begin

bps_para <= bps38400;

bps_para_2 <= bps38400_2;

end

3'd3: begin

bps_para <= bps57600;

bps_para_2 <= bps57600_2;

end

3'd4: begin

bps_para <= bps115200;

bps_para_2 <= bps115200_2;

end

default: ;

endcase

end

end

always @ (posedge clk or negedge rst_n)

if(!rst_n) cnt <= 13'd0;

else if(cnt

else cnt <= 13'd0;

always @ (posedge clk or negedge rst_n)

if(!rst_n) clk_bps_r <= 1'b0;

else if(cnt==bps_para_2 && bps_start) clk_bps_r <= 1'b1; // clk_bps_r高电平为接收或者发送数据位的!中间!采样点

else clk_bps_r <= 1'b0;

assign clk_bps = clk_bps_r;

endmodule

module my_uart_rx(clk,rst_n,rs232_rx,clk_bps,bps_start,rx_data,rx_int);

input clk; // 50MHz主时钟

input rst_n; //低电平复位信号

input rs232_rx; // RS232接收数据信号!!

input clk_bps; // clk_bps的高电平为接收或者发送数据位的中间采样点

output bps_start; //接收到数据后,波特率时钟启动信号置位

output[7:0] rx_data; //接收数据寄存器,保存直至下一个数据来到

output rx_int; //接收数据中断信号,接收到数据期间始终为高电平

//----------------------------------------------------------------

reg rs232_rx0,rs232_rx1,rs232_rx2; //接收数据寄存器,滤波用

wire neg_rs232_rx; //表示数据线接收到下降沿

always @ (posedge clk or negedge rst_n) begin

if(!rst_n) begin

rs232_rx0 <= 1'b1;

rs232_rx1 <= 1'b1;

rs232_rx2 <= 1'b1;

end

else begin

rs232_rx0 <= rs232_rx;

rs232_rx1 <= rs232_rx0;

rs232_rx2 <= rs232_rx1;

end

end

assign neg_rs232_rx = rs232_rx2 & ~rs232_rx1; //接收到下降沿后neg_rs232_rx置高一个时钟周期 ??

//----------------------------------------------------------------

reg bps_start_r;

reg[3:0] num; //移位次数

reg rx_int; //接收数据中断信号,接收到数据期间始终为高电平

always @ (posedge clk or negedge rst_n) begin

if(!rst_n) begin

bps_start_r <= 1'bz;

rx_int <= 1'b0;

end

else if(neg_rs232_rx) begin

bps_start_r <= 1'b1; //启动接收数据

rx_int <= 1'b1; //接收数据中断信号使能

end

else if(num==4'd12) begin //??

bps_start_r <= 1'bz; //数据接收完毕

rx_int <= 1'b0; //接收数据中断信号关闭

end

end

assign bps_start = bps_start_r;

//----------------------------------------------------------------

reg[7:0] rx_data_r; //接收数据寄存器,保存直至下一个数据来到

//----------------------------------------------------------------

reg[7:0] rx_temp_data; //当前接收数据寄存器

reg rx_data_shift; //数据移位标志

always @ (posedge clk or negedge rst_n) begin

if(!rst_n) begin

rx_data_shift <= 1'b0;

rx_temp_data <= 8'd0;

num <= 4'd0;

rx_data_r <= 8'd0;

end

else if(rx_int) begin //接收数据处理

if(clk_bps) begin //读取并保存数据,接收数据为一个起始位,8bit数据,一个结束位 rx_data_shift <= 1'b1;

num <= num+1'b1;

if(num<=4'd8) rx_temp_data[7] <= rs232_rx; //锁存9bit(1bit起始位,8bit 数据)??如何配置rs232_rx

end

else if(rx_data_shift) begin //数据移位处理

rx_data_shift <= 1'b0;

if(num<=4'd8) rx_temp_data <= rx_temp_data >> 1'b1; //移位8次,第1bit起始位移除,剩下8bit正好是接收数据

else if(num==4'd12) begin

num <= 4'd0; //接收到STOP位后结束,num清零

rx_data_r <= rx_temp_data; //把数据锁存到数据寄存器rx_data中

end

end

end

end

assign rx_data = rx_data_r;

endmodule

module my_uart_tx(clk,rst_n,clk_bps,rx_data,rx_int,rs232_tx,bps_start);

input clk; // 50MHz主时钟

input rst_n; //低电平复位信号

input clk_bps; // clk_bps的高电平为接收或者发送数据位的中间采样点

input[7:0] rx_data; //接收数据寄存器

input rx_int; //接收数据中断信号,接收到数据期间始终为高电平,在次利用它的下降沿来启动发送数据

output rs232_tx; // RS232发送数据信号

output bps_start; //接收或者要发送数据,波特率时钟启动信号置位

//---------------------------------------------------------

reg rx_int0,rx_int1,rx_int2; //rx_int信号寄存器,捕捉下降沿滤波用

wire neg_rx_int; // rx_int下降沿标志位

always @ (posedge clk or negedge rst_n) begin

if(!rst_n) begin

rx_int0 <= 1'b0;

rx_int1 <= 1'b0;

rx_int2 <= 1'b0;

end

else begin

rx_int0 <= rx_int;

rx_int1 <= rx_int0;

rx_int2 <= rx_int1;

end

end

assign neg_rx_int = ~rx_int1 & rx_int2; //捕捉到下降沿后,neg_rx_int拉地保持一个主时钟周期??

//---------------------------------------------------------

reg[7:0] tx_data; //待发送数据的寄存器

//---------------------------------------------------------

reg bps_start_r;

reg tx_en; //发送数据使能信号,高有效

reg[3:0] num;

always @ (posedge clk or negedge rst_n) begin

if(!rst_n) begin

bps_start_r <= 1'bz;

tx_en <= 1'b0;

tx_data <= 8'd0;

end

else if(neg_rx_int) begin //接收数据完毕,准备把接收到的数据发回去

bps_start_r <= 1'b1;

tx_data <= rx_data; //把接收到的数据存入发送数据寄存器

tx_en <= 1'b1; //进入发送数据状态中

end

else if(num==4'd11) begin //数据发送完成,复位

bps_start_r <= 1'bz;

tx_en <= 1'b0;

end

end

assign bps_start = bps_start_r;

//---------------------------------------------------------

reg rs232_tx_r;

always @ (posedge clk or negedge rst_n) begin

if(!rst_n) begin

num <= 4'd0;

rs232_tx_r <= 1'b1;

end

else if(tx_en) begin

if(clk_bps) begin

num <= num+1'b1;

case (num)

4'd0: rs232_tx_r <= 1'b0; //发送起始位

4'd1: rs232_tx_r <= tx_data[0]; //发送bit0

4'd2: rs232_tx_r <= tx_data[1]; //发送bit1

4'd3: rs232_tx_r <= tx_data[2]; //发送bit2

4'd4: rs232_tx_r <= tx_data[3]; //发送bit3

4'd5: rs232_tx_r <= tx_data[4]; //发送bit4

4'd6: rs232_tx_r <= tx_data[5]; //发送bit5

4'd7: rs232_tx_r <= tx_data[6]; //发送bit6

4'd8: rs232_tx_r <= tx_data[7]; //发送bit7

4'd9: rs232_tx_r <= 1'b0; //发送结束位

default: rs232_tx_r <= 1'b1;

endcase

end

else if(num==4'd11) num <= 4'd0; //复位

end

end

assign rs232_tx = rs232_tx_r; //如何配置rs232_tx???endmodule

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)在进行模块的端口申明时,每行只申明一个端口,并建议采用以下顺序:

VERILOG语言编写规范

VERILOG语言编写规范 1 目的 本规范的目的是提高书写代码的可读性可修改性可重用性,优化代码综合和仿真结果,指导设计工程师使用VerilogHDL规范代码和优化电路,规范化公司的ASIC设计输入从而做到 1. 逻辑功能正确 2.可快速仿真 3. 综合结果最优如果是hardware model) 4. 可读性较好。 2 范围 本规范涉及Verilog HDL编码风格,编码中应注意的问题, Testbench的编码等。 本规范适用于Verilog model的任何一级( RTL behavioral, gate_level),也适用于出于仿真,综合或二者结合的目的而设计的模块。 3 定义 Verilog HDL : Verilog 硬件描述语言 FSM :有限状态机 伪路径:静态时序分析( STA)认为是时序失败,而设计者认为是正确的路径 4 引用标准和参考资料 下列标准包含的条文通过在本标准中引用而构成本标准的条文在标准出版时所示版本 均为有效所有标准都会被修订使用本标准的各方应探讨使用下列标准最新版本的可能性 Actel HDLCoding Style Guider Sun Microsystems Revision 1.0 VerilogStyle and Coding Guidelines 5 规范内容 5.1 Verilog 编码风格

本章节中提到的Verilog编码规则和建议适应于 Verilog model的任何一级( RTL behavioral,gate_level) 也适用于出于仿真,综合或二者结合的目的而设计的模块。 5.1.1 命名规范 选择有意义的信号和变量名,对设计是十分重要的。命名包含信号或变量诸如出处,有效状态等基本含义下面给出一些命名的规则。 1. 用有意义而有效的名字 有效的命名有时并不是要求将功能描述出来如 For ( I = 0; I < 1024; I = I + 1 ) Mem[I]<= #1 32’b0; For 语句中的循环指针I 就没必要用loop_index作为指针名。 2. 用连贯的缩写 长的名字对书写和记忆会带来不便,甚至带来错误采用缩写时应注意同一信号在模块中的一致性。缩写的例子如下: Addr address Pntr pointer Clk clock Rst reset 3. 用名字前加小写n表示低电平有效高电平有效的信号不得以下划线表示短暂 的引擎信号建议采用高有效 如 nRst, nTrdy, nIrdy nIdsel. 4. 大小写原则 名字一般首字符大写,其余小写(但parameter, integer 定义的数值名可全部用大写),两个词之间要用下划线连接(或第二个单词首字母大写) 如 :Packet_addr, Data_in, Mem_wr , Mem_ce_ Or: PacketAddr, DataIn, MemWr , MemCe 5.全局信号名字中应包含信号来源的一些信息 如: D_addr[7:2] 这里的 D 指明了地址是解码模块(Decoder module)中的地址.

如何用VC++实现串口通信

用VC 6.0实现串行通信的三种方法 中国科学院王颖 ---- 摘要:本文介绍了在Windows平台下串行通信的实现机制,讨论了根据不同的条件用Visual C++ 设计串行通信程序的三种方法,并结合实际,实现对温度数据的接收监控。 ---- 在实验室和工业应用中,串口是常用的计算机与外部串行设备之间的数据传输通道,由于串行通信方便易行,所以应用广泛。依据不同的条件实现对串口的灵活编程控制是我们所需要的。 ---- 在光学镜片镀膜工艺中,用单片机进行多路温度数据采集控制,采集结果以串行方式进入主机,每隔10S向主机发送一次采样数据,主机向单片机发送相关的控制命令,实现串行数据接收,处理,记录,显示,实时绘制曲线。串行通信程序开发环境为VC++ 6.0。 ---- Windows下串行通信 ---- 与以往DOS下串行通信程序不同的是,Windows不提倡应用程序直接控制硬件,而是通过Windows 操作系统提供的设备驱动程序来进行数据传递。串行口在Win 32中是作为文件来进行处理的,而不是直接对端口进行操作,对于串行通信,Win 32 提供了相应的文件I/O函数与通信函数,通过了解这些函数的使用,可以编制出符合不同需要的通信程序。与通信设备相关的结构有COMMCONFIG ,COMMPROP,COMMTIMEOUTS,COMSTAT,DCB,MODEMDEVCAPS,MODEMSETTINGS共7个,与通信有关的Windows API函数共有26个,详细说明可参考MSDN帮助文件。以下将结合实例,给出实现串行通信的三种方法。 ---- 实现串行通信的三种方法 ---- 方法一:使用VC++提供的串行通信控件MSComm 首先,在对话框中创建通信控件,若Control 工具栏中缺少该控件,可通过菜单Project --> Add to Project --> Components and Control插入即可,再将该控件从工具箱中拉到对话框中。此时,你只需要关心控件提供的对Windows 通讯驱动程序的API 函数的接口。换句话说,只需要设置和监视MSComm控件的属性和事件。 ---- 在ClassWizard中为新创建的通信控件定义成员对象(CMSComm m_Serial),通过该对象便可以对串口属性进行设置,MSComm 控件共有27个属性,这里只介绍其中几个常用属性: ---- CommPort 设置并返回通讯端口号,缺省为COM1。 ---- Settings 以字符串的形式设置并返回波特率、奇偶校验、数据位、停止位。 ---- PortOpen 设置并返回通讯端口的状态,也可以打开和关闭端口。 ---- Input 从接收缓冲区返回和删除字符。 ---- Output 向发送缓冲区写一个字符串。 ---- InputLen 设置每次Input读入的字符个数,缺省值为0,表明读取接收缓冲区中的全部内

VERYLOG编码规范

Verilog编码规范! 一. 强调Verilog代码编写风格的必要性。 强调Verilog代码编写规范,经常是一个不太受欢迎的话题,但却是非常有必要的。 每个代码编写者都有自己的编写习惯,而且都喜欢按照自己的习惯去编写代码。与自己编写风格相近的代码,阅读起来容易接受和理解。相反和自己编写风格差别较大的代码,阅读和接受起来就困难一些。 曾有编程大师总结说,一个优秀的程序员,能维护的代码长度大约在1万行数量级。代码的整洁程度,很大程度上影响着代码的维护难度。 遵循代码编写规范书写的代码,很容易阅读、理解、维护、修改、跟踪调试、整理文档。相反代码编写风格随意的代码,通常晦涩、凌乱,会给开发者本人的调试、修改工作带来困难,也会给合作者带来很大麻烦。 (实际上英文Coding Style有另一层涵义,更偏重的是,某一个电路,用那一种形式的语言描述,才能将电路描述得更准确,综合以后产生的电路更合理。本文更偏重的是,编写Verilog代码时的书写习惯。) 二. 强调编写规范的宗旨。 缩小篇幅 提高整洁度 便于跟踪、分析、调试 增强可读性,帮助阅读者理解 便于整理文档 便于交流合作 三. 变量及信号命名规范。 1. 系统级信号的命名。 系统级信号指复位信号,置位信号,时钟信号等需要输送到各个模块的全局信号;系统信号以字符串Sys开头。 2. 低电平有效的信号后一律加下划线和字母n。如:SysRst_n;FifoFull_n; 3. 经过锁存器锁存后的信号,后加下划线和字母r,与锁存前的信号区别。如CpuRamRd信号,经锁存后应命名为CpuRamRd_r。 低电平有效的信号经过锁存器锁存后,其命名应在_n后加r。如CpuRamRd_n信号,经锁存后应命名为CpuRamRd_nr 多级锁存的信号,可多加r以标明。如CpuRamRd信号,经两级触发器锁存后,应命名为CpuRamRd_rr。 4. 模块的命名。 在系统设计阶段应该为每个模块进行命名。命名的方法是,将模块英文名称的各个单词首字母组合起来,形成3到5个字符的缩写。若模块的英文名只有一个单词,可取该单词的前3个字母。各模块的命名以3个字母为宜。例如: Arithmatic Logical Unit模块,命名为ALU。 Data Memory Interface模块,命名为DMI。

PC机之间串口通信的实现-Read

PC机之间串口通信的实现 一、实验目的 1.熟悉微机接口实验装置的结构和使用方法。 2.掌握通信接口芯片8251和8250的功能和使用方法。 3.学会串行通信程序的编制方法。 二、实验内容与要求 1.基本要求 主机接收开关量输入的数据(二进制或十六进制),从键盘上按“传输”键(可自行定义),就将该数据通过8251A传输出去。终端接收后在显示器上显示数据。具体操作说明如下: (1)出现提示信息“start with R in the board!”,通过调整乒乓开关的状态,设置8位数据; (2)在小键盘上按“R”键,系统将此时乒乓开关的状态读入计算机I中,并显示出来,同时显示经串行通讯后,计算机II接收到的数据; (3)完成后,系统提示“do you want to send another data? Y/N”,根据用户需要,在键盘按下“Y”键,则重复步骤(1),进行另一数据的通讯;在键盘按除“Y”键外的任意键,将退出本程序。 2.提高要求 能够进行出错处理,例如采用奇偶校验,出错重传或者采用接收方回传和发送方确认来保证发送和接收正确。 三、设计报告要求 1.设计目的和内容 2.总体设计 3.硬件设计:原理图(接线图)及简要说明 4.软件设计框图及程序清单 5.设计结果和体会(包括遇到的问题及解决的方法) 四、8251A通用串行输入/输出接口芯片 由于CPU与接口之间按并行方式传输,接口与外设之间按串行方式传输,因此,在串行接口中,必须要有“接收移位寄存器”(串→并)和“发送移位寄存器”(并→串)。能够完成上述“串←→并”转换功能的电路,通常称为“通用异步收发器”(UART:Universal

Verilog状态机的写法

Verilog状态机的写法-转 1 引言 Verilog HDL作为当今国际主流的HDL语言,在芯片的前端设计中有着广泛的应用。它的语法丰富,成功地应用于设计的各个阶段:建模、仿真、验证和综合等。可综合是指综合工具能将Verilog HDL代码转换成标准的门级结构网表,因此代码的描述必须符合一定的规则。大部分数字系统都可以分为控制单元和数据单元两个部分,控制单元的主体是一个状态机,它接收外部信号以及数据单元产生的状态信息,产生控制信号,因而状态机性能的好坏对系统性能有很大的影响。 有许多可综合状态机的Verilog代码描述风格,不同代码描述风格经综合后得到电路的物理实现在速度和面积上有很大差别。优秀的代码描述应当易于修改、易于编写和理解,有助于仿真和调试,并能生成高效的综合结果。 2 有限状态机 有限状态机(Finite State Machine,FSM)在数字系统设计中应用十分广泛。根据状态机的输出是否与输入有关,可将状态机分为两大类:摩尔(Moore)型状态机和米莉 (Mealy)型状态机。Moore型状态机的输出仅与现态有关;Mealy型状态机的输出不仅与现态有关,而且和输入也有关。图1是有限状态机的一般结构图,它主要包括三个部分,其中组合逻辑部分包括状态译码器和输出译码器,状态译码器确定状态机的下一个状态,输出译码器确定状态机的输出,状态寄存器属于时序逻辑部分,用来存储状态机的内部状态。 图1 状态机的结构框图 2.1 好的状态机标准 好的状态机的标准很多,最重要的几个方面如下: 第一,状态机要安全,是指FSM不会进入死循环,特别是不会进入非预知的状态,而且由于某些扰动进入非设计状态,也能很快的恢复到正常的状态循环中来。这里面有两层含义。其一要求该FSM的综合实现结果无毛刺等异常扰动,其

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 -

51单片机和计算机之间实现串口通信的电路图

51单片机和计算机之间实现串口通信的电路图 串口通讯参考程序如下: 来源:深入浅出AVR单片机 #include unsigned char UART_RX; //定义串口接收数据变量 unsigned char RX_flag; //定义穿行接收标记 /**************************************************************************************** ***** 函数名:UART串口初始化函数 调用:UART_init(); 参数:无 返回值:无 结果:启动UART串口接收中断,允许串口接收,启动T/C1产生波特率(占用) 备注:振荡晶体为12MHz,PC串口端设置[ 4800,8,无,1,无] /**************************************************************************************** ******/ void UART_init (void){ EA = 1; //允许总中断(如不使用中断,可用//屏蔽) ES = 1; //允许UART串口的中断 TMOD = 0x20; //定时器T/C1工作方式2 SCON = 0x50; //串口工作方式1,允许串口接收(SCON = 0x40 时禁止串口接收) TH1 = 0xF3; //定时器初值高8位设置 TL1 = 0xF3; //定时器初值低8位设置 PCON = 0x80; //波特率倍频(屏蔽本句波特率为2400) TR1 = 1; //定时器启动 } /**************************************************************************************** ******/ /**************************************************************************************** ***** 函数名:UART串口接收中断处理函数 调用:[SBUF收到数据后中断处理] 参数:无 返回值:无 结果:UART串口接收到数据时产生中断,用户对数据进行处理(并发送回去)备注:过长的处理程序会影响后面数据的接收

VHDL+Verilog良好的代码编写风格

VHDL+Verilog良好的代码编写风格(二十五条) 田Sir 发表于: 2010-4-28 13:56 来源: 湖北师范学院电工电子实验教学示范中心良好代码编写风格可以满足信、达、雅的要求。在满足功能和性能目标的前提下,增强代码的可读性、可移植性,首要的工作是在项目开发之前为整个设计团队建立一个命名约定和缩略语清单,以文档的形式记录下来,并要求每位设计人员在代码编写过程中都要严格遵守。良好代码编写风格的通则概括如下:(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)在进行模块的端口申明时,每行只申明一个端口,并建议采用以下顺序:输入信号的clk、rst、enables other control signals、data and address signals。然后再申明输出信号的clk、rst、enalbes other control signals、data signals; (16)在例化模块时,使用名字相关的显式映射而不要采用位置相关的映射,这样可以提高代码的可读性和方便debug 连线错误; (17)如果同一段代码需要重复多次,尽可能使用函数,如果有可能,可以将函数通用化,以使得它可以复用。注意,内部函数的定义一般要添加注释,这样可以提高代码的可读性; (18)尽可能使用循环语句和寄存器组来提高源代码的可读性,这样可以有效地减少代码行数; (19)对一些重要的always 语句块定义一个有意义的标号,这样有助于调试。注意标号名不要与信号名、变量名重复; (20)代码编写时的数据类型只使用IEEE 定义的标准类型,在VHDL 语言中,设计者可以定义新的类型和子类型,但是所有这些都必须基于IEEE 的标准; (21)在设计中不要直接使用数字,作为例外,可以使用0 和1。建议采用参数定义代替直接的数字。同

MFC实现对串口通信的编写

在Windows应用程序的开发中,我们常常需要面临与外围数据源设备通信的问题。计算机和单片机(如MCS-51)都具有串行通信口,可以设计相应的串口通信程序,完成二者之间的数据通信任务。 实际工作中利用串口完成通信任务的时候非常之多。已有一些文章介绍串口编程的文章在计算机杂志上发表。但总的感觉说来不太全面,特别是介绍32位下编程的更少,且很不详细。笔者在实际工作中积累了较多经验,结合硬件、软件,重点提及比较新的技术,及需要注意的要点作一番探讨。希望对各位需要编写串口通信程序的朋友有一些帮助 一.串行通信的基本原理 串行端口的本质功能是作为CPU和串行设备间的编码转换器。当数据从 CPU经过串行端口发送出去时,字节数据转换为串行的位。在接收数据时,串行的位被转换为字节数据。 在Windows环境(Windows NT、Win98、Windows2000)下,串口是系统资源的一部分。 应用程序要使用串口进行通信,必须在使用之前向操作系统提出资源申请要求(打开串口),通信完成后必须释放资源(关闭串口)。 串口通信程序的流程如下图: 二.串口信号线的接法 一个完整的RS-232C接口有22根线,采用标准的25芯插头座(或者9芯插头座)。25芯和9芯的主要信号线相同。以下的介绍是以25芯的RS-232C为例。 ①主要信号线定义: 2脚:发送数据TXD; 3脚:接收数据RXD; 4脚:请求发送RTS; 5脚:清除发送CTS; 6脚:数据设备就绪DSR;20脚:数据终端就绪DTR;8脚:数据载波检测DCD; 1脚:保护地; 7脚:信号地。 ②电气特性: 数据传输速率最大可到20K bps,最大距离仅15m. 注:看了微软的MSDN 6.0,其Windows API中关于串行通讯设备(不一定都是串口RS-232C或RS-422或RS-449)速率的设置,最大可支持到RS_256000,即256K bps! 也不知道到底是什么串

用verilog语言编写交通灯程序

交通灯 一、实验目的 写一个交通灯,要求: ①有东西南北四个方向,两组交通灯轮流交替变换,其中,红灯时间为30 个时间单位,绿灯时间为25个时间单位,黄灯时间为5个时间单位。最后用modelsim软件进行仿真。 ②要求设计是一个可综合设计。 二、实验原理 根据实验要求的逻辑功能描述,可以分析得出原理图如下: 根据实验要求画出控制器的状态转移图如下:

三、代码 1、源代码 (1)控制器模块 module traffic_lights(clk,rst,count,ew,sn); input clk,rst; input[5:0] count; output[2:0] ew,sn; reg[2:0] ew,sn; reg[3:0] state; parameter Idle=3'b000,s1=3'b001,s2=3'b010,s3=3'b011,s4=3'b100; always @(posedge clk) if(!rst) begin state<=Idle; end else casex(state) Idle: if(rst) begin state<=s1; end s1: if(count=='d25) begin state<=s2; end s2: if(count=='d30) begin state<=s3;

end s3: if(count=='d55) begin state<=s4; end s4: if(count=='d60) begin state<=s1; end endcase always @(posedge clk) begin if(!rst) begin ew<=3'b100; sn<=3'b100; end else casex(state) Idle: if(rst) begin ew<=3'b100; sn<=3'b001; end s1: if(count=='d25) begin ew<=3'b100; sn<=3'b010; end

个人总结Verilog代码编写的25条经验

个人总结Verilog代码编写的25条经验 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、在进行模块的端口申明时,每行只申明一个端口,并建议采用以下顺序: 输入信号的clk、rst、enables other control signals、data and address signals。然后再申明输出信号的clk、rst、enalbes other control signals、data signals; 16、在例化模块时,使用名字相关的显式映射而不要采用位置相关的映射,这样可以提高代码的可读性和方便debug 连线错误; 17、如果同一段代码需要重复多次,尽可能使用函数,如果有可能,可以将函数通用化,以使得它可以复用。注意,内部函数的定义一般要添加注释,这样可以提高代码的可读性;

verilog语言代码设计规范

verilog语言代码设计规范2011年12月

目录 一、规范适用范围 ------------------------------------------------------------------------ 4 1.1项目适用范围------------------------------------------------------------------------------------- 4 1.2人员适用范围------------------------------------------------------------------------------------- 4 1.3编码设计的成果形式 --------------------------------------------------------------------------- 4 二、代码书写规范 ------------------------------------------------------------------------ 5 2.1模块说明书写规范------------------------------------------------------------------------------- 5 2.1模块注释书写规范------------------------------------------------------------------------------- 5 2.3变量名称书写规范------------------------------------------------------------------------------- 6 2.4代码结构书写规范------------------------------------------------------------------------------- 7 三、使用verilog语言的语法范围----------------------------------------------------- 8 3.1设计RTL代码的语法范围 -------------------------------------------------------------------- 8 3.2设计仿真代码的语法范围 -------------------------------------------------------------------- 10 四、使用verilog语言的结构范围---------------------------------------------------- 11 4.1系统设计文件的形式与使用方法----------------------------------------------------------- 11 4.2模块结构划分的标准 -------------------------------------------------------------------------- 12 4.3组合逻辑的代码风格 ------------------------------------------------------------------------ 13 4.4时序逻辑的代码风格 -------------------------------------------------------------------------- 21 4.5仿真代码的代码风格 -------------------------------------------------------------------------- 27 五、使用受限范围内的语法或结构要进行的申请过程-------------------------- 32 5.1受限的语法与结构------------------------------------------------------------------------------ 32 5.2批准使用的程序--------------------------------------------------------------------------------- 32

verilog数字钟代码全新

module digclk(clk,en,rst,dula,wela,s1,s2,s3,led,flag1,start1,flag2,start2,aled,s6,s4,s5); //s1调时s2调分s3调秒wela位码dula段码en使能clk时钟,flag1是跑表标志(拨上去就是显示跑表),置一为跑表功能,start1为跑表开始停止 //flag2为闹钟标志(拨上去就是设置闹钟时间)start2为闹钟开关aled闹钟提示灯input clk,rst,en,s1,s2,s3,flag1,start1,flag2,start2,s6,s4,s5; output [2:0] wela; output [7:0] dula; output led; output aled; reg led; reg aled; reg [7:0] cnt,dula; reg [2:0] wela; reg[7:0] hourh,hourl,minh,minl,sech,secl; reg[7:0] phourh,phourl,pminh,pminl,psech,psecl; reg[7:0] ahourh,ahourl,aminh,aminl,asech,asecl; reg[3:0] a; //a用于数码管显示的临时变量 (* synthesis, keep *) reg clk1; always @(posedge clk1) begin if(start2) begin if(hourh==ahourh&&hourl==ahourl&&minh==aminh&&minl==aminl&&sech==asech&&secl ==asecl) aled=1'b1; else aled=1'b0; end end always @(posedge clk1) //闹钟功能 begin if(flag2) begin if(!s4) //调节小时 begin /*if(ahourl==9)begin ahourl<=0;ahourh<=ahourh+1;end if(ahourh==2&&ahourl==3)begin ahourh<=0;ahourl<=0; end else ahourl<=ahourl+1;*/ ahourl<=ahourl+1; if(ahourl==3&&ahourh==2)begin ahourl<=0;ahourh<=0;end if(ahourl==9) begin ahourl<=0;ahourh<=ahourh+1;end;

串口通讯方法的三种实现

串口基本信息 用一台电脑实验串口自发自收,实验前要将串口(以9针为例)的发送引脚(2脚)和接受引脚(3脚)短接。 三线连接:适用于计算机之间尤其是PC机和单片机之间的数据通信。其连接信号对为(TxD,RxD)、(RxD,TxD)、(SG,SG)。即发送数据TxD端和接受数据RxD端交叉连接,信号地SG对应连接。 七线交叉连接:适用于同型号的计算机之间的连接,如PC机间的数据通信。其连接信号对为:(TxD,RxD)、(RxD,TxD)、(SG,SG)、(RTS,CTS)、(CTS,RTS)、(DSR.DTR)、(DTR,DSR)。其中,TxD、RxD、SG与前面信号的含义相同,RTS为请求发送,CTS为准许发送,DSR为数据装置准备好,DTR为数据终端准备好。在本地连接的微机系统中,RTS、CTS、DTR、DSR用作硬件联络控制信号。 目前使用的串口连接线有DB9和DB25两种连接器,用户可以国家使用的具体机器选择相应的连接器。 一个串口通讯类在https://www.wendangku.net/doc/601176594.html,/network/serialport.shtml。 PC机的RS-232接口的电平标准是-12V标示“1”,和+12V表示“0”,有些单片机的信号电平时TTL 型,即大于2.4v表示“1”,小于0.5v表示“0”,因此采用RS-232总线进行异步通信是,发送端和接受端要有一个电平转换接口。 串口通讯方法的三种实现 串口是计算机上一种非常通用的设备通信协议。大多数计算机包含两个基于RS232的串口。串口同时也是仪器仪表设备通用的通信协议;很多GPIB兼容的设备也带有RS一232口。同时,串口通信协议也可以用于获取远程采集设备的数据。 串口通信(Serial Communication),是指外设和计算机间,通过数据信号线、地线、控制线等,按位进行传输数据的一种通讯方式。串口通信方便易行,应用广泛。在Windows应用程序的开发中,我们常常需要面临与外围数据源设备通信的问题。计算机和单片机(如MSC—51)都具有串行通信口,可以设计相应的串El通信程序,完成二者之间的数据通信任务。 1串口通讯原理 串口通信的原理非常简单,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。它很简单并且能够实现远距离通信。比如IEEE488定义并行通行状态时,规定设备线总常不得超过20米,并且任意两个设备间的长度不得超过2米;而对于串口而言,长度可达1200米。 典型地,串口用于ASCII码字符的传输。通信使用3根线完成:(1)地线,(2)发送,(3)接收。由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。其它线用于握手,但是不是必须的。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通信的端口,这些参数必须匹配。 2串口通讯实现 在.net平台下使用C#语言实现串口通信的方法主要有三种:第一种方法是采用VB6.0中提供的MSComm控件,这种方法编程简单.但MSComm控件在使用前需要在系统中注册;第二种方法是采用微软在.net2.0及其以后版本提供的内置的串口操作类--System.IO.SerialPort,使用简单,但欠灵活;第三种方法是Windows的API函数,虽然编程难度高,但这种方法可以清楚地掌握串口通信的机制,并且高效、自由、灵活。 无论那种采用方式实现串口通讯,都需要通过以下四个步骤来完成: 1)打开串口 MSComm控件是通过设置PortOpen属性值来打开和关闭串口.具体语法为:MSComm. PortOpen=True/False. SerialPort类则是调用类的Open()和Close()方法来实现串口的打开和关闭。 API函数是通过CreateFile来打开串口.因为在Win32系统中,串口被看作一个文件,使用与文件相同的操作方式进行操作。 2)配置串口

Verilog+HDL代码书写规范

1.目的 本规范的目的是提高书写代码的可读性、可修改性、可重用性,优化代码综合和仿真的结果,指导设计工程师使用VerilogHDL规范代码和优化电路,规范化可编程技术部的FPGA设计输入,从而做到:①逻辑功能正确,②可快速仿真,③综合结果最优(如果是hardware model),④可读性较好。 2.范围 本规范涉及Verilog HDL编码风格,编码中应注意的问题,Testbench的编码等。 本规范适用于Verilog model的任何一级(RTL,behavioral, gate_level),也适用于出于仿真、综合或二者结合的目的而设计的模块。 3.定义 Verilog HDL : Verilog 硬件描述语言 FSM :有限状态机 伪路径:静态时序分析(STA)认为是时序失败,而设计者认为是正确的路径。 4.规范内容 4.1.Verilog 编码风格 本章节中提到的Verilog编码规则和建议适应于 Verilog model的任何一级(RTL,behavioral, gate_level),也适用于出于仿真,综合或二者结合的目的而设计的模块。 4.1.1. 命名的习惯 选择有意义的信号和变量名,对设计是十分重要的。命名包含信号或变量诸如出处、有效状态等基本含义,下面给出一些命名的规则。 y用有意义而有效的名字 有效的命名有时并不是要求将功能描述出来,如 For ( I = 0; I < 1024; I = I + 1 ) Mem[I] <= 32’b0; For 语句中的循环指针I 就没必要用loop_index作为指针名。 y用连贯的缩写 长的名字对书写和记忆会带来不便,甚至带来错误。采用缩写时应注意同一信号在模块中的一致性。缩写的例子如下: Addr address Pntr pointer Clk clock reset

相关文档