代碼注釋有些匆忙,如有錯(cuò)誤注釋還請(qǐng)批評(píng),僅作參考
Uart比較簡(jiǎn)單,所以僅對(duì)tx作比較詳細(xì)的注釋,但里面一些內(nèi)容還是值得新手學(xué)習(xí)的
1開始位(低電平)+8位數(shù)據(jù)+1停止位(高電平,這里選的是一個(gè)周期高電平,也可兩個(gè))(無校驗(yàn)位)
1、prescale是完成一個(gè)bit需要主時(shí)鐘計(jì)數(shù)的次數(shù)(其和主時(shí)鐘以及波特率之間的關(guān)系參考網(wǎng)上文章)
2、進(jìn)入uart模塊的異步信號(hào),最好使用提供的同步器同步
3、異步復(fù)位信號(hào)最好使用提供的同步器同步
4、波特率任意選,只要時(shí)鐘夠大,能夠符合誤碼率計(jì)算即可,這里使用的是125Mhz
5、基本的思想就是移位
6、傳輸條件就是握手
7、如果使用Xlinx的片子,建議使用全局時(shí)鐘資源(IBUFG后面連接BUFG的方法是最基本的全局時(shí)鐘資源的使用方法)
8、這個(gè)完整的代碼就是使用IBUFG+BUFG
9、傳輸雖然簡(jiǎn)單,但對(duì)于新手來講,還是有挺多的知識(shí)點(diǎn)值得學(xué)習(xí)的點(diǎn)
10、公眾號(hào)只是對(duì)代碼進(jìn)行了簡(jiǎn)單注釋
UART的發(fā)送數(shù)據(jù)模塊
// 歡迎大家關(guān)注公眾號(hào):AriesOpenFPGA
// Q群:808033307
// Language: Verilog 2001
// 代碼注釋有些匆忙,如有錯(cuò)誤注釋還請(qǐng)批評(píng),僅作參考
// UART
// 1開始位+8位數(shù)據(jù)+1停止位(無校驗(yàn))
// prescale是完成一個(gè)bit需要主時(shí)鐘計(jì)數(shù)的次數(shù)(其和主時(shí)鐘以及波特率之間的關(guān)系參考網(wǎng)上文章)
// 進(jìn)入uart模塊的異步信號(hào),最好使用提供的同步器同步
// 異步復(fù)位信號(hào)最好使用提供的同步器同步
// 波特率任意選,只要時(shí)鐘夠大,能夠符合誤碼率計(jì)算即可,這里使用的是125M
// 基本的思想就是移位
// 傳輸條件就是握手
// 如果使用Xlinx的片子,建議使用全局時(shí)鐘資源(IBUFG后面連接BUFG的方法是最基本的全局時(shí)鐘資源的使用方法)
// 這個(gè)完整的代碼就是使用IBUFG+BUFG
// 傳輸雖然簡(jiǎn)單,但對(duì)于新手來講,還是有挺多的知識(shí)點(diǎn)值得學(xué)習(xí)的
// 公眾號(hào)只是對(duì)代碼進(jìn)行了簡(jiǎn)單注釋
`timescale 1ns / 1ps
/* AXI4-Stream UART */
module uart_tx #
(
parameter DATA_WIDTH = 8
)
(
input wire clk, // 系統(tǒng)時(shí)鐘
input wire rst, // 復(fù)位信號(hào)
/* AXI input */
input wire [DATA_WIDTH-1:0] s_axis_tdata, // 輸入到這個(gè)模塊準(zhǔn)備發(fā)送出去的數(shù)據(jù)
input wire s_axis_tvalid, // 有數(shù)據(jù)要輸入到這個(gè)模塊
output wire s_axis_tready, // 該模塊準(zhǔn)備好接收數(shù)據(jù)
output wire txd, // UART interface
output wire busy, // Status 線忙
input wire [15:0] prescale // Configuration 預(yù)分度
);
reg s_axis_tready_reg = 0;
reg txd_reg = 1;
reg busy_reg = 0;
reg [DATA_WIDTH:0] data_reg = 0;
reg [18:0] prescale_reg = 0;
reg [3:0] bit_cnt = 0;
assign s_axis_tready = s_axis_tready_reg;
assign txd = txd_reg;
assign busy = busy_reg;
always @(posedge clk)
begin
if (rst)
begin
s_axis_tready_reg <= 0; // 從機(jī)沒有準(zhǔn)備好發(fā)送
txd_reg <= 1; // 發(fā)送線拉高
prescale_reg <= 0; //
bit_cnt <= 0; // 位計(jì)數(shù)器初始化為0
busy_reg <= 0; // 復(fù)位后為不忙狀態(tài)
end
else
begin
if (prescale_reg > 0)
begin
s_axis_tready_reg <= 0;
prescale_reg <= prescale_reg - 1;
end
else if (bit_cnt == 0) //比特計(jì)數(shù)器為0
begin
s_axis_tready_reg <= 1; // 從機(jī)把ready信號(hào)拉高
busy_reg <= 0; // 忙信號(hào)拉低無效
if (s_axis_tvalid) // 如果從機(jī)準(zhǔn)備好接收數(shù)據(jù)
begin
s_axis_tready_reg <= !s_axis_tready_reg; //
prescale_reg <= (prescale << 3)-1; //
bit_cnt <= DATA_WIDTH+1; // 一共10次計(jì)數(shù)
data_reg <= {1'b1, s_axis_tdata}; //
txd_reg <= 0; // 起始位0(起始位tx拉低,停止位拉高)
busy_reg <= 1; // 開始傳輸后,傳輸線進(jìn)入忙狀態(tài)
end
end
else
begin
if (bit_cnt > 1) //
begin
bit_cnt <= bit_cnt - 1;
prescale_reg <= (prescale << 3)-1; // 經(jīng)過(prescale << 3)-1次的系統(tǒng)時(shí)鐘計(jì)數(shù),完成一位的移位
{data_reg, txd_reg} <= {1'b0, data_reg}; // 移位操作
end
else if (bit_cnt == 1)
begin
bit_cnt <= bit_cnt - 1;
prescale_reg <= (prescale << 3);
txd_reg <= 1; // 停止位1
end
end
end
end
endmodule
UART的接收模塊(不詳細(xì)講解)
Language: Verilog 2001
1ns / 1ps
/*
AXI4-Stream UART
*/
module uart_rx #
(
parameter DATA_WIDTH = 8
)
(
input wire clk,
input wire rst,
AXI output */
output wire [DATA_WIDTH-1:0] m_axis_tdata,
output wire m_axis_tvalid,
input wire m_axis_tready,
UART interface */
input wire rxd,
Status */
output wire busy,
output wire overrun_error,
output wire frame_error,
Configuration */
input wire [15:0] prescale
);
reg [DATA_WIDTH-1:0] m_axis_tdata_reg = 0;
reg m_axis_tvalid_reg = 0;
reg rxd_reg = 1;
reg busy_reg = 0;
reg overrun_error_reg = 0;
reg frame_error_reg = 0;
reg [DATA_WIDTH-1:0] data_reg = 0;
reg [18:0] prescale_reg = 0;
reg [3:0] bit_cnt = 0;
assign m_axis_tdata = m_axis_tdata_reg;
assign m_axis_tvalid = m_axis_tvalid_reg;
assign busy = busy_reg;
assign overrun_error = overrun_error_reg;
assign frame_error = frame_error_reg;
always @(posedge clk)
begin
if (rst) // 初始化各種參數(shù)
begin
m_axis_tdata_reg <= 0;
m_axis_tvalid_reg <= 0;
rxd_reg <= 1;
prescale_reg <= 0;
bit_cnt <= 0;
busy_reg <= 0;
overrun_error_reg <= 0;
frame_error_reg <= 0;
end
else
begin
rxd_reg <= rxd;
overrun_error_reg <= 0;
frame_error_reg <= 0;
if (m_axis_tvalid && m_axis_tready) // 準(zhǔn)備有數(shù)據(jù)要發(fā)以及準(zhǔn)被好發(fā)
begin
m_axis_tvalid_reg <= 0;
end
if (prescale_reg > 0) //
begin
prescale_reg <= prescale_reg - 1;
end
else if (bit_cnt > 0)
begin
if (bit_cnt > DATA_WIDTH+1)
begin
if (!rxd_reg) // 實(shí)際的read為0時(shí),開始計(jì)數(shù)bit
begin
bit_cnt <= bit_cnt - 1;
prescale_reg <= (prescale << 3)-1; //prescale是16位移3位減1位,因?yàn)閜rescale_reg
end
else
begin
bit_cnt <= 0;
prescale_reg <= 0;
end
end
else if (bit_cnt > 1)
begin
bit_cnt <= bit_cnt - 1;
prescale_reg <= (prescale << 3)-1;
data_reg <= {rxd_reg, data_reg[DATA_WIDTH-1:1]};
end
else if (bit_cnt == 1)
begin
bit_cnt <= bit_cnt - 1;
if (rxd_reg)
begin
m_axis_tdata_reg <= data_reg;
m_axis_tvalid_reg <= 1;
overrun_error_reg <= m_axis_tvalid_reg;
end
else
begin
frame_error_reg <= 1;
end
end
end
else
begin
busy_reg <= 0;
if (!rxd_reg)
begin
prescale_reg <= (prescale << 2)-2;
bit_cnt <= DATA_WIDTH + 2;
data_reg <= 0;
busy_reg <= 1;
end
end
end
end
endmodule
UART頂層
Language: Verilog 2001
1ns / 1ps
/*
AXI4-Stream UART
*/
module uart #
(
parameter DATA_WIDTH = 8
)
(
input wire clk,
input wire rst,
/*
AXI input
*/
input wire [DATA_WIDTH-1:0] s_axis_tdata,
input wire s_axis_tvalid,
output wire s_axis_tready,
/*
AXI output
*/
output wire [DATA_WIDTH-1:0] m_axis_tdata,
output wire m_axis_tvalid,
input wire m_axis_tready,
/*
UART interface
*/
input wire rxd,
output wire txd,
/*
Status
*/
output wire tx_busy,
output wire rx_busy,
output wire rx_overrun_error,
output wire rx_frame_error,
/*
Configuration
*/
input wire [15:0] prescale
);
uart_tx #(
.DATA_WIDTH(DATA_WIDTH)
)
uart_tx_inst (
.clk(clk),
.rst(rst),
axi input
.s_axis_tdata(s_axis_tdata),
.s_axis_tvalid(s_axis_tvalid),
.s_axis_tready(s_axis_tready),
output
.txd(txd),
status
.busy(tx_busy),
configuration
.prescale(prescale)
);
uart_rx #(
.DATA_WIDTH(DATA_WIDTH)
)
uart_rx_inst (
.clk(clk),
.rst(rst),
axi output
.m_axis_tdata(m_axis_tdata),
.m_axis_tvalid(m_axis_tvalid),
.m_axis_tready(m_axis_tready),
input
.rxd(rxd),
status
.busy(rx_busy),
.overrun_error(rx_overrun_error),
.frame_error(rx_frame_error),
configuration
.prescale(prescale)
);
endmodule
同步(異步復(fù)位)模塊
Language: Verilog-2001
很常用的模塊
1 ns / 1 ps
/*
Synchronizes an active-high asynchronous reset signal to a given clock by
using a pipeline of N registers.
*/
module sync_reset #(
parameter N=2 // depth of synchronizer
)(
input wire clk,
input wire rst,
output wire sync_reset_out
);
reg [N-1:0] sync_reg = {N{1'b1}};
assign sync_reset_out = sync_reg[N-1];
always @(posedge clk or posedge rst) begin
if (rst)
sync_reg <= {N{1'b1}};
else
sync_reg <= {sync_reg[N-2:0], 1'b0};
end
endmodule
同步(異步信號(hào))模塊
// Language: Verilog-2001
//很常用的模塊
`timescale 1 ns / 1 ps
/*
* Synchronizes an asyncronous signal to a given clock by using a pipeline of
* two registers.
*/
module sync_signal
parameter WIDTH=1, // width of the input and output signals
parameter N=2 // depth of synchronizer
)(
input wire clk,
input wire [WIDTH-1:0] in,
output wire [WIDTH-1:0] out
);
reg [WIDTH-1:0] sync_reg[N-1:0];
/*
* The synchronized output is the last register in the pipeline.
*/
assign out = sync_reg[N-1];
integer k;
always @(posedge clk) begin
sync_reg[0] <= in;
for (k = 1; k < N; k = k + 1) begin
sync_reg[k] <= sync_reg[k-1];
end
end
endmodule
審核編輯 :李倩
-
Verilog
+關(guān)注
關(guān)注
28文章
1351瀏覽量
110310 -
uart
+關(guān)注
關(guān)注
22文章
1243瀏覽量
101687 -
代碼
+關(guān)注
關(guān)注
30文章
4823瀏覽量
68953
原文標(biāo)題:Uart協(xié)議及Verilog代碼
文章出處:【微信號(hào):zhuyandz,微信公眾號(hào):FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論