Verilog之串口(UART)通信
0:起始位,低电平;1~8:数据位;9:校验位,高电平;10:停止位,高电平。
波特率 “9600bps”表示每秒可以传输9600位。
波特率定时计数器由时钟频率除以波特率。
采集1~8位,忽略0、9、10位。
发送“0、8位数据、1、1”
串口传输数据,从最低位开始,到最高位结束。
串口发送:
module tx_bps_module ( CLK, RSTn, Count_Sig, BPS_CLK ); input CLK; input RSTn; input Count_Sig; output BPS_CLK; /***************************/ reg [12:0]Count_BPS; always @ ( posedge CLK or negedge RSTn ) if( !RSTn ) Count_BPS <= 13'd0; else if( Count_BPS == 13'd5207 ) Count_BPS <= 13'd0; else if( Count_Sig ) Count_BPS <= Count_BPS + 1'b1; else Count_BPS <= 13'd0; /********************************/ assign BPS_CLK = ( Count_BPS == 13'd2604 ) ? 1'b1 : 1'b0; /*********************************/ endmodule
module tx_control_module ( CLK, RSTn, TX_En_Sig, TX_Data, BPS_CLK, TX_Done_Sig, TX_Pin_Out ); input CLK; input RSTn; input TX_En_Sig; input [7:0]TX_Data; input BPS_CLK; output TX_Done_Sig; output TX_Pin_Out; /********************************************************/ reg [3:0]i; reg rTX; reg isDone; always @ ( posedge CLK or negedge RSTn ) if( !RSTn ) begin i <= 4'd0; rTX <= 1'b1; isDone <= 1'b0; end else if( TX_En_Sig ) case ( i ) 4'd0 : if( BPS_CLK ) begin i <= i + 1'b1; rTX <= 1'b0; end 4'd1, 4'd2, 4'd3, 4'd4, 4'd5, 4'd6, 4'd7, 4'd8 : if( BPS_CLK ) begin i <= i + 1'b1; rTX <= TX_Data[ i - 1 ]; end 4'd9 : if( BPS_CLK ) begin i <= i + 1'b1; rTX <= 1'b1; end 4'd10 : if( BPS_CLK ) begin i <= i + 1'b1; rTX <= 1'b1; end 4'd11 : if( BPS_CLK ) begin i <= i + 1'b1; isDone <= 1'b1; end 4'd12 : begin i <= 4'd0; isDone <= 1'b0; end endcase /********************************************************/ assign TX_Pin_Out = rTX; assign TX_Done_Sig = isDone; /*********************************************************/ endmodule
module tx_module ( CLK, RSTn, TX_Data, TX_En_Sig, TX_Done_Sig, TX_Pin_Out ); input CLK; input RSTn; input [7:0]TX_Data; input TX_En_Sig; output TX_Done_Sig; output TX_Pin_Out; /********************************/ wire BPS_CLK; tx_bps_module U1 ( .CLK( CLK ), .RSTn( RSTn ), .Count_Sig( TX_En_Sig ), // input - from U2 .BPS_CLK( BPS_CLK ) // output - to U2 ); /*********************************/ tx_control_module U2 ( .CLK( CLK ), .RSTn( RSTn ), .TX_En_Sig( TX_En_Sig ), // input - from top .TX_Data( TX_Data ), // input - from top .BPS_CLK( BPS_CLK ), // input - from U2 .TX_Done_Sig( TX_Done_Sig ), // output - to top .TX_Pin_Out( TX_Pin_Out ) // output - to top ); /***********************************/ endmodule
串口接受
module detect_module ( CLK, RSTn, RX_Pin_In, H2L_Sig ); input CLK; input RSTn; input RX_Pin_In; output H2L_Sig; /******************************/ reg H2L_F1; reg H2L_F2; always @ ( posedge CLK or negedge RSTn ) if( !RSTn ) begin H2L_F1 <= 1'b1; H2L_F2 <= 1'b1; end else begin H2L_F1 <= RX_Pin_In; H2L_F2 <= H2L_F1; end /***************************************/ assign H2L_Sig = H2L_F2 & !H2L_F1; /***************************************/ endmodule
module rx_control_module ( CLK, RSTn, H2L_Sig, RX_Pin_In, BPS_CLK, RX_En_Sig, Count_Sig, RX_Data, RX_Done_Sig ); input CLK; input RSTn; input H2L_Sig; input RX_En_Sig; input RX_Pin_In; input BPS_CLK; output Count_Sig; output [7:0]RX_Data; output RX_Done_Sig; /********************************************************/ reg [3:0]i; reg [7:0]rData; reg isCount; reg isDone; always @ ( posedge CLK or negedge RSTn ) if( !RSTn ) begin i <= 4'd0; rData <= 8'd0; isCount <= 1'b0; isDone <= 1'b0; end else if( RX_En_Sig ) case ( i ) 4'd0 : if( H2L_Sig ) begin i <= i + 1'b1; isCount <= 1'b1; end /*进入第0位,同时驱动bps_module开始计数。又以bps_module驱动状态1~11*/ 4'd1 : if( BPS_CLK ) begin i <= i + 1'b1; end /*第0位中部,BPS_CLK发出第一个脉冲,忽略第0位*/ 4'd2, 4'd3, 4'd4, 4'd5, 4'd6, 4'd7, 4'd8, 4'd9 : if( BPS_CLK ) begin i <= i + 1'b1; rData[ i - 2 ] <= RX_Pin_In; end 4'd10 : if( BPS_CLK ) begin i <= i + 1'b1; end 4'd11 : if( BPS_CLK ) begin i <= i + 1'b1; end 4'd12 : begin i <= i + 1'b1; isDone <= 1'b1; isCount <= 1'b0; end 4'd13 : begin i <= 4'd0; isDone <= 1'b0; end endcase /********************************************************/ assign Count_Sig = isCount; assign RX_Data = rData; assign RX_Done_Sig = isDone; /*********************************************************/ endmodule
module rx_bps_module ( CLK, RSTn, Count_Sig, BPS_CLK ); input CLK; input RSTn; input Count_Sig; output BPS_CLK; /***************************/ reg [12:0]Count_BPS; always @ ( posedge CLK or negedge RSTn ) if( !RSTn ) Count_BPS <= 13'd0; else if( Count_BPS == 13'd5207 ) Count_BPS <= 13'd0; else if( Count_Sig ) Count_BPS <= Count_BPS + 1'b1; else Count_BPS <= 13'd0; /********************************/ assign BPS_CLK = ( Count_BPS == 12'd2604 ) ? 1'b1 : 1'b0; /*周期中间开始采集数据*/ /*********************************/ endmodule
module rx_module ( CLK, RSTn, RX_Pin_In, RX_En_Sig, RX_Done_Sig, RX_Data ); input CLK; input RSTn; input RX_Pin_In; input RX_En_Sig; output [7:0]RX_Data; output RX_Done_Sig; /**********************************/ wire H2L_Sig; detect_module U1 ( .CLK( CLK ), .RSTn( RSTn ), .RX_Pin_In( RX_Pin_In ), // input - from top .H2L_Sig( H2L_Sig ) // output - to U3 ); /**********************************/ wire BPS_CLK; rx_bps_module U2 ( .CLK( CLK ), .RSTn( RSTn ), .Count_Sig( Count_Sig ), // input - from U3 .BPS_CLK( BPS_CLK ) // output - to U3 ); /**********************************/ wire Count_Sig; rx_control_module U3 ( .CLK( CLK ), .RSTn( RSTn ), .H2L_Sig( H2L_Sig ), // input - from U1 .RX_En_Sig( RX_En_Sig ), // input - from top .RX_Pin_In( RX_Pin_In ), // input - from top .BPS_CLK( BPS_CLK ), // input - from U2 .Count_Sig( Count_Sig ), // output - to U2 .RX_Data( RX_Data ), // output - to top .RX_Done_Sig( RX_Done_Sig ) // output - to top ); /************************************/ endmodule