xytlucil

串口发送接收

0
阅读(1270)

该程序实现串口发送接收及其仿真

///////////////////////////////////////////////////////////////////////////

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