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)
begin
if(rst)
cs <= IDLE;
else
cs <= ns;
end
//下一个状态
always @(*)
begin
if(rst)
ns = IDLE;
else
begin
ns = 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;
endcase
end
end
//计数
always @(posedge clk)
begin
if(rst)
begin
presult <= 1'b0;//初值为0,为偶校验
count <= 4'd0;
end
else if(cs == SEND_DATA)
begin
if(count == 7)
count <= 4'd0;
else
count <= count + 1'b1;
end
else
count <= 4'd0;
end
//寄存器移位
reg [7:0] data_o_temp;
always @(posedge clk)
begin
if(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];//右移
else
data_o_temp <= 8'd0;
end
//发送数据
always @(posedge clk)
begin
if(rst)
txd <= 1'b1;//空闲状态处于高电平
else if(cs == SEND_START)
txd <= 1'b0;//起始位为低电平
else if(cs == SEND_DATA)
begin
txd <= data_o_temp[0];
presult <= presult ^ data_o_temp[0];
end
else if(cs == SEND_CHECK)//发送奇偶校验位、发送结束位
txd <= presult;
else if(cs == SEND_END)//发送停止位
txd <= 1'b1;
else
txd <= 1'b1;
end
endmodule
2.接收
module uart_rx(rxd,clk,rst,data_i,receive_ack,data_error);
input rxd;//接收的bit
input 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)
begin
if(rst)
cs <= IDLE;
else
cs <= ns;
end
//下一个状态
always @(*)
begin
if(rst)
ns = IDLE;
else
begin
ns = 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]: begin
if(~rxd) ns = RECEIVE_DATA;
else ns = IDLE;
end
default: ns = IDLE;
endcase
end
end
//计数
reg presult;//偶校验位
always @(posedge clk)
begin
if(rst)
begin
count <= 4'd0;
presult <= 1'b0;
data_error <= 1'b0;
end
else if(cs == RECEIVE_DATA)
begin
if(count == 7)
count <= 4'd0;
else
count <= count + 1'b1;
end
else
count <= 4'd0;
end
//接收数据,先接收最低位
always @(posedge clk)
begin
if(rst)
data_i <= 8'd0;
else if(cs == RECEIVE_DATA)
begin
data_i[7] <= rxd;
data_i[6:0] <= data_i[7:1];
presult <= presult ^ rxd;
end
else if(cs == RECEIVE_CHECK)
begin
if(presult == rxd)
data_error <= 1'b0;
else
data_error <= 1'b1;
end
else
data_i <= 8'd0;
end
assign receive_ack = (cs == RECEIVE_CHECK)? 1'b1:1'b0;
endmodule