600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > UART串口通信协议

UART串口通信协议

时间:2022-07-19 23:18:26

相关推荐

UART串口通信协议

1.发送

module uart_tx(clk,rst,receive_ack,data_o,txd);input clk;input rst;input receive_ack;//发送数据命令,高电平有效input [7:0] data_o;//8个数据位output txd;//发送数据reg txd;reg [3:0] count;reg presult;//偶校验位//assign presult = CHECK_EVEN^data_o[0]^data_o[1]^data_o[2]^data_o[3]^data_o[4]^data_o[5]^data_o[6]^data_o[7];//parameter CHECK_EVEN = 1'b0;//偶校验//定义状态机的5个状态:等待、发送起始位、发送数据位、发送奇偶校验位、发送结束位parameter IDLE=5'b00001,SEND_START=5'b00010,SEND_DATA=5'b00100,SEND_CHECK=5'b01000,SEND_END=5'b10000;parameter IDLE_POS=3'd0,SEND_START_POS=3'd1,SEND_DATA_POS=3'd2,SEND_CHECK_POS=3'd3,SEND_END_POS=3'd4;reg [4:0] cs,ns;//状态转换always @(posedge clk)beginif(rst)cs <= IDLE;elsecs <= ns;end//下一个状态always @(*)beginif(rst)ns = IDLE;elsebeginns = cs;//赋初值case(1'b1)cs[IDLE_POS]: if(receive_ack) ns = SEND_START;//收到高电平,表示接收到发送命令,同时将线路拉低一个时钟周期cs[SEND_START_POS]: ns = SEND_DATA;cs[SEND_DATA_POS]: if(count == 7) ns = SEND_CHECK;//数据位发送完毕,开始发送校验位cs[SEND_CHECK_POS]: ns = SEND_END;cs[SEND_END_POS]: if(receive_ack) ns = SEND_START;default: ns = IDLE;endcaseendend//计数always @(posedge clk)beginif(rst)beginpresult <= 1'b0;//初值为0,为偶校验count <= 4'd0;endelse if(cs == SEND_DATA)beginif(count == 7)count <= 4'd0;elsecount <= count + 1'b1;endelsecount <= 4'd0;end//寄存器移位reg [7:0] data_o_temp;always @(posedge clk)beginif(rst)data_o_temp <= 8'd0;else if(cs == SEND_START)data_o_temp <= data_o;else if (cs == SEND_DATA)data_o_temp [6:0] <= data_o_temp [7:1];//右移elsedata_o_temp <= 8'd0;end//发送数据always @(posedge clk)beginif(rst)txd <= 1'b1;//空闲状态处于高电平else if(cs == SEND_START)txd <= 1'b0;//起始位为低电平else if(cs == SEND_DATA)begintxd <= data_o_temp[0];presult <= presult ^ data_o_temp[0];endelse if(cs == SEND_CHECK)//发送奇偶校验位、发送结束位txd <= presult;else if(cs == SEND_END)//发送停止位txd <= 1'b1;elsetxd <= 1'b1;endendmodule

2.接收

module uart_rx(rxd,clk,rst,data_i,receive_ack,data_error);input rxd;//接收的bitinput clk;input rst;output [7:0] data_i;output receive_ack;output data_error;//奇偶校验位比较结果输出位reg [7:0] data_i;reg [3:0] count;reg data_error;//定义状态机的4个状态:空闲、接收数据、接收奇偶校验位、停止parameter IDLE=4'b0001,RECEIVE_DATA=4'b0010,RECEIVE_CHECK=4'b0100,RCEIVE_END=4'b1000;parameter IDLE_POS=2'd0,RECEIVE_DATA_POS=2'd1,RECEIVE_CHECK_POS=2'd2,RCEIVE_END_POS=2'd3;reg [3:0] cs,ns;//状态转换always @(posedge clk)beginif(rst)cs <= IDLE;elsecs <= ns;end//下一个状态always @(*)beginif(rst)ns = IDLE;elsebeginns = cs;//赋初值case(1'b1)cs[IDLE_POS]:if(~rxd) ns = RECEIVE_DATA;cs[RECEIVE_DATA_POS]:if(count == 7) ns = RECEIVE_CHECK;cs[RECEIVE_CHECK_POS]: ns = RCEIVE_END;cs[RCEIVE_END_POS]: beginif(~rxd) ns = RECEIVE_DATA;else ns = IDLE;enddefault: ns = IDLE;endcase endend//计数reg presult;//偶校验位always @(posedge clk)beginif(rst)begincount <= 4'd0;presult <= 1'b0;data_error <= 1'b0;endelse if(cs == RECEIVE_DATA)beginif(count == 7)count <= 4'd0;elsecount <= count + 1'b1;endelsecount <= 4'd0;end//接收数据,先接收最低位always @(posedge clk)beginif(rst)data_i <= 8'd0;else if(cs == RECEIVE_DATA)begindata_i[7] <= rxd;data_i[6:0] <= data_i[7:1];presult <= presult ^ rxd;endelse if(cs == RECEIVE_CHECK)beginif(presult == rxd)data_error <= 1'b0;elsedata_error <= 1'b1;endelsedata_i <= 8'd0;endassign receive_ack = (cs == RECEIVE_CHECK)? 1'b1:1'b0;endmodule

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。