实例介绍
【实例简介】
该模块主要通过verilog实现UART串口功能,包括接收和发送
【实例截图】
【核心代码】
odule rs232_tx(
clk_in,
rst_n,
baud_sel,
par_sel,
data_sel,
stop_sel,
mod_en,
tx_en,
data_in,
tx_out,
tx_busy
);
//---------------------------------------------------------//
//system port
input clk_in; //50Mhz
input rst_n;
//input port
input [7:0] baud_sel; //波特率?择
input [3:0] par_sel; //校验位?择
input [3:0] data_sel; //数据位长度?择
input [3:0] stop_sel; //停止位长度?择
input mod_en;
input tx_en; //发送使能
input [7:0] data_in; //数据输入
//output port
output reg tx_out; //串行数据输出
output reg tx_busy; //忙标志位
//---------------------------------------------------------//
//---------------------------------------------------------//
//register and wire
reg [1:0] tx_en_dly;
reg [7:0] baud_sel_r;
reg [3:0] par_sel_r;
reg [3:0] data_sel_r;
reg [3:0] stop_sel_r;
reg mod_en_r;
reg [3:0] current_state;
reg [3:0] next_state;
parameter [3:0] idle = 4'd0;
parameter [3:0] fifo_rd = 4'd1;
parameter [3:0] star_bit = 4'd2;
parameter [3:0] first_bit = 4'd3;
parameter [3:0] second_bit = 4'd4;
parameter [3:0] third_bit = 4'd5;
parameter [3:0] fourth_bit = 4'd6;
parameter [3:0] fifth_bit = 4'd7;
parameter [3:0] sixth_bit = 4'd8;
parameter [3:0] seventh_bit = 4'd9;
parameter [3:0] eighth_bit = 4'd10;
parameter [3:0] parity_bit = 4'd11;
parameter [3:0] stop_bit = 4'd12;
reg [12:0]baud_data; //波特率要计的敿
reg [12:0]simple_2; //1/2波特率计敿
reg [7:0] data_in_r; //数据输入寄存噿
wire par_flag; //数据偶校骿
reg par_temp; //根据配置信息选择的校验位
reg [13:0]stop_L_data; //停止位的长度
reg stop_cnt_en; //停止位计数使胿
reg [13:0]stop_cnt; //停止位计数器
reg baud_cnt_en; //波特率技术器使能
reg [12:0]baud_cnt; //波特率技术器
//-- baud -- cnt data
// 9600 4608
// 14400 3072
// 19200 2304
// 38400 1152
// 56000 790
// 57600 768
// 115200 384
// 128000 346
// 256000 173
assign par_flag = ^data_in_r;
//---------------------------------------------------------//
//模块使能判断
always @(posedge clk_in or negedge rst_n)begin
if(!rst_n)
begin
tx_en_dly <= 2'b0;
mod_en_r <= 1'b0;
end
else
begin
tx_en_dly <= {tx_en_dly[0],tx_en};
mod_en_r <= mod_en;
end
end
//---------------------------------------------------------//
//锁存配置信息
always @(posedge clk_in or negedge rst_n)begin
if(!rst_n)begin
baud_sel_r <= 8'd0;
par_sel_r <= 4'd0;
data_sel_r <= 4'd0;
stop_sel_r <= 4'd0;
data_in_r <= 8'd0;
end
else if((mod_en_r == 1'b1)&&(next_state == idle))begin
data_in_r <= data_in;
baud_sel_r <= baud_sel;
par_sel_r <= par_sel;
data_sel_r <= data_sel;
stop_sel_r <= stop_sel;
end
end
//---------------------------------------------------------//
//波特率计数解枿
always @(posedge clk_in or negedge rst_n)begin
if(!rst_n)begin
baud_data <= 13'd0;
simple_2 <= 13'd0;
end
else begin
simple_2 <= (baud_data >> 1);
case(baud_sel_r)
8'd0: baud_data <= 13'd5208; //9600
8'd1: baud_data <= 13'd3472; //14400
8'd2: baud_data <= 13'd2604; //19200
8'd3: baud_data <= 13'd1302; //38400
8'd4: baud_data <= 13'd892; //56000
8'd5: baud_data <= 13'd868; //57600
8'd6: baud_data <= 13'd434; //115200
8'd7: baud_data <= 13'd390; //128000
8'd8: baud_data <= 13'd195; //256000
default:baud_data <= 13'd5208;
endcase
end
end
//---------------------------------------------------------//
//主状态机
always @(posedge clk_in or negedge rst_n)begin
if(!rst_n)
current_state <= idle;
else
current_state <= next_state;
end
always @(*)begin
if(!rst_n)
next_state = current_state;
case(current_state)
idle:begin
if((tx_en == 1'b1)&&(mod_en_r == 1'b1))
next_state = star_bit;
else
next_state = idle;
end
star_bit:begin
if(baud_cnt == baud_data - 1'b1)
next_state = first_bit;
else
next_state = star_bit;
end
first_bit:begin
if(baud_cnt == baud_data - 1'b1)
next_state = second_bit;
else
next_state = first_bit;
end
second_bit:begin
if(baud_cnt == baud_data - 1'b1)
next_state = third_bit;
else
next_state = second_bit;
end
third_bit:begin
if(baud_cnt == baud_data - 1'b1)
next_state = fourth_bit;
else
next_state = third_bit;
end
fourth_bit:begin
if(baud_cnt == baud_data - 1'b1)begin
if(data_sel_r == 4'd0)
next_state = parity_bit;
else
next_state = fifth_bit;
end else
next_state = fourth_bit;
end
fifth_bit:begin
if(baud_cnt == baud_data - 1'b1)begin
if(data_sel_r == 4'd1)
next_state = parity_bit;
else
next_state = sixth_bit;
end else
next_state = fifth_bit;
end
sixth_bit:begin
if(baud_cnt == baud_data - 1'b1)begin
if(data_sel_r == 4'd2)
next_state = parity_bit;
else
next_state = seventh_bit;
end else
next_state = sixth_bit;
end
seventh_bit:begin
if(baud_cnt == baud_data - 1'b1)begin
if(data_sel_r == 4'd3)
next_state = parity_bit;
else
next_state = eighth_bit;
end else
next_state = seventh_bit;
end
eighth_bit:begin
if(baud_cnt == baud_data - 1'b1)
next_state = parity_bit;
else
next_state = eighth_bit;
end
parity_bit:begin
if(par_sel_r == 4'd0)
next_state = stop_bit;
else begin
if(baud_cnt == baud_data - 4'd2)
next_state = stop_bit;
else
next_state = parity_bit;
end
end
stop_bit:begin
if(stop_cnt == stop_L_data - 4'd3)
next_state = idle;
else
next_state = stop_bit;
end
default:
next_state = current_state;
endcase
end
//---------------------------------------------------------//
//并串转换数据输出
always @(posedge clk_in or negedge rst_n)begin
if(!rst_n)
tx_out <= 1'b1;
else
case(next_state)
star_bit: tx_out <= 1'b0;
first_bit: tx_out <= data_in_r[0];
second_bit: tx_out <= data_in_r[1];
third_bit: tx_out <= data_in_r[2];
fourth_bit: tx_out <= data_in_r[3];
fifth_bit: tx_out <= data_in_r[4];
sixth_bit: tx_out <= data_in_r[5];
seventh_bit: tx_out <= data_in_r[6];
eighth_bit: tx_out <= data_in_r[7];
parity_bit: tx_out <= par_temp;
stop_bit: tx_out <= 1'b1;
default: tx_out <= 1'b1;
endcase
end
//---------------------------------------------------------//
//---------------------------------------------------------//
//奇偶校验位生房
always @(posedge clk_in or negedge rst_n)begin
if(!rst_n)
par_temp <= 1'b0;
else if(par_sel_r == 4'd2)
par_temp <= par_flag;
else if(par_sel_r == 4'd3)
par_temp <= ~par_flag;
end
//---------------------------------------------------------//
//---------------------------------------------------------//
//计算停止位长庿
always @(posedge clk_in or negedge rst_n)begin
if(!rst_n)
stop_L_data <= 14'd0;
else
case(stop_sel_r)
4'd0: stop_L_data <= baud_data;
4'd1: stop_L_data <= (baud_data simple_2);
4'd2: stop_L_data <= (baud_data baud_data);
default:stop_L_data <= baud_data;
endcase
end
//---------------------------------------------------------//
//---------------------------------------------------------//
//停止位计数器
always @(posedge clk_in or negedge rst_n)begin
if(!rst_n)
stop_cnt_en <= 1'b0;
else if(next_state == stop_bit)
stop_cnt_en <= 1'b1;
else if(next_state == idle)
stop_cnt_en <= 1'b0;
end
always @(posedge clk_in or negedge rst_n)begin
if(!rst_n)
stop_cnt <= 14'd0;
else if(stop_cnt_en == 1'b1)
stop_cnt <= stop_cnt 1'b1;
else
stop_cnt <= 14'd0;
end
//---------------------------------------------------------//
//---------------------------------------------------------//
//设备忙状态标志位
always @(posedge clk_in or negedge rst_n)begin
if(!rst_n)
tx_busy <= 1'b0;
else if(next_state == star_bit)
tx_busy <= 1'b1;
else if((next_state == stop_bit)&&(stop_cnt == stop_L_data - 4'd10))
tx_busy <= 1'b0;
else
tx_busy <= tx_busy;
end
//---------------------------------------------------------//
//---------------------------------------------------------//
//波特率计数器
always @(posedge clk_in or negedge rst_n)begin
if(!rst_n)
baud_cnt_en <= 1'b0;
else if(next_state == star_bit)
baud_cnt_en <= 1'b1;
else if(next_state == stop_bit)
baud_cnt_en <= 1'b0;
end
always @(posedge clk_in or negedge rst_n)begin
if(!rst_n)
baud_cnt <= 13'd0;
else if(baud_cnt == baud_data)
baud_cnt <= 13'd0;
else if(baud_cnt_en == 1'b1)
baud_cnt <= baud_cnt 1'b1;
else
baud_cnt <= 13'd0;
end
endmodule
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论