(1)RS232接收模块visio框图:
(2)接收模块Verilog代码编写:
/*
常见波特率: 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'd1;
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)
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) &&(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)仿真文件代码:
`timescale 1ns / 1ps
module rs232_tx_tb;
reg [16:0] baud_set ;
reg clk ;
reg reset_n ;
reg rx ;
reg rx_start ;
wire [7:0] rx_data ;
wire rx_done ;
initial clk = 1'd1;
always #10 clk = ~clk;
initial begin
baud_set <= 17'd9600;
rx_start <= 1'd0;
#200;
rx_start <= 1'd1;
reset_n <= 1'd0;
rx <= 1'd1;
#15;
reset_n <= 1'd1;
@(posedge clk)
set_bit(8'd1 );
set_bit(8'd3 );
set_bit(8'd7 );
set_bit(8'd15);
$stop;
end
rs232_rx rs232_rx_inst
(
.baud_set ( baud_set ) ,
.clk ( clk ) ,
.reset_n ( reset_n ) ,
.rx ( rx ) ,
.rx_start ( rx_start ) ,
.rx_data ( rx_data ) ,
.rx_done ( rx_done )
);
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
endmodule
(4)仿真波形: