(1)顶层模块设计Visio视图(没有加入baud_set端口):
(2)修改一部分串口接收模块代码:
/*
常见波特率: 4800、9600、14400、115200
在系统时钟为50MHz时,对应计数为:
(1/4800) * 10^9 /20 -1 = 10416
(1/9600) * 10^9 /20 -1 = 5207
(1/14400) * 10^9 /20 -1 = 3471
(1/115200) * 10^9 /20 -1 = 433
*/
module rs232_rx
(
input [16:0] baud_set ,
input clk ,
input reset_n ,
input rx ,
input rx_start ,
output reg[7:0] rx_data ,
output reg rx_done
);
reg [15:0] BAUD_MCNT ;
reg rx_reg0 ;
reg rx_reg1 ;
reg rx_reg2 ;
reg en_baud_cnt ;
reg [15:0] baud_cnt ;
reg [3:0] bit_cnt ;
reg [7:0] r_rx_data ;
wire nedge ;
wire w_rx_done ;
//波特最大计数设计
always@(posedge clk)
begin
case(baud_set)
17'd4800 :BAUD_MCNT <= 16'd10416;
17'd9600 :BAUD_MCNT <= 16'd5207;
17'd14400 :BAUD_MCNT <= 16'd3471;
17'd115200 :BAUD_MCNT <= 16'd433;
default :BAUD_MCNT <= 16'd5207; //当输入baud_set为其他值时,一律当成9600处理。
endcase
end
//输入信号打拍处理
always@(posedge clk)
begin
rx_reg0 <= rx;
rx_reg1 <= rx_reg0;
end
//下降沿设计
always@(posedge clk)
rx_reg2 <= rx_reg1;
assign nedge = (rx_reg2) && (!rx_reg1);
//波特率计数使能信号设计
always@(posedge clk or negedge reset_n)
if(!reset_n)
en_baud_cnt <= 1'd0;
else if(!rx_start)
en_baud_cnt <= 1'd0;
else if(nedge)
en_baud_cnt <= 1'd1;
else if((bit_cnt == 4'd0) && (baud_cnt == BAUD_MCNT/2)&&(rx_reg2)) //防止起始位只是一个抖动
en_baud_cnt <= 1'd0;
else if((bit_cnt == 4'd9) && (baud_cnt == BAUD_MCNT/2))
en_baud_cnt <= 1'd0;
else
en_baud_cnt <= en_baud_cnt;
//波特计数器模块设计
always@(posedge clk or negedge reset_n)
if(!reset_n)
baud_cnt <= 16'd0;
else if(!en_baud_cnt)
baud_cnt <= 16'd0;
else if((baud_cnt == BAUD_MCNT) || ((bit_cnt == 4'd9) && (baud_cnt == BAUD_MCNT/2)))
baud_cnt <= 16'd0;
else
baud_cnt <= baud_cnt + 16'd1;
//位计数器模块设计
always@(posedge clk or negedge reset_n)
if(!reset_n)
bit_cnt <= 4'd0;
else if((baud_cnt == BAUD_MCNT/2) &&(bit_cnt == 4'd9))
bit_cnt <= 4'd0;
else if(baud_cnt == BAUD_MCNT)
bit_cnt <= bit_cnt + 4'd1;
else
bit_cnt <= bit_cnt;
//rx_data设计
always@(posedge clk or negedge reset_n)
if(!reset_n)
r_rx_data <= 8'd0;
else if(baud_cnt == BAUD_MCNT/2)begin
case(bit_cnt)
4'd1: r_rx_data[0] <= rx_reg2;
4'd2: r_rx_data[1] <= rx_reg2;
4'd3: r_rx_data[2] <= rx_reg2;
4'd4: r_rx_data[3] <= rx_reg2;
4'd5: r_rx_data[4] <= rx_reg2;
4'd6: r_rx_data[5] <= rx_reg2;
4'd7: r_rx_data[6] <= rx_reg2;
4'd8: r_rx_data[7] <= rx_reg2;
default:r_rx_data <= r_rx_data;
endcase
end
else
r_rx_data <= r_rx_data;
always@(posedge clk or negedge reset_n)
if(!reset_n)
rx_data <= 8'd0;
else if(w_rx_done)
rx_data <= r_rx_data;
else
rx_data <= rx_data;
//w_rx_done和rx_done信号设计
assign w_rx_done = (bit_cnt == 4'd9) && (baud_cnt == BAUD_MCNT/2) ;
always@(posedge clk or negedge reset_n)
if(!reset_n)
rx_done <= 1'd0;
else
rx_done <= w_rx_done;
endmodule
(3)顶层模块代码:
module rx232
(
input clk ,
input reset_n ,
input rx ,
output tx ,
output reg led
);
wire tx_done ;
wire [7:0] rx_data ;
wire rx_done ;
wire [7:0] tx_data ;
wire tx_start;
assign tx_data = rx_data;
assign tx_start = rx_done;
rs232_rx rs232_rx_inst0
(
.baud_set ( 17'd9600 ) ,
.clk ( clk ) ,
.reset_n ( reset_n ) ,
.rx ( rx ) ,
.rx_start ( 1'd1 ) ,
.rx_data ( rx_data ) ,
.rx_done ( rx_done )
);
rs232_tx rs232_tx_inst0
(
.baud_set ( 17'd9600 ) ,
.clk ( clk ) ,
.reset_n ( reset_n ) ,
.tx_data ( tx_data ) ,
.tx_start ( tx_start ) ,
.tx ( tx ) ,
.tx_done ( tx_done )
);
always@(posedge clk or negedge reset_n)
if(!reset_n)
led <= 1'd0;
else if(tx_done)
led <= ~led;
else
led <= led;
endmodule
(4)仿真文件代码:
`timescale 1ns / 1ps
module rx232_tb;
reg clk ;
reg reset_n ;
reg rx ;
wire tx ;
wire led ;
initial clk = 1'd1;
always #10 clk = ~clk;
initial begin
reset_n <= 1'd0;
rx <= 1'd1;
#22;
reset_n <= 1'd1;
#2000;
@(posedge clk);
set_byte();
#2000000;
$stop;
end
task set_byte();
integer j;
for(j = 1;j < 20; j = j + 3)
set_bit(j);
endtask
task set_bit(
input [7:0]data
);
integer i;
for(i = 0; i < 10; i = i + 1)begin
case(i)
0: rx <= 1'd0;
1: rx <= data[0];
2: rx <= data[1];
3: rx <= data[2];
4: rx <= data[3];
5: rx <= data[4];
6: rx <= data[5];
7: rx <= data[6];
8: rx <= data[7];
9: rx <= 1'd1;
endcase
#(5208 * 20);
end
endtask
rx232 rx232_inst
(
.clk (clk ),
.reset_n (reset_n),
.rx (rx ),
.tx (tx ),
.led (led )
);
endmodule
(5)仿真波形:
波特率均固定在9600,波特率计数器最大值固定在5207:
rs232接收模块顺利将rx串行数据转换成了[7:0]rx_data并行数据,并输出了rx_done信号,将它们赋值给了rs232发送模块的[7:0]tx_data信号和tx_start信号:
现以传输的数据13为例,比较rx与tx信号的细节,且可以观察到led随着tx发送完一次数据而翻转:
(6)引脚绑定:
(7)开发板连接图:
(8)串口调试:
led翻转
传输多个数据: