rs串口verilog代码
常用Verilog代码

新建文本文档 begin if(en) begin a=b; end else begin a='bz; end end end endmodule //使用always过程语句描述的简单算术逻辑单元 `define add 3'd0; `define minus 3'd1; `define band 3'd2; `define bor 3'd3; `define bnot 3'd; module alu(out,opcode,a,b); output reg [7:0] out; input [2:0] opcode; input [7:0] a,b; always@(opcode or a or b) begin case(opcode) `add:out=a+b; `minus:out=a-b; `band:out=a&b; `bor:out=a|b; `bnot:out=~a; default:out=8'hx; endcase end endmodule //8线-3线编码器 module encode8_3(i,y); input [7:0] i; output reg [2:0] y; always@(i) begin case(i[7:0]) 8'b00000001:y[2:0]=3'b000; 8'b00000010:y[2:0]=3'b001; 8'b00000100:y[2:0]=3'b010; 8'b00001000:y[2:0]=3'b011; 8'b00010000:y[2:0]=3'b100; 8'b00100000:y[2:0]=3'b101; 8'b01000000:y[2:0]=3'b110; 8'b10000000:y[2:0]=3'b111; default:y[2:0]=3'b000; endcase end endmodule //3_8译码器 module decoder3_8(a,y); 第 3 页
Verilog程序代码集

1.全加器Sum=A⊕B⊕CinCount=AB+Cin(A+B)①数据流module adder(a,b,Cin,Sum,Count); input [2:0]a,b;input Cin;output [2:0] Sum;output Count;assign {Count,Sum}=a+b+Cin; endmodule②行为描述always语句module adder(a,b,c,Cin,Sum,Count); input [4:0] a,b;input Cin;output reg [4:0] Sum;output reg Count;reg T1,T2,T3;always@(a or b or Cin)beginSum=a^b^Cin;T1=A&B;T2=Cin&A;T3=Cin&B;Count=T1|T2|T3;endendmodule③结构体module adder (a,b,Cin,Sum,Count);input a,b,Cin;output Sum,Count;Xor a1(s1,a1,b);Xor a2(Sum,s1,Cin);and a3(T1,a,b);or a4(T2,a,b);and a5(T3,Cin,T2);or a6(Count,T1,T3);Endmodule2.数值比较器①判断两值是否相等module compare(a,b,equal);input [7:0] a,b;output equal;assign equal=(a==b)?|0; ②谁大谁输出module compare(a,b,out);input [7:0] a,b;output reg[7:0] out;always@(a or b)beginif (a>b) out<=a;else if (a==b) out<=a;else out<=b;endendmodule③输出参数module compare(a.b.xgy,xsy,xey);input [7:0] x,y;output reg xgy,xsy,xey;always@(x or y)beginif (x==y) xey=1;else xey=0;if (x>y) begin xgy=1;xsy=0;endelse if (x<y) begin xgy=0;xsy=1;end endendmodule3.编码器(4-2 8-3 16-4编码)①case语句8-3编码(优先)module code (in ,out);input [7:0] in;output reg [2:0] out;always@(in)case x(in)begin f=1;8’b1xxxxxxx:out=3’b111;end begin f=1;8’b01xxxxxx:out=3’b110;end begin f=1;8’b001xxxxx:out=3’b101;end begin f=1;8’b0001xxxx:out=3’b100;end begin f=1;8’b00001xxx:out=3’b011;end begin f=1;8’bxx:out=3’b010;endbegin f=1;8’bx:out=3’b001;endbegin f=1;8’b:out=3’b000;end default:begin f=0:out=3’b000;end endcaseendmodule②if-else语句(4-2优先编码)module code(in,out);input[3:0] in;output reg [1:0] out;always@(in)if (in[3]==1):begin f=1;out=2’b11;end else if (in[2]==1):begin f=1;out=2’b10;end else if (in[1]==1):begin f=1;out=2’b01;end else if (in[0]==1):begin f=1;out=2’b00;end else begin f=0;out=2’b00;end endmodule4.多路选择器①行为描述(4选1)module choice(A,B,C,D,ncs addr out);input [7:0]A,B,C,D;input ncs;input [1:0] addr ;output reg[7:0] out;always@(A or B or C or D or ncs or addr) beginif (!ncs)case(addr)2’b00:out=A;2’b01:out=B;2’b10:out=C;2’b11:out=D;endcaseelse out=0;endendmodule5.设计一个4位双向移位寄存器。
波特率发生器

串口RS232通信程序(Verilog)串口有9个管脚,其中只有三个是最重要的,分别是pin 2: RxD (receive data) 接收数据pin 3: TxD (transmit data) 发送数据pin 5: GND(ground) 地串行通信时序我们先来看看字节0x55的发送0x55的二进制代码是01010101,但发送时由低字节开始的,因此发送次序依次为1-0-1-0-1-0-1-0.串行通信电平•"1" is sent using -10V (or between -5V and -15V).•"0" is sent using +10V (or between 5V and 15V).由于计算机RS232的电平与电路板(通常+5V)之间电平的不同所以要用到转换芯片如果PCB板电源+-5V的话用MAX232如果PCB板(FPGA)电源是+-3.3V的话用MAX3232这个图的串口如果采用母头的话,要用交叉公母线,保证是PCB板上这边的RxD连计算机的TxD(3 Pin),PCB板这边的TxD连计算机的RxD(2 Pin).串行通信波特率这里要弄清楚波特率与比特率的差别:比特率是数字信号的传输速率,它用单位时间内传输的二进制代码的有效位(bit)数来表示,其单位为每秒比特数bit/s(bps)、每秒千比特数(Kbps)或每秒兆比特数(Mbps)来表示(此处K和M分别为1000和1000000,而不是涉及计算机存储器容量时的1024和1048576)。
波特率指数据信号对载波的调制速率,它用单位时间内载波调制状态改变次数来表示,其单位为波特(Baud)。
波特率与比特率的关系为:比特率=波特率X单个调制状态对应的二进制位数两相调制(单个调制状态对应1个二进制位)的比特率等于波特率;四相调制(单个调制状态对应2个二进制位)的比特率为波特率的两倍;八相调制(单个调制状态对应3个二进制位)的比特率为波特率的三倍;依次类推。
基于verilog的很基础的RS232串口收发代码

基于verilog的很基础的RS232串口收发代码写代码,记笔记,防忘记,须牢记。
写串口的Verilog代码关键是要搞明白RS232串口的通信协议,它并不像单片机,直接读写SBUF就可实现串口的收发功能,收发整个字节。
而FPGA要一位一位的收发,因此必须了解RS232的数据格式。
起始位:RS232约定一位起始位“0”。
停止位:约定停止位为“1”。
可选一位或两位停止位。
奇偶校验位:可选。
通过串口发送数据时,要严格遵守RS232的数据格式,先发送起始位,然后是数据,最后是停止位(无奇偶校验的情况)。
通过串口接收数据时,若接收端无数据输入,会一直处于高电平,若开始接收数据,会首先收到来自串口的起始位“0”,然后是要接收的数据,最后为停止位(无奇偶校验的情况)。
所以对于接收模块,可如此设计,FPGA一直检测接收端是否有下降沿到来,直到检测到下降沿,才开始接收数据。
波特率设置的重要性不言而喻,毋庸赘述。
此设计为最基础的串口收发代码,控制逻辑简单,适合编写第一次编写串口代码的朋友。
此设计收发的数据格式为1位起始位,1位停止位,无奇偶校验位,8位数据位。
波特率为19200,代码中可随意更改。
具体Verilog代码如下:顶层模块`timescale 1ns / 1ps/////////////////////////////////////////////////////////////////// /////////////// Company : 杭州电子科技大学// Engineer : 晓晓川// Create Date : 2012.08.26// Design Name : serial_test// Module Name : serial_test// Project Name: serial_test// Target Device: CycloneII EP2C5T144C8// Tool versions: Quartus II 11.0// Revision : V1.0// Description : 一个极为简单的串口收发工程,适于串口收发的入门。
verilog 传递参数

verilog 传递参数在Verilog中,模块之间传递参数通常通过模块的端口进行。
Verilog中的模块可以有输入端口(input)、输出端口(output)和双向端口(inout)。
通过这些端口,可以在模块之间传递参数和数据。
首先,你需要在模块的定义中声明端口,并指定它们的方向和数据类型。
例如:verilog.module MyModule(。
input wire clk, // 输入时钟信号。
input wire [7:0] data_in, // 8位输入数据。
output reg [7:0] data_out // 8位输出数据。
);// 模块逻辑。
endmodule.在该例子中,MyModule模块有一个输入时钟信号(clk)、一个8位的输入数据(data_in)和一个8位的输出数据(data_out)。
当你实例化这个模块并连接到其他模块时,你需要将参数传递给端口。
例如:verilog.module MyTopModule(。
input wire clk,。
input wire [7:0] input_data,。
output reg [7:0] output_data.);MyModule inst1(。
.clk(clk), // 将顶层模块的时钟信号连接到子模块的时钟信号。
.data_in(input_data), // 将输入数据连接到子模块的输入数据。
.data_out(output_data) // 将子模块的输出数据连接到顶层模块的输出数据。
);// 其他逻辑。
endmodule.在这个例子中,MyTopModule模块实例化了MyModule模块,并通过连接端口将参数传递给子模块。
当顶层模块的输入发生变化时,这些变化将传递到子模块,并子模块的输出也会传递回顶层模块。
总的来说,在Verilog中传递参数是通过模块的端口进行的,你需要在模块定义和实例化时正确地连接端口,以实现参数的传递和数据交换。
基于FPGA Verilog RS232串口回环测试例程,附源程序仿真源码及测试图片

FPGA Verilog RS232串口回环测试基于FPGA Verilog RS232串口回环测试例程,支持多byte数据传输,附源程序仿真源码及测试图片。
测试基于SSCOM/友善之臂上位机软件测试,测试结果如下图一图二所示。
图一SSCOM图二图三连续发送仿真截图图四连续接收仿真截图后附verilog源程序代码及testbech仿真例程,注释欠。
重点:多byte回环测试要点,上位机串口多位数据连续发送停止位和起始位之间无间隔,回环程序在接收和发送都需要具备在停止位后能立马跳转到下一个起始位的能力。
重点关注cnt_bit的处理方式。
附录1 顶层例化uart_txd uart_txd(.clk_50m(sys_clk_50m),.reset_n(sys_rst_n),.tx_data(rx_data),.baud_set(3'd4),.send_en(rx_done),.send_done(),.send_busy(send_busy),.uart_tx(uart_tx));uart_rxd uart_rxd(.clk_50m(sys_clk_50m),.reset_n(sys_rst_n),.rx_data(rx_data),.baud_set(3'd4),.rx_done(rx_done),.rx_busy(rx_busy),.uart_rx(uart_rx));附录2 串口发送源程序`timescale1ns/1ps///////////////////////////////////////////////////////////////////// /////////////// Company:// Engineer://// Create Date: 2020/06/21 09:45:23// Design Name:// Module Name: uart_txd// Project Name:// Target Devices:// Tool Versions:// Description://// Dependencies:// Revision:// Revision 0.01 - File Created// Additional Comments://///////////////////////////////////////////////////////////////////// /////////////module uart_txd(clk_50m,reset_n,tx_data,baud_set,send_en,send_done,send_busy,uart_tx);input clk_50m;input reset_n;input[7:0] tx_data;input[2:0] baud_set;input send_en;output reg send_done;output reg send_busy;output reg uart_tx;reg[12:0] cnt;reg[12:0] baud_rate_cnt_max;reg[3:0] cnt_bit;reg[7:0] tx_data_r;localparam baud_rate_9600 =13'd5207;localparam baud_rate_19200 =13'd2603;localparam baud_rate_38400 =13'd1301;localparam baud_rate_57600 =13'd867;localparam baud_rate_115200 =13'd433;always@(posedge clk_50m or negedge reset_n)if(!reset_n)baud_rate_cnt_max <= baud_rate_115200;elsecase(baud_set)3'd0:baud_rate_cnt_max = baud_rate_9600;3'd1:baud_rate_cnt_max = baud_rate_19200;3'd2:baud_rate_cnt_max = baud_rate_38400;3'd3:baud_rate_cnt_max = baud_rate_57600;3'd4:baud_rate_cnt_max = baud_rate_115200;default:baud_rate_cnt_max = baud_rate_115200;endcasealways@(posedge clk_50m or negedge reset_n)if(!reset_n)tx_data_r <=8'd0;else if(send_en)tx_data_r <= tx_data;elsetx_data_r <= tx_data_r;always@(posedge clk_50m or negedge reset_n)if(!reset_n)send_busy <=1'b0;else if(send_en)send_busy <=1'b1;else if(cnt == baud_rate_cnt_max)beginif(cnt_bit ==4'd10)send_busy <=1'b0;elsesend_busy <= send_busy;endelsesend_busy <= send_busy;always@(posedge clk_50m or negedge reset_n)if(!reset_n)send_done <=1'b0;else if(cnt == baud_rate_cnt_max)beginif(cnt_bit ==4'd10)send_done <=1'b1;elsesend_done <=1'b0;endelsesend_done <=1'b0;always@(posedge clk_50m or negedge reset_n)if(!reset_n)cnt <=13'd0;else if(send_busy)beginif(cnt == baud_rate_cnt_max)cnt <=13'd0;elsecnt <= cnt +1'b1;endelsecnt <= cnt;/****************************************always@(posedge clk_50m or negedge reset_n)if(!reset_n)cnt_bit <= 4'd0;else if(send_en) //send_en needs to be 1 clock high pulse cnt_bit <= 4'd1;else if(cnt == baud_rate_cnt_max)beginif(cnt_bit == 4'd10)cnt_bit <= 4'd0;elsecnt_bit <= cnt_bit + 1'b1;endelsecnt_bit <= cnt_bit;******************************************/always@(posedge clk_50m or negedge reset_n)if(!reset_n)cnt_bit <=4'd0;else if(send_busy &&(cnt_bit ==4'd11))cnt_bit <=4'd1;else if(cnt ==1)cnt_bit <= cnt_bit +1'b1;elsecnt_bit <= cnt_bit;always@(posedge clk_50m or negedge reset_n)if(!reset_n)beginuart_tx <=1'b1;endelsecase(cnt_bit)4'd0:;4'd1: uart_tx <=1'b0;//start4'd2: uart_tx <= tx_data_r[0];//bit 04'd3: uart_tx <= tx_data_r[1];4'd4: uart_tx <= tx_data_r[2];4'd5: uart_tx <= tx_data_r[3];4'd6: uart_tx <= tx_data_r[4];4'd7: uart_tx <= tx_data_r[5];4'd8: uart_tx <= tx_data_r[6];4'd9: uart_tx <= tx_data_r[7];//bit 84'd10: uart_tx <=1'b1;//stopdefault:;endcaseendmodule附录3 串口发送testbench`timescale1ns/1ps///////////////////////////////////////////////////////////////////// /////////////// Company:// Engineer://// Create Date: 2020/06/21 11:38:04// Design Name:// Module Name: uart_txd_tb// Project Name:// Target Devices:// Tool Versions:// Description://// Dependencies://// Revision:// Revision 0.01 - File Created// Additional Comments://///////////////////////////////////////////////////////////////////// /////////////module uart_txd_tb();reg clk_50m;reg reset_n;reg[7:0] tx_data;reg[2:0] baud_set;reg send_en;wire send_done;wire send_busy;wire uart_tx;parameter CLK_PERIOD =20;initial clk_50m =0;always#(CLK_PERIOD /2) clk_50m =~clk_50m;initial begintx_data =8'h55;baud_set =4;reset_n =0;send_en =0;#(CLK_PERIOD *100);reset_n =1;# CLK_PERIOD;send_en =1;#(CLK_PERIOD );send_en =0;#(CLK_PERIOD *4340);send_en =1;#(CLK_PERIOD );send_en =0;#(CLK_PERIOD *4340);#(CLK_PERIOD *100);$stop;enduart_txd uart_txd(.clk_50m(clk_50m),.reset_n(reset_n),.tx_data(tx_data),.baud_set(baud_set),.send_en(send_en),.send_done(send_done),.send_busy(send_busy),.uart_tx(uart_tx));endmodule附录4 串口接收源程序`timescale1ns/1ps///////////////////////////////////////////////////////////////////// /////////////// Company:// Engineer://// Create Date: 2020/06/21 15:30:30// Design Name:// Module Name: uart_rxd// Project Name:// Target Devices:// Tool Versions:// Description://// Dependencies://// Revision:// Revision 0.01 - File Created// Additional Comments://///////////////////////////////////////////////////////////////////// /////////////module uart_rxd(clk_50m,reset_n,rx_data,baud_set,rx_done,rx_busy,uart_rx);input clk_50m;input reset_n;output reg[7:0] rx_data;input[2:0] baud_set;output reg rx_done;output reg rx_busy;input uart_rx;reg[12:0] cnt;reg[12:0] baud_rate_cnt_max;reg[3:0] cnt_bit;reg uart_rx_r1;reg uart_rx_r2;wire nedge;localparam baud_rate_9600 =13'd5207;localparam baud_rate_19200 =13'd2603;localparam baud_rate_38400 =13'd1301;localparam baud_rate_57600 =13'd867;localparam baud_rate_115200 =13'd433;always@(posedge clk_50m or negedge reset_n)if(!reset_n)baud_rate_cnt_max <= baud_rate_115200;elsecase(baud_set)3'd0:baud_rate_cnt_max = baud_rate_9600;3'd1:baud_rate_cnt_max = baud_rate_19200;3'd2:baud_rate_cnt_max = baud_rate_38400;3'd3:baud_rate_cnt_max = baud_rate_57600;3'd4:baud_rate_cnt_max = baud_rate_115200;default:baud_rate_cnt_max = baud_rate_115200;endcasealways@(posedge clk_50m or negedge reset_n)if(!reset_n)beginuart_rx_r1 <=8'd0;uart_rx_r2 <=8'd0;endelse beginuart_rx_r1 <= uart_rx;uart_rx_r2 <= uart_rx_r1;endassign nedge = uart_rx_r2 &(!uart_rx_r1);always@(posedge clk_50m or negedge reset_n) if(!reset_n)rx_busy <=1'b0;else if(nedge)rx_busy <=1'b1;else if(cnt == baud_rate_cnt_max)begin if(cnt_bit ==4'd10)rx_busy <=1'b0;elserx_busy <= rx_busy;endelserx_busy <= rx_busy;always@(posedge clk_50m or negedge reset_n) if(!reset_n)rx_done <=1'b0;else if(cnt == baud_rate_cnt_max)begin if(cnt_bit ==4'd10)rx_done <=1'b1;elserx_done <=1'b0;endelserx_done <=1'b0;always@(posedge clk_50m or negedge reset_n) if(!reset_n)cnt <=13'd0;else if(rx_busy)beginif(cnt == baud_rate_cnt_max)cnt <=13'd0;elsecnt <= cnt +1'b1;endelsecnt <= cnt;always@(posedge clk_50m or negedge reset_n) if(!reset_n)cnt_bit <=4'd1;else if(cnt == baud_rate_cnt_max )begin if(cnt_bit ==4'd10)cnt_bit <=4'd1;elsecnt_bit <= cnt_bit +1'b1;endelsecnt_bit <= cnt_bit;always@(posedge clk_50m or negedge reset_n)if(!reset_n)beginrx_data <=8'd0;endelse if(cnt == baud_rate_cnt_max /2)case(cnt_bit)4'd1:;//start4'd2: rx_data[0]<= uart_rx_r2;//bit 04'd3: rx_data[1]<= uart_rx_r2;4'd4: rx_data[2]<= uart_rx_r2;4'd5: rx_data[3]<= uart_rx_r2;4'd6: rx_data[4]<= uart_rx_r2;4'd7: rx_data[5]<= uart_rx_r2;4'd8: rx_data[6]<= uart_rx_r2;4'd9: rx_data[7]<= uart_rx_r2;//bit 74'd10:;//stopdefault:;endcaseelserx_data <= rx_data;endmodule附录5串口接收testbench`timescale1ns/1ps///////////////////////////////////////////////////////////////////// /////////////// Company:// Engineer://// Create Date: 2020/06/21 19:44:29// Design Name:// Module Name: uart_rxd_tb// Project Name:// Target Devices:// Tool Versions:// Description://// Dependencies://// Revision:// Revision 0.01 - File Created// Additional Comments://///////////////////////////////////////////////////////////////////// /////////////module uart_rxd_tb();reg clk_50m;reg reset_n;wire[7:0] rx_data;wire rx_done;wire rx_busy;reg uart_rx;parameter CLK_PERIOD =20;initial clk_50m =0;always#(CLK_PERIOD /2) clk_50m =~clk_50m;initial beginreset_n =0;uart_rx =1;//idle#(CLK_PERIOD *100);reset_n =1;# CLK_PERIOD;uart_rx =0;//start#(CLK_PERIOD *434);uart_rx =1;//bit0#(CLK_PERIOD *434);uart_rx =0;//bit1#(CLK_PERIOD *434);uart_rx =1;//bit2#(CLK_PERIOD *434);uart_rx =0;//bit3#(CLK_PERIOD *434);uart_rx =1;//bit4#(CLK_PERIOD *434);uart_rx =0;//bit5#(CLK_PERIOD *434);uart_rx =1;//bit6#(CLK_PERIOD *434);uart_rx =0;//bit7#(CLK_PERIOD *434);uart_rx =1;//stop#(CLK_PERIOD *434);uart_rx =1;//idle#(CLK_PERIOD *434);#(CLK_PERIOD *434);#(CLK_PERIOD *434);uart_rx =0;//start #(CLK_PERIOD *434);uart_rx =0;//bit0#(CLK_PERIOD *434);uart_rx =1;//bit1#(CLK_PERIOD *434);uart_rx =0;//bit2#(CLK_PERIOD *434);uart_rx =1;//bit3#(CLK_PERIOD *434);uart_rx =0;//bit4#(CLK_PERIOD *434);uart_rx =1;//bit5#(CLK_PERIOD *434);uart_rx =0;//bit6#(CLK_PERIOD *434);uart_rx =1;//bit7#(CLK_PERIOD *434);uart_rx =1;//stop#(CLK_PERIOD *434);uart_rx =1;//idle#(CLK_PERIOD *434);#(CLK_PERIOD *434);#(CLK_PERIOD *434);$stop;enduart_rxd uart_rxd(.clk_50m(clk_50m),.reset_n(reset_n),.rx_data(rx_data),.baud_set(3'd4),.rx_done(rx_done),.rx_busy(rx_busy),.uart_rx(uart_rx));endmodule。
RS编码

RS 编码RS(255,249) 码的生成多项式为G (x )=∏=-5)(i ia x ,其中a 为本原元,是本原多项式p (x )=12348++++xxxx 的根。
RS 系统编码器可看作是一个多项式除法器,首先用kn x-乘以消息多项式m (x ),,即在信息码后附加(n-k )个“0”, ,将得到的结果kn x -m (x )除以g (x ),得到余式,b (x )=112210...----++++k n k n xb x b x b b 为所求的校验位,从而,可将码字多项式表示为c (x )=kn x -m (x )+b (x )。
RS 译码由于RS 码是一种循环码,令码字多项式为c (x ),错误多项式为e (x ),则接收多项式可表示为r (x )= c (x )+ e (x )。
存在校验矩阵H ,使c*TH=0,!,定义接收矢量的伴随式S= r*TH=(t s s s 221,...,,)。
可得伴随式:)()(jjj a e a r s ==j=1,2,3,…n 可知伴随式完全由噪声E 决定,充分反映了信道干扰的情况。
循环码编码循环码通常采用码多项式描述, 假设(7, 4)循环码的码字为(1001000), 就可用T(x)=1+x3 表示。
特别是用g(x)表示前k- 1 位皆为0 的码组, 称为生成多项式。
由循环码的性质可知, 循环码对生成矩阵可由码对生成多项式g( x) 及其循环移位构成, (7, 4)循环码生成多项式g(x)=1+x+x3(1011)或g(x)=1+x2+x3(1101), 以选1011 为(7, 4)CRC 码的生成多项式, 用矩阵表示如下式2- 1。
根据生成矩阵, 就可利用上面介绍的方法设计编码器了。
还可以利用循环码自身的循环性, 更方便地实现编码器。
(7, 4)循环码为例, 若输入信息码元为u(x)=1+x3, 则: kn x-u (x )=63x x +=x+)1m od(22x x x ++因此, 码多项式为:o (x )=r (x )+kn x -u (x )=x+632x xx++其中r(x)=x+x2 为信息码元置为高位后整除生成多项式的余式, 它正好对应于校验序列。
verilog RS232 串口通信 verilog

module uart_top(clk,rs232_rx,rs232_tx);
input clk; //时钟信号50M
input rs232_rx; //数据输入信号
bps_start,
clk_bps,
rs232_rx,
rx_data,
rx_int
);
input clk; //50MHz时钟
input rst_n; //低电平复位信号
input rs232_rx; //接收数据信号
);
uart_rx uart_rx(//数据接收模块
.clk(clk),
.rst_n(rst_n),
.bps_start(bps_start1),
.clk_bps(clk_bps1),
.rs232_rx(rs232_rx),
.rx_data(rx_data),
else
begin
if(int_cnt<250) int_cnt<=int_cnt+1'b1;
end
end
assign data_flg=(int_cnt==10)?1'b1:1'b0;
always @(posedge data_flg or negedge rst_n)
output rs232_tx; //数据输出信号
wire clk_bps1,clk_bps2;
wire bps_start1,bps_start2;
wire [7:0] rx_data;
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
UART是通用异步收发器的简称,其中有一种电平规范较RS232规范,它用-3~-15V表示正逻辑,3~15V表示负逻辑,通过FPGA芯片实现RS232通信首先要解决的就是FPGA电平和RS232电平之间的矛盾,通常采用MAX3232作为物理层的电平接口,根据MAX3232提供的标准配制方式把物理电路设计好后,接下来的通信就是要实现逻辑的接收和发送……设计最简单的RS232通信逻辑,FPGA实现将接收到的数据会发出去,总共两个数据传输引脚,一收一发。
将此通信模块分为三个部分:接收模块,波特率控制模块,发送模块。
工作原理:此模块接收MAX3232传过来的串行数据,对齐进行判断采样,校验,最后将数据流中的串行数据转换为八位并行数据,将此八位数据储存,或送给发送模块发送出去。
根据RS232通信标准器串行数据分为起始位、数据位、校验位、停止位,空闲时为高电平,起始位通常为低电平,数据位通常为8位,校验位分为奇校验、偶校验等,停止位一位或两位且为高电平。
FPGA接收模块对此数据进行异步接收,首先就要检测其数据传输开始标识,当然就是检测开始位,于是要有下降沿检测电路,检测到下降沿是输出一高脉冲,此电路可以用两个D触发器加上基本门电路实现,脉冲触发开始进入接收状态,输出接收状态标志位,使其为1,此标志位使能波特率控制模块输出采样脉冲,此计数脉冲触发接收模块中的计数器计数,加到相应的位就把当前的串行总线上的值赋给缓冲器,或对其判断,当计数完成11次计数后,已将8位串行数据转成并行数据到缓冲器中,且进行了校验的判断和停止位的判别,这是接收状态结束,接收状态位置0,计数器清零。
对于波特率产生模块用于控制采样数据脉冲的周期,其周期就为串行数据传送一个bit所用的时间,根据此时间和时钟周期设置计数值。
当接收模块完成工作时,接收状态位为0时可以触发发送模块,发送模块检测接收状态的下降沿,由此产生一高脉冲,与发送模块类似,根据波特率控制模块产生的计数脉冲将并行数据转成串行数据,并加上开始位、校验位、停止位。
由此完成整个串行通信模块。
要熟悉:下降沿检测程序设计,并转串设计等。
顶层模块图如下所示:各模块的程序如下://本程序实现rs232通信中的串行数据接收模块module rs232_rx(//inputclk,//50M的时钟输入rst_n,//低电平复位信号输入rx_cnt_pluse,//采样脉冲输入,总共11个采样脉冲,一个时钟宽度的高电平rs232_in_s,//串行数据输入,空闲时为高电平,1bit低电平作为起始位,接着8bit数据位LSB传输模式,接着偶数校验位,接着1bit低电平作为停止位//outputrs232_out_p,//输出8位并行数据rx_flag,//数据接收状态输出,接收状态下为高电平,其余为低电平rx_error_flag//接收校验错误标识位,若检测奇数校验位或者停止位不正确时输出高电平 );parameter WIGTH=8;input clk,rst_n;input rx_cnt_pluse;input rs232_in_s;output [WIGTH-1:0] rs232_out_p;output rx_flag;output rx_error_flag;reg [3:0] cnt=0;reg rx_flag=0;reg [WIGTH-1:0] rs232_out_p;reg rs232_in_s_r1,rs232_in_s_r2,rs232_in_s_r3,rs232_in_s_r4;wire rs232_in_s_start_flag;always@(posedge clk or negedge rst_n)beginif(!rst_n)beginrs232_in_s_r1<=0;rs232_in_s_r2<=0;endelse//串行数据开始传输检测电路,检测其下降沿,有下降沿是输出一个clk宽度的高脉冲beginrs232_in_s_r1<=rs232_in_s;rs232_in_s_r2<=rs232_in_s_r1;rs232_in_s_r3<=rs232_in_s_r2;rs232_in_s_r4<=rs232_in_s_r3;endendassignrs232_in_s_start_flag=rs232_in_s_r4&(~rs232_in_s_r1)&(~rs232_in_s_r2)&(~rs232_in_ s_r3);always@(posedge clk or negedge rst_n)begin//接收状态控制电路,第一个下降沿时标识位置高,当cnt计数到11时置低if(!rst_n)rx_flag<=0; //数据接收状态输出,接收状态下为高电平,其余为低电平else if(rs232_in_s_start_flag)rx_flag<=1;else if(cnt==11)rx_flag<=0;endreg rx_error_flag_r1,rx_error_flag_r2;rx_error_flag//接收校验错误标识位,若检测奇数校验位或者停止位不正确时输出高电平reg [WIGTH-1:0] rs232_out_p_temp=0;always@(posedge clk or negedge rst_n)begin//串转并逻辑if(!rst_n)begincnt<=0;rs232_out_p_temp<=0;rx_error_flag_r1<=0;rx_error_flag_r2<=0;endelse if(rx_flag)//接收有效状态下,开始接收数据beginif(rx_cnt_pluse)//采样脉冲出发cnt累加// rx_cnt_pluse,//采样脉冲输入,总共11个采样脉冲,一个时钟宽度的高电平begincnt<=cnt+1;case(cnt)//将当前串行数据输入线上的数据锁存到寄存器的相应的位1: rs232_out_p_temp[0]<=rs232_in_s;2: rs232_out_p_temp[1]<=rs232_in_s;3: rs232_out_p_temp[2]<=rs232_in_s;4: rs232_out_p_temp[3]<=rs232_in_s;5: rs232_out_p_temp[4]<=rs232_in_s;6: rs232_out_p_temp[5]<=rs232_in_s;7: rs232_out_p_temp[6]<=rs232_in_s;8: rs232_out_p_temp[7]<=rs232_in_s;9:beginif(rs232_in_s!=^rs232_out_p_temp)//偶数校验位,有奇数个1为1,偶数个1为0 rx_error_flag_r1<=1;else//若校验出错,则给出标识1rx_error_flag_r1<=0;end10:beginif(!rs232_in_s)//1bit1作为停止位。
//串行数据输入,空闲时为高电平,1bit低电平作为起始位,接着8bit数据位rx_error_flag_r2<=1;else//若停止位出错,则给出标识2rx_error_flag_r2<=0;enddefault: ;endcaseendelse if(cnt==11)begincnt<=0;//当计数到11时cnt清零,把缓存中的数据输出rs232_out_p<=rs232_out_p_temp;endendend//两标识相或得到错误标识输出assign rx_error_flag=rx_error_flag_r2 | rx_error_flag_r1;endmodule//////////////////////////////////////////////////////////////////////////此程序完成对8位数据通过RS232口发送出去module rs232_tx(//inputclk,//50M的时钟输入rst_n,//异步置位信号输入rs232_in_p,//8位并行数据输入tx_cnt_flag,//并转串同步脉冲输入rx_flag,//发送开始信号,检测其低电平开始发送//outputrs232_out_s,//串行数据输出tx_flag//发送状态标志,高电平表示正在处于发送状态 );parameter WIGTH=8;input clk,rst_n;input [WIGTH-1:0] rs232_in_p;input tx_cnt_flag; //并转串同步脉冲输入input rx_flag; ,//发送开始信号,检测其低电平开始发送output rs232_out_s;output tx_flag; //发送状态标志,高电平表示正在处于发送状态reg rs232_out_s;reg tx_flag;reg rx_flag_r1,rx_flag_r2;wire rx_flag_negedge;always@(posedge clk or negedge rst_n)begin//检测发送开始信号,检测rx_flag信号的下降沿if(!rst_n)beginrx_flag_r1<=0;rx_flag_r2<=0;endelsebeginrx_flag_r1<=rx_flag;rx_flag_r2<=rx_flag_r1;endendassign rx_flag_negedge=(~rx_flag_r1)&rx_flag_r2;reg [3:0] cnt=0;always@(posedge clk or negedge rst_n)beginif(!rst_n)begintx_flag<=0; //发送状态标志,高电平表示正在处于发送状态endelse if(rx_flag_negedge)tx_flag<=1;else if(cnt==12)tx_flag<=0;endalways@(posedge clk or negedge rst_n) beginif(!rst_n)rs232_out_s<=1; //串行数据输出else if(tx_flag)beginif(tx_cnt_flag//并转串同步脉冲输入)begin//并转串逻辑,停止位是0cnt<=cnt+1;case(cnt)0:rs232_out_s<=0;1:rs232_out_s<=rs232_in_p[0];2:rs232_out_s<=rs232_in_p[1];3:rs232_out_s<=rs232_in_p[2];4:rs232_out_s<=rs232_in_p[3];5:rs232_out_s<=rs232_in_p[4];6:rs232_out_s<=rs232_in_p[5];7:rs232_out_s<=rs232_in_p[6];8:rs232_out_s<=rs232_in_p[7];9:rs232_out_s<=^rs232_in_p;10:rs232_out_s<=1;default:rs232_out_s<=1;endcaseendelse if(cnt==12)begincnt<=0;rs232_out_s<=1;endendendendmodule////////////////////////////////////////////////本程序实现对rs232波特率的控制module baudrate_ctr(//inputclk,//50M的时钟输入rx_tx_en,//发送或接收数据有效标识引脚,其为高电平是表示处于发送或接收状态rst_n,baudrate_word,//波特率设置数输入//outputrx_tx_cnt_pluse//此信号给接收模块作为采样基准信号,给发送模块作为发送同步基准信号);input clk,rst_n;input rx_tx_en;input [13:0] baudrate_word;output rx_tx_cnt_pluse;reg rx_tx_cnt_pluse;reg [13:0] cnt=0;reg [13:0] baudrate_word_reg=0;always@(posedge clk or negedge rst_n)begin//波特率设置数锁存逻辑if(!rst_n)baudrate_word_reg<=0;elsebaudrate_word_reg<=baudrate_word;endalways@(posedge clk or negedge rst_n)begin//完成一个bit传输时间的计数if(!rst_n)begincnt<=0;endelseif((cnt==baudrate_word_reg) || !rx_tx_en)cnt<=0;elsecnt<=cnt+1;endalways@(posedge clk or negedge rst_n)begin//当计数到1bit中间是输出一个clk周期宽度的高脉冲作为输出 if(!rst_n)rx_tx_cnt_pluse<=0;elseif(cnt==(baudrate_word_reg>>1))rx_tx_cnt_pluse<=1;elserx_tx_cnt_pluse<=0;endendmodule。