ISSP调试工具
串口(异步串行通信接口):IIC(集成电路总线)、SPI(串行外围总线)、UART(通用异步收发器)
UART发送
UART发送
FPGA通过URAT串口发送协议向PC发送数据。发送:并行数据转串行数据
UART发送一个字节时序图:
串口发送总模块
Clk时钟信号,Rst_n复位信号,Bps_set四位选择波特率信号,Con_en使能信号,Data_in8位输入信号. Rs232_tx输出信号,Done_tx输出一次完整11位Rs232_tx数据完成信号,Uart_state输出完所有信号完成标志信号.
数字设计图
串口发送模块
module UART_TX(
Clk,
Rst_n,
Bps_set,
Con_en,
Data_in,
Rs232_tx,
Done_tx,
Uart_state
);
input Clk;
input Rst_n;
input [2:0]Bps_set;
input Con_en;
input [7:0]Data_in;
output reg Rs232_tx;
output reg Done_tx;
output reg Uart_state;
reg [15:0]count; //计数器定值
reg [15:0]high_count; //计数值
reg [7:0]Data_in_r;
reg bps_clk;
reg [3:0]bps_count;
localparam start_bite = 1'b0;
localparam stop_bite = 1'b1;
//查找表输出计数值
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
count <= 16'd5207;
else begin
case(Bps_set)
0: count <= 16'd5207; //波特率9600
1: count <= 16'd2603; //波特率19200
2: count <= 16'd1301; //波特率38400
3: count <= 16'd865; //波特率57600
4: count <= 16'd433; //波特率115200
default : count <= 16'd5207;
endcase
end
//产生Uart_state使能信号
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
Uart_state <= 1'b0;
else if(Con_en)
Uart_state <= 1'b1;
else if(bps_count == 4'd11)
Uart_state <= 1'b0;
else Uart_state <= Uart_state;
//计数满产生bps_clk信号
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
high_count <= 0;
else if(Uart_state) begin
if(high_count == count)
high_count <= 0;
else high_count <= high_count + 1'b1;
end
else high_count <= 0;
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
bps_clk <= 1'b0;
else if(high_count == 16'b1)
bps_clk <= 1'b1;
else bps_clk <= 1'b0;
//计数bps_clk的高电平到11计数满为0 产生Done_tx高点平信号
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
bps_count <= 4'b0;
else if(bps_count == 4'd11)
bps_count <= 4'b0;
else if(bps_clk )
bps_count <= bps_count + 4'b1;
else bps_count <= bps_count;
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
Done_tx <= 1'b0;
else if(bps_count == 4'd11)
Done_tx <= 1;
else Done_tx <= 0;
always @(posedge Clk or negedge Rst_n )
if(!Rst_n)
Data_in_r <= 0;
else if(Con_en)
Data_in_r <= Data_in ;
else Data_in_r <= Data_in_r;
//十选一多路选择器
always @(posedge Clk or negedge Rst_n)
if(!Rst_n)
Rs232_tx <= 1'b1;
else begin
case(bps_count)
0: Rs232_tx <= 1'b1;
1: Rs232_tx <= start_bite;
2: Rs232_tx <= Data_in_r[0];
3: Rs232_tx <= Data_in_r[1];
4: Rs232_tx <= Data_in_r[2];
5: Rs232_tx <= Data_in_r[3];
6: Rs232_tx <= Data_in_r[4];
7: Rs232_tx <= Data_in_r[5];
8: Rs232_tx <= Data_in_r[6];
9: Rs232_tx <= Data_in_r[7];
10: Rs232_tx <= stop_bite;
default : Rs232_tx <= 1'b1;
endcase
end
endmodule
串口发送仿真模块
`timescale 1ns/1ns
`define clk_period 20
module UART_TX_tb;
reg Clk;
reg Rst_n;
reg [2:0]Bps_set;
reg Con_en;
reg [7:0]Data_in;
wire Rs232_tx;
wire Done_tx;
wire Uart_state;
UART_TX UART_TX0(
.Clk(Clk),
.Rst_n(Rst_n),
.Bps_set(Bps_set),
.Con_en(Con_en),
.Data_in(Data_in),
.Rs232_tx(Rs232_tx),
.Done_tx(Done_tx),
.Uart_state(Uart_state)
);
initial Clk = 1;
always#(`clk_period/2) Clk = ~Clk;
initial begin
Rst_n = 1'b0;
Data_in = 8'b0;
Con_en = 1'b0;
Bps_set = 3'd4;
#(`clk_period*20+1);
Rst_n = 1'b1;
#(`clk_period*20+1);
Data_in = 8'hae;
Con_en = 1'b1;
#(`clk_period);
Con_en = 1'b0;
@(posedge Done_tx)
#(`clk_period*2000);
Data_in = 8'h5b;
Con_en = 1'b1;
#(`clk_period);
Con_en = 1'b0;
@(posedge Done_tx)
#(`clk_period*2000);
$stop;
end
endmodule
仿真结果
可以看到bps_count为2时Rs232_tx为Data_in最低位0,bps_count为3时Rs232_tx为Data_in次位1,以此类推。
按键消抖模块
module Key_shake(Clk,Rst_n,Key_in,Key_flag,Key_data);
input Clk;
input Rst_n;
input Key_in;
output reg Key_flag; //当按键按下20ms消除抖动成功后产生一个脉冲flag信号,检测到产生flag信号后产生按键按下低电平。
output reg Key_data;
reg [3:0]state;
reg [19:0]count; //寄存器计数
reg count_start;//时能计时
reg count_full;//计满脉冲信号
reg reg0,reg1;
reg key_in_now0,key_in_now1;
wire rise,fall;
localparam
High_pulse = 4'b0001, //高电平稳定状态
Low_eliminate = 4'b0010, //键下降沿稳定状态
Low_pulse = 4'b0100, //低电平稳定状态
High_eliminate = 4'b1000; //键上升沿稳定状态
always @(posedge Clk or negedge Rst_n) //对输入按键信号做同步处理,消除异步信号亚稳态的影响。
if(!Rst_n) begin
key_in_now0 <= 1'b0;
key_in_now1 <=1'b0;
end
else begin
key_in_now0 <= Key_in;
key_in_now1 <= key_in_now0;
end
always @(posedge Clk or negedge Rst_n) //脉冲边沿检测 两个寄存器
if(!Rst_n) begin
reg0 <= 1'b0;
reg1 <=1'b0;
end
else begin
reg0 <= key_in_now1;
reg1 <= reg0;
end
assign fall = !reg0 & reg1; //检测到下降沿
assign rise = reg0 & !reg1; //检测到上升沿
always @(posedge Clk or negedge Rst_n) //20ms计数器
if(!Rst_n)
count <= 20'b0;
else if(count_start)
count <= count + 20'b1;
else count <= 20'b0;
always @(posedge Clk or negedge Rst_n) //20ms计数器计数满标志脉冲信号
if(!Rst_n)
count_full <= 1'b0;
else if(count == 99_9999)
count_full <= 1'b1;
else count_full <= 1'b0;
always @(posedge Clk or negedge Rst_n)
if(!Rst_n) begin
Key_data <= 1'b1;
state <= High_pulse;
Key_flag <= 1'b0;
count_start <= 1'b0;
end
else case(state)
High_pulse : begin Key_flag <= 0;
Key_data <= 1'b1;
if(fall) begin
state <= Low_eliminate;
count_start <= 1'b1; //使能开始20ms计数
end
else state <= High_pulse;
end
Low_eliminate :
if(count_full) begin
state <= Low_pulse;
Key_flag <= 1'b1;
Key_data <= 1'b0;
count_start <= 1'b0; //关闭使能20ms计数
end
else begin
if(rise) begin
state <= High_pulse;
count_start <= 1'b0; //关闭使能20ms计数
end
else
state <= Low_eliminate;
end
Low_pulse: begin Key_flag <= 1'b0;
if(rise) begin
state <= High_eliminate;
count_start <= 1'b1; //开始计时
end
else state <= Low_pulse;
end
High_eliminate :
if(count_full) begin
Key_data <= 1'b1;
Key_flag <= 1'b1;
state <= High_pulse;
end
else begin
if(fall) begin
state <= Low_pulse;
count_start <= 1'b0;
end else
state <= High_eliminate;
end
default : begin
state <= High_pulse; //默认状态
count_start <= 1'b0;
Key_data <= 1'b1;
Key_flag <= 1'b0;
end
endcase
endmodule
顶层模块
调用IP核。
module UART_tx_top(
Clk,
Rst_n,
Rs232_tx,
Key_in0,
led
);
input Clk;
input Rst_n;
input Key_in0;
output Rs232_tx;
output led;
wire Con_en;
wire [7:0]Data_in;
wire Key_flag0;
wire Key_data0;
assign Con_en = Key_flag0 & !Key_data0;
Key_shake Key_shake0(
.Clk(Clk),
.Rst_n(Rst_n),
.Key_in(Key_in0),
.Key_flag(Key_flag0),
.Key_data(Key_data0)
);
UART_TX UART_TX0(
.Clk(Clk),
.Rst_n(Rst_n),
.Bps_set(3'd0),
.Con_en(Con_en),
.Data_in(Data_in),
.Rs232_tx(Rs232_tx),
.Done_tx(),
.Uart_state(led)
);
issp issp0(
.probe(),
.source(Data_in)
);
endmodule
FPGA发送信号PC端
更多推荐
FPGA入门——串口发送模块与验证
发布评论