uart_rx
`define NONE 0
`define ODD 1
`define SEVEN 2
`define SPACE 3
`define MARK 4
`define STOP_ONE 0
`define STOP_ONEHALF 1
`define STOP_TWO 2
module uart_rx
#( parameter CLK = 50_000_000,
parameter BAUD = 9600,
parameter DATABITS = 8,
parameter PARITY = `NONE,
parameter STOPBITS = `STOP_ONE
)
(
input wire clk,
input wire rst,
input wire rx,
output reg [DATABITS-1:0] data,
output reg err,
output reg done //回复接受完毕
);
reg [2:0] rx_r;
always@(posedge clk or posedge rst)
if(rst)
rx_r<=0;
else
begin
rx_r[1:0]<={rx_r[0],rx};
rx_r[2:1]<={rx_r[1],rx_r[0]};
end
reg flag;
always@(posedge clk or posedge rst)
if(rst)
flag<=0;
else if((cstate==FSM_START&&sampling&&rx_r[2]==1)||(cstate==FSM_STOP&&sampling))
flag<=0;
else if(rx_r[2:1]==2'b10)
flag<=1;
else
flag<=flag;
reg [12:0] cnt;
always@(posedge clk or posedge rst)
if(rst)
cnt<=0;
else if(flag==0 || cnt==CLK/BAUD)
cnt<=0;
else if(flag==1)
cnt<=cnt+1;
reg sampling;
always@(posedge clk or posedge rst)
if(rst)
sampling<=0;
else if(cnt==(CLK/BAUD>>1))
sampling<=1;
else
sampling<=0;
//状态机
localparam FSM_IDEL =0,
FSM_START =1,
FSM_DATA =2,
FSM_PARITY =3,
FSM_STOP =4;
reg [2:0] cstate;
reg [3:0] number=0;
always@(posedge clk or posedge rst)
if(rst)
begin
cstate<=FSM_IDEL;
err<=0;
done<=0;
number<=0;
data<=0;
end
else
case(cstate)
FSM_IDEL : begin
done<=0;
if(flag)
cstate<=FSM_START;
else
cstate<=FSM_IDEL;
end
FSM_START : if(sampling)
if(rx_r[2]==0)
cstate<=FSM_DATA;
else
cstate<=FSM_IDEL;
else
cstate<=FSM_START;
FSM_DATA : if(sampling&&number<DATABITS)
begin
data[number]<=rx_r[2];
number<=number+1;
end
else if(number==DATABITS)
begin
number<=0;
if(ifparity==0)
cstate<=FSM_STOP;
else if(ifparity)
cstate<=FSM_PARITY;
end
else
cstate<=FSM_DATA;
FSM_PARITY : if(sampling)
begin
cstate<=FSM_STOP;
if(parity_value==rx_r[2])
err<=0;
else
err<=1;
end
else
cstate<=FSM_PARITY;
FSM_STOP : if(sampling)
begin
done<=1;
if(rx_r[2])
cstate<=FSM_IDEL;
else
err<=1;
end
else
cstate<=FSM_STOP;
default : begin
cstate<=FSM_IDEL;
err<=0;
done<=0;
number<=0;
data<=0;
end
endcase
reg parity_value;
reg ifparity;
always@(*)
if(rst)
begin
parity_value=0;
ifparity=0;
end
else
case(PARITY)
`NONE : begin
parity_value=0;
ifparity=0;
end
`ODD : begin
parity_value=~(^data);
ifparity=1;
end
`SEVEN : begin
parity_value=^data;
ifparity=1;
end
`SPACE : begin
parity_value=0;
ifparity=1;
end
`MARK : begin
parity_value=1;
ifparity=1;
end
default : begin
parity_value=0;
ifparity=0;
end
endcase
endmodule
uart_tx
下面展示一些 内联代码片
。
`define NONE 0
`define ODD 1
`define EVEN 2
`define SPACE 3
`define MARK 4
`define STOP_ONE 0
`define STOP_ONEHALF 1
`define STOP_TWO 2
module uart_tx
#(
parameter CLK = 50_000_000,
parameter BAUD = 9600,
parameter DATABITS = 8,
parameter PARITY = `NONE,
parameter STOPBITS = `STOP_ONE
)
(
input wire clk,
input wire rst,
input wire [DATABITS-1:0] data,
input wire enable,
output reg tx,
output reg busy //在发送数据的过程中,不接受新的发送任务
);
//缓存外部传输数据
reg [DATABITS-1:0] data_r;
reg [3:0] number=0;
always@(posedge clk or posedge rst)
if(rst)
data_r<=0;
else if(enable && busy==0)
data_r<=data;
else
data_r<=data_r;
reg [13:0] cnt;
localparam CNT_MAX=CLK/BAUD-1;
always@(posedge clk or posedge rst)
if(rst)
cnt<=0;
else if(cnt==CNT_MAX || busy==0 )
cnt<=0;
else if(busy==1)
cnt<=cnt+1;
else
cnt<=cnt;
localparam FSM_IDEL =0,
FSM_START =1,
FSM_DATA =2,
FSM_PARITY =3,
FSM_STOP =4;
reg [2:0] cstate;
reg stop=0;
always@(posedge clk or posedge rst)
if(rst)
begin
cstate<=FSM_IDEL;
tx<=1;
number<=0;
busy<=0;
stop<=0;
end
else
case(cstate)
FSM_IDEL : begin
tx<=1;
if(enable)
begin
busy<=1;
cstate<=FSM_START;
end
else
cstate<=FSM_IDEL;
end
FSM_START : begin
tx<=0;
if(cnt==CNT_MAX)
cstate<=FSM_DATA;
else
cstate<=FSM_START;
end
FSM_DATA : begin
tx<=data_r[number];
if(cnt==CNT_MAX && number<(DATABITS-1))
number<=number+1;
else if(number==(DATABITS-1) && cnt==CNT_MAX)
begin
number<=0;
if(!ifparity)
cstate<=FSM_STOP;
else
cstate<=FSM_PARITY;
end
else
begin
cstate<=FSM_DATA;
number<=number;
end
end
FSM_PARITY : begin
tx<=parity_value;
if(cnt==CNT_MAX)
cstate<=FSM_STOP;
else
cstate<=FSM_PARITY;
end
FSM_STOP : begin
tx<=1;
if(STOPBITS==`STOP_ONE)
begin
if(cnt==CNT_MAX)
begin
busy<=0;
cstate<=FSM_IDEL;
end
else
cstate<=FSM_STOP;
end
else if(STOPBITS==`STOP_ONEHALF)
begin
if(stop==0&&cnt==CNT_MAX)
stop<=1;
else if(stop==1 && cnt<=(CNT_MAX>>1))
begin
stop<=0;
busy<=0;
cstate<=FSM_IDEL;
end
else
cstate<=FSM_STOP;
end
else if(STOPBITS==`STOP_TWO)
begin
if(stop==0&&cnt==CNT_MAX)
stop<=1;
else if(stop==1 && cnt<=CNT_MAX)
begin
stop<=0;
busy<=0;
cstate<=FSM_IDEL;
end
else
cstate<=FSM_STOP;
end
end
default : begin
cstate<=FSM_IDEL;
tx<=1;
number<=0;
busy<=0;
stop<=0;
end
endcase
reg ifparity; //是否有校验位
reg parity_value; //校验位的值
always@(*)
if(rst)
begin
ifparity=0;
parity_value=0;
end
else
case(PARITY)
`NONE : begin
ifparity=0;
parity_value=0;
end
`ODD : begin
ifparity=1;
parity_value=~(^data_r);
end
`EVEN : begin
ifparity=1;
parity_value=^data_r;
end
`SPACE : begin
ifparity=1;
parity_value=0;
end
`MARK : begin
ifparity=1;
parity_value=1;
end
default : begin
ifparity=0;
parity_value=0;
end
endcase
endmodule