串口发送接收
0赞该程序实现串口发送接收及其仿真
///////////////////////////////////////////////////////////////////////////
module top(
input clk,//100m
input rst,
input rxd,
output [7:0]data_rxd,
output data_rxd_flag,
output txd,
output txd_flag,
input [7:0] data_txd
);
wire clk_uart_16;
wire clk_uart_16_en;
precise_devider
#(.devide_cnt(32'd6597070))
precise_devider_rec
(.clk(clk),
.rst(rst),
.clk_uart_16(clk_uart_16),
.clk_uart_16_en (clk_uart_16_en)
);
uart_receiver uart_receiver (
.clk(clk),
.rst(rst),
.uart_start(1),//1串口开启,0串口关闭
.clk_uart_16(clk_uart_16),//波特率的16倍,用于数据中间采样
.clk_uart_en(clk_uart_16_en),//波特率时钟使能信号
.rxd(rxd), //串口数据
.data_rxd(data_rxd),//接收到的串口并行数据
.data_rxd_flag(data_rxd_flag)//接收数据结束标志
);
wire clk_uart;
wire clk_uart_en;
precise_devider
#(.devide_cnt(32'd412317))
precise_devider_txd(
.clk(clk),
.rst(rst),
.clk_uart_16(clk_uart),
.clk_uart_16_en(clk_uart_en)
);
uart_transmit uart_transmit(
.clk(clk),
.rst(rst),
.uart_start(1),
.clk_uart(clk_uart),
.clk_uart_en(clk_uart_en),
.data_txd(data_txd),
.txd(txd),
.txd_flag(txd_flag)
);
endmodule
/////////////////////////////////////////////////////
/*该模块完成了串口数据的接收,把串行数据转换成并行8位数据。先检测起始位0,检测到起始位后
在接下来数据中间把数据采集,然后检测结束位。然后从新开始。
*/
module uart_receiver (
input clk,
input rst,
input uart_start,//1串口开启,0串口关闭
input clk_uart_16,//波特率的16倍,用于数据中间采样
input clk_uart_en,//波特率时钟使能信号
input rxd, //串口数据
output reg [7:0] data_rxd,//接收到的串口并行数据
output reg data_rxd_flag//接收数据结束标志
//output reg [4:0] counter_16,
//output reg [3:0] receive_bit,
//output reg [3:0] state
);
reg [4:0] counter_16;//时钟计数,16表示在数据结束位置
reg [3:0] receive_bit;//接收数据的位数
reg [3:0] state;
parameter idle =0;
parameter start=1;
parameter sample=2;
parameter stop=3;
parameter top=15;
parameter center=7;
reg rxd_s;
always@(posedge clk or negedge rst) //把异步信号进行同步
if(rst==0)
rxd_s<=0;
else
rxd_s<=rxd;
always @(posedge clk or negedge rst)
begin
if((rst==0)|(uart_start==0))
begin
state<=0;
counter_16<=0;
receive_bit<=0;
end
else
begin
case(state)
idle:
begin
if(clk_uart_en==1)
begin
if(rxd_s==0)
begin
state<=start;//检测到起始位跳转到开始状态
counter_16<=counter_16+1;
receive_bit<=0;
end
else
begin
state<=state;
end
end
else
begin
state<=state;
end
end
start:
begin
if(clk_uart_en==1)
begin
if(counter_16==center)
begin
if(rxd_s==0)//起始位稳定
begin
state<=state;
counter_16<=counter_16+1;
end
else
begin
state<=idle;
counter_16<=0;
end
end
else
if(counter_16==top)//起始位结束
begin
state<=sample;
counter_16<=0;
end
else
begin
counter_16<=counter_16+1;
state<=state;
end
end
else
begin
state<=state;
counter_16<=counter_16;
end
end
sample:
begin
if(clk_uart_en==1)
begin
if(counter_16==top)
begin
if(receive_bit==7)//采完8位数据后,进入停止位
begin
state<=stop;
counter_16<=0;
receive_bit<=8;
end
else
begin
state<=state;
counter_16<=0;
receive_bit<=receive_bit+1;
end
end
else
begin
state<=state;
counter_16<=counter_16+1;
end
end
else
begin
state<=state;
counter_16<=counter_16;
end
end
stop:
begin
if(clk_uart_en==1)
begin
if(counter_16==top)
begin
state<=idle;
counter_16<=0;
end
else
begin
state<=state;
counter_16<=counter_16+1;
end
end
else
begin
state<=state;
counter_16<=counter_16;
end
end
default:state<=0;
endcase
end
end
reg [7:0]data_rxd_r;
always@(posedge clk or negedge rst)
begin
if(rst==0)
begin
data_rxd_r<=0;
end
else
begin
if((state==sample)&&(clk_uart_en==1)&&(counter_16==center))
begin
case(receive_bit)
0:data_rxd_r[0]<=rxd_s;
1:data_rxd_r[1]<=rxd_s;
2:data_rxd_r[2]<=rxd_s;
3:data_rxd_r[3]<=rxd_s;
4:data_rxd_r[4]<=rxd_s;
5:data_rxd_r[5]<=rxd_s;
6:data_rxd_r[6]<=rxd_s;
7:data_rxd_r[7]<=rxd_s;
default:data_rxd_r<=data_rxd_r;
endcase
end
else
begin
data_rxd_r<=data_rxd_r;
end
end
end
always@(posedge clk or negedge rst)
begin
if(rst==0)
begin
data_rxd_flag<=0;
data_rxd<=0;
end
else
begin
if((state==stop)&&(counter_16==top))
begin
data_rxd_flag<=1;
data_rxd<=data_rxd_r;
end
else
begin
data_rxd_flag<=0;
data_rxd<=data_rxd;
end
end
end
endmodule
///////////////////////////////////////////////////////
module uart_transmit(
input clk,
input rst,
input uart_start,
input clk_uart,
input clk_uart_en,
input [7:0]data_txd,
output reg txd,
output reg txd_flag
);
reg [3:0]state;
parameter start_detect=0;
parameter tramsmit=1;
parameter tramsmit_over=2;
reg [3:0] transmit_bit;
always @(posedge clk or negedge rst)
begin
if(rst==0)
begin
transmit_bit<=0;
state<=0;
end
else
begin
case(state)
start_detect:
begin
if(uart_start==1)
begin
state<=state+1;
transmit_bit<=0;
end
else
begin
state<=state;
transmit_bit<=0;
end
end
tramsmit:
begin
if(clk_uart_en==1)
begin
if(transmit_bit==9)
begin
transmit_bit<=10;
state<=tramsmit_over;
end
else
begin
transmit_bit<=transmit_bit+1;
state<=tramsmit;
end
end
else
begin
state<=state;
transmit_bit<=transmit_bit;
end
end
tramsmit_over:
begin
if(clk_uart_en==1)
begin
transmit_bit<=0;
state<=start_detect;
end
else
begin
transmit_bit<=10;
state<=state;
end
end
default:state<=0;
endcase
end
end
always@(posedge clk or negedge rst)
begin
if(rst==0)
begin
txd<=1;
end
else
begin
if((state==tramsmit)&&(clk_uart_en==1))
begin
case(transmit_bit)
0:txd<=0;
1:txd<=data_txd[0];
2:txd<=data_txd[1];
3:txd<=data_txd[2];
4:txd<=data_txd[3];
5:txd<=data_txd[4];
6:txd<=data_txd[5];
7:txd<=data_txd[6];
8:txd<=data_txd[7];
9:txd<=1;
default:txd<=txd;
endcase
end
else
begin
txd<=txd;
end
end
end
always@(posedge clk or negedge rst)
begin
if(rst==0)
begin
txd_flag<=0;
end
else
begin
if((transmit_bit==10))
begin
txd_flag<=1;
end
else
begin
txd_flag<=0;
end
end
end
endmodule
////////////////////////////////////////
module top_tb;
reg clk;
reg rst;
wire txd_flag;
wire txd;
reg [7:0]data_txd;
reg rxd;
wire data_rxd_flag;
wire [7:0]data_rxd;
reg data_rxd_flag_r1;
always @(posedge clk or negedge rst)
begin
if(rst==0)
data_rxd_flag_r1<=0;
else
data_rxd_flag_r1<=data_rxd_flag;
end
wire data_rxd_flag_detect;
assign data_rxd_flag_detect=(data_rxd_flag)&(!data_rxd_flag_r1);
reg [7:0] data_txd_counter;
always @(posedge clk or negedge rst)
begin
if(rst==0)
data_txd_counter<=0;
else
begin
if(data_rxd_flag_detect==1)
data_txd_counter<=data_txd_counter+1;
else
data_txd_counter<=data_txd_counter;
end
end
always @(posedge clk or negedge rst)
begin
if(rst==0)
data_txd<=0;
else
data_txd<=data_txd_counter;
end
initial
begin
#0 rst=1;
#0 clk=0;
//#0 rxd=1;
#5 rst=0;
#10 rst=1;
end
always@(*) rxd=txd;
always #5 clk<=~clk;
top top(
.clk(clk),
.rst(rst),
.rxd(rxd),
.data_rxd(data_rxd),
.data_rxd_flag(data_rxd_flag),
.txd(txd),
.txd_flag(txd_flag),
.data_txd(data_txd)
);
endmodule
////////////////////////////////
module precise_devider
#(parameter devide_cnt=32'd6597070)
(
input clk,
input rst,
output reg clk_uart_16,
output clk_uart_16_en
);
//parameter devide_cnt=32'd6597070;
reg [31:0] counter_devide_cnt;
always @(posedge clk or negedge rst)
begin
if(rst==0)
begin
counter_devide_cnt<=0;
end
else
begin
counter_devide_cnt<=counter_devide_cnt+devide_cnt;
end
end
always @(posedge clk or negedge rst)
begin
if(rst==0)
begin
clk_uart_16<=0;
end
else
begin
if(counter_devide_cnt<=32'h7fffffff)
begin
clk_uart_16<=0;
end
else
begin
clk_uart_16<=1;
end
end
end
reg clk_uart_16_r;
always@(posedge clk or negedge rst)
begin
if(rst==0)
clk_uart_16_r<=0;
else
clk_uart_16_r<=clk_uart_16;
end
assign clk_uart_16_en=clk_uart_16&(!clk_uart_16_r);
endmodule
