|
这个程序我是在人人网的一个讨论组中下的,作者是郑剑(还是姓吴还是孙的)
据其原帖描述,误码率0.1% 感觉还可以,于是就下来
编译没有问题,功能就是“自发自收”,但是跑到板子里,问题就来了
1 自发自收单个字节(16进制,以下相同),没有问题,但是用示波器观看波形(当时还不会modelsim),看到了现象是,波形中,一个字节数据中的停止位是错的,于是修改了代码
2 自发自收,多个数据时,除了第一个字节,后面数据都是错误的... 看波形,一个字节数据宽应该是(1.04ms),但是实际波形明显多出了 2个Bits的时间宽度...;;修改了原程序中的收、发 数据位个数后,自发自收正常,出错概率很低...基本没有可以说 呵呵
但是新的问题来了,也不知道如何在这个程序上修改了(下面的代码是我修改后的,在我板子上正常的)
功能需求
PC发送数据包格式如下:
bootcode len cmd para checksum
比如发送
40 03 02 01 BB
该命令包的命令码就是:02 ,参数:01
当FPGA 收到命名包,并解析命令包,
当命令码为:02时 , 且参数为:01;调用 音乐播放模块,并播放音乐..
再发送: 40 03 02 02 BA 是
当FPGA 收到命名包,并解析命令包,
当命令码为:02时 , 且参数为:02;停止播放音乐..
请问如何在这个基础上修改呢? 谢谢- module my_uart_top(clk,rst_n,rs232_rx,rs232_tx);
-
- input clk; // 主时钟
- input rst_n; //低电平复位信号
- input rs232_rx; // RS232接收数据信号
- output rs232_tx; // RS232发送数据信号
-
- wire bps_start1,bps_start2; //接收到数据后,波特率时钟启动信号置位
- wire clk_bps1,clk_bps2; // clk_bps的高电平为接收或者发送数据位的中间采样点
- wire[7:0] rx_data; //接收数据寄存器,保存直至下一个数据来到
- wire rx_int; //接收数据中断信号,接收到数据期间始终为高电平
- //----------------------------------------------------
- speed_select speed_rx( .clk(clk), //波特率选择模块,接收和发送模块复用,不支持全双工通信
- .rst_n(rst_n),
- .bps_start(bps_start1),
- .clk_bps(clk_bps1)
- );
-
- my_uart_rx my_uart_rx( .clk(clk), //接收数据模块
- .rst_n(rst_n),
- .rs232_rx(rs232_rx),
- .clk_bps(clk_bps1),
- .bps_start(bps_start1),
- .rx_data(rx_data),
- .rx_int(rx_int)
- );
-
- speed_select speed_tx( .clk(clk), //波特率选择模块,接收和发送模块复用,不支持全双工通信
- .rst_n(rst_n),
- .bps_start(bps_start2),
- .clk_bps(clk_bps2)
- );
- my_uart_tx my_uart_tx( .clk(clk), //发送数据模块
- .rst_n(rst_n),
- .clk_bps(clk_bps2),
- .rx_data(rx_data),
- .rx_int(rx_int),
- .rs232_tx(rs232_tx),
- .bps_start(bps_start2)
- );
-
- endmodule
- module my_uart_rx(clk,rst_n,rs232_rx,clk_bps,bps_start,rx_data,rx_int);
-
- input clk; // 主时钟
- 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 [url=home.php?mod=space&uid=72445]@[/url] (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'b0;
- 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'd10) begin //??
- bps_start_r <= 1'b0; //数据接收完毕
- 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'd10) 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; // 主时钟
- 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'b0;
- 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'd10) begin //数据发送完成,复位
- bps_start_r <= 1'b0;
- 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'b1; //发送结束位
- default: rs232_tx_r <= 1'b1;
- endcase
- end
- else if(num==4'd10) num <= 4'd0; //复位
- end
- end
-
- assign rs232_tx = rs232_tx_r; //如何配置rs232_tx???
-
- endmodule
- module speed_select(clk,rst_n,bps_start,clk_bps);
-
- input clk; // 主时钟
- input rst_n; //低电平复位信号
- input bps_start; //接收到数据后,波特率时钟启动信号置位
- output clk_bps; // clk_bps的高电平为接收或者发送数据位的中间采样点
- parameter bps9600 = 5208,//5207, //波特率为9600bps 这里使用FPGA主频计算11.06962Mhz,5207是50MHz主频计算值
- bps19200 = 2603, //波特率为19200bps
- bps38400 = 1301, //波特率为38400bps
- bps57600 = 867, //波特率为57600bps
- bps115200 = 433; //波特率为115200bps
-
- parameter bps9600_2 = 2604,//2603,
- bps19200_2 = 1301,
- bps38400_2 = 650,
- bps57600_2 = 433,
- bps115200_2 = 216;
-
- reg[31:0] bps_para; //分频计数最大值,以前是13位数据,但是总是有报警,所以我就给改成了32为数据,没有了多余的报警
- reg[31:0] bps_para_2; //分频计数的一半
- /*`define bps_para 5207 //因为这个uart_ctrl在always中会产生报警,所以使用伪指令的宏定义
- `define bps_para_2 2603*/ //这个宏定义的参数在使用的时候必须给参数前加一个`例如:`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<bps_para && bps_start) cnt <= cnt+1'b1; //波特率时钟计数启动
- 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
复制代码 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|