import serial
while(1):try:#打开串口
ser = serial.Serial("COM3",115200,timeout=0.5)print("打开串口",ser)#向串口写入数据
data =input("输入发送的数据:")
ser.write(data.encode('gbk'))#接受数据
receive_data = ser.readline()
receive = receive_data.decode('gbk')print("接收到的数据为:",receive)
ser.close()#关闭串口except Exception as e:print("打开串口失败!\n",e)
二、打开Quartus,在FPGA上运行uart代码
1.顶层文件
module control(input clk,input rst_n,input[7:0] rx_din,input rx_vld,//接受信号发送出去的有效标志
input busy,
output reg [7:0] tx_din,
output reg tx_vld //?为什么是reg
);
parameter SEND_BYTE =8;//FIFO中每存够8字节数据,就连续发送一次
//中间信号定义
reg rdreq_sig;//?
wire [7:0] data_sig;
wire wrreq_sig;
wire empty_sig;
wire full_sig;
wire [7:0] q_sig;
wire [7:0] usedw_sig;
reg rdreq_sig_flag;//?
//rdreq_sig_flag 读请求标志
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
rdreq_sig_flag <=1'b0;
end
elseif(usedw_sig >= SEND_BYTE)begin
rdreq_sig_flag <=1'b1;
end
elseif(empty_sig) begin
rdreq_sig_flag <=1'b0;
end
end
//rdreq_sig 读信号 (随时可以读 ,只要有数据进来且满足对应条件 读请求标志拉高&& 非空 && busy为低电平)
always @(*)begin
if(rdreq_sig_flag && empty_sig ==1'b0 && busy == 1'b0)begin
rdreq_sig <=1'b1;
end
else begin
rdreq_sig <=1'b0;
end
end
//tx_din
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
tx_din <=1'b0;
end
else begin
tx_din <= q_sig;
end
end
//tx_vld
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
tx_vld <=1'b0;
end
elseif(rdreq_sig)begin
tx_vld <=1'b1;
end
else begin
tx_vld <=1'b0;
end
end
assign wrreq_sig = rx_vld && full_sig ==1'b0;//接受到有效数据的发送请求 && fifo没满
assign data_sig = rx_din;
fifo fifo_inst (.aclr (~rst_n ),//高电平有效
.clock ( clk ),.data ( data_sig ),.rdreq ( rdreq_sig ),.wrreq ( wrreq_sig ),.empty ( empty_sig ),.full ( full_sig ),.q ( q_sig ),.usedw ( usedw_sig ));
endmodule
2.uart_rx接收模块
module uart_rx(input clk,input rst_n,input[2:0] baud_set,input din,//串行的输入数据
output reg [7:0] rx_dout,//8bit接收数据输出
output reg rx_vld //接收数据输出有效
);//参数定义 每个波特率下计数器最大计数值
localparam BPS_115200 =434,
BPS_57600 =868,
BPS_38400 =1302,
BPS_19200 =2604,
BPS_9600 =5208;//中间信号
reg [12:0] cnt_bps;
wire add_cnt_bps;
wire end_cnt_bps;
reg [9:0] cnt_bit;
wire add_cnt_bit;
wire end_cnt_bit;
reg [12:0] rx_bps;//
reg [9:0] rx_data_r;//接受一帧数据(起始位,数据位,停止位)
reg din_r0;//同步
reg din_r1;//打拍
reg din_r2;
wire nedge;
reg rx_flag;
always @(*)begin
case(baud_set)0:rx_bps = BPS_115200;1:rx_bps = BPS_57600;2:rx_bps = BPS_38400;3:rx_bps = BPS_19200;4:rx_bps = BPS_9600;
default : rx_bps = BPS_115200;
endcase
end
//cnt_bps 计数器
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_bps <=0;
end
elseif(add_cnt_bps)begin
if(end_cnt_bps)begin
cnt_bps <=0;
end
else begin
cnt_bps <= cnt_bps +1;
end
end
end
assign add_cnt_bps = rx_flag ;
assign end_cnt_bps = add_cnt_bps && cnt_bps == rx_bps -1;//同步 打拍
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
din_r0 <=1'b1;
din_r1 <=1'b1;
end
else begin
din_r0 <= din;
din_r1 <= din_r0;//打拍
din_r2 <= din_r1;
end
end
//检测到下降沿
assign nedge =~din_r1 & din_r2;//rx_flag
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
rx_flag <=1'b0;
end
elseif(nedge && rx_flag ==1'b0 )begin
rx_flag <=1'b1;
end
elseif(end_cnt_bit && rx_flag ==1'b1)begin
rx_flag <=1'b0;
end
end
//cnt_bit 计数器
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_bit <=0;
end
elseif(add_cnt_bit)begin
if(end_cnt_bit)begin
cnt_bit <=0;
end
else begin
cnt_bit <= cnt_bit +1;
end
end
end
assign add_cnt_bit = end_cnt_bps;
assign end_cnt_bit = add_cnt_bit &&(cnt_bit ==10-1|| rx_data_r[0]);//rx_data_r
always @(posedge clk or negedge rst_n)begin
if(!rst_n) begin
rx_data_r <=0;
end
elseif(rx_flag && cnt_bps ==(cnt_bps>>1))begin
rx_data_r[cnt_bit]<= din ;
end
end
//rx_dout
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
rx_dout <=0;
end
elseif(end_cnt_bit)begin
rx_dout <= rx_data_r[8:1];
end
end
//rx_vld
always @(posedge clk or negedge rst_n) begin
if(!rst_n)begin
rx_vld <=1'b0;
end
elseif(end_cnt_bit)begin
rx_vld <=1'b1;
end
else begin
rx_vld <=1'b0;
end
end
endmodule
3.uart发送模块
module uart_tx(input clk,input rst_n,input[2:0] baud_set,input[7:0] tx_din,//发送数据(8bit)input tx_vld,//发送数据有效指示标志(发送请求)
output reg tx_dout ,
output reg busy
);//参数定义 每个波特率下计数器最大计数值
localparam BPS_115200 =434,
BPS_57600 =868,
BPS_38400 =1302,
BPS_19200 =2604,
BPS_9600 =5208;//中间信号
reg [12:0] cnt_bps;//波特率计数器
wire add_cnt_bps;
wire end_cnt_bps;
reg [3:0] cnt_bit;//bit计数器 0-9
wire add_cnt_bit;
wire end_cnt_bit;
reg tx_flag;
reg [12:0] tx_bps;
reg [9:0] tx_data_r;//表示一帧的数据(10bit)
//tx_bps用组合逻辑做一个波特率选择器
always @ (*)begin
case(baud_set)0: tx_bps = BPS_115200;1: tx_bps = BPS_57600;2: tx_bps = BPS_38400;3: tx_bps = BPS_19200;4: tx_bps = BPS_9600;
default : tx_bps = BPS_115200;
endcase
end
//cnt_bps 计数器
always @ (posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_bps <=0;
end
elseif(add_cnt_bps)begin
if(end_cnt_bps)
cnt_bps <=0;else
cnt_bps <= cnt_bps +1;
end
end
assign add_cnt_bps = tx_flag ;
assign end_cnt_bps = add_cnt_bps && cnt_bps == tx_bps -1;//cnt_bit 计数器
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
cnt_bit <=0;
end
elseif(add_cnt_bit)begin
if(end_cnt_bit)
cnt_bit <=0;else
cnt_bit <= cnt_bit +1;
end
end
assign add_cnt_bit = end_cnt_bps;
assign end_cnt_bit = add_cnt_bit && cnt_bit ==10-1;//tx_flag
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
tx_flag <=1'b0;
end
elseif(tx_vld)//当有发送请求时,flag =1;
tx_flag <=1'b1;elseif(end_cnt_bit)//当10bit数据发送完的时候 tx_flag =0;
tx_flag <=1'b0;
end
//tx_dout
//assign tx_data_r = tx_vld?{1'b1,tx_din,1'b0}:tx_data_r;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
tx_data_r <=0;
end
elseif(tx_vld)begin
tx_data_r <={1'b1,tx_din,1'b0};
end
end
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
tx_dout <=1'b1;//初始状态为高电平 ?原因:如果是低电平的话 ,当下一次发送数据时,就会误以为是起始位
end
elseif(tx_flag && cnt_bps ==2-1)begin //发送信号拉高且bps计数器开始计数时
tx_dout <= tx_data_r[cnt_bit];
end
else begin
tx_dout <= tx_dout;
end
end
/*always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
busy <=0;
end
elseif(tx_vld || tx_flag)begin
busy <=1'b1;
end
else begin
busy <=0
end
end*///busy
always @(*)begin
if(tx_vld || tx_flag)begin
busy =1'b1;
end
else begin
busy =0;
end
end
endmodule