verilog簡單實現串列埠
阿新 • • 發佈:2019-01-07
//uart 2017.10.7 傳送接收到的資料
//波特率9600 一個停止位 無奇偶校驗
//DE2板子
/*
rx GPIO_K25 0 left -----tx
tx GPIO_K26 1 right -----rx
GND 右邊第6 或者倒數第6
*/
//復位不成功 ????? 復位按鍵有問題 靠右按即可復位
//特別注意 如果一個條件中同時給一個暫存器賦不同的值 結果不確定
//以下是錯誤程式碼例子 tx_num
//同時賦值 這裡加一 下面賦值0
/*
tx_num<=tx_num+1'b1;
case(tx_num)
0:tx<=1'b0;
1:tx<=tx_data[0];
2:tx<=tx_data[1];
3:tx<=tx_data[2];
4:tx<=tx_data[3];
5:tx<=tx_data[4];
6:tx<=tx_data[5];
7:tx<=tx_data[6];
8:tx<=tx_data[7];
9:begin tx<=1'b1; tx_num<=4'b0; end
*/
//一些小的演算法問題 畫個時序圖 標出各個點暫存器的值
//對照程式看是否正確 特別是需要判斷且改變狀態的點
//以下是程式碼
//----------------------程式碼------------------
module uart(
clk, //50Mhz
rst_n, //reset
rx, //input
tx, //ouptut
sw //測試是否收到資料
);
input clk,rst_n;
input rx;
output reg tx;
//測試是否收到資料
output wire [7:0] sw;
//-----------------檢測是否有資料來--------
//邊沿檢測
wire rx_start;
reg rx1;
[email protected](posedge clk or negedge rst_n)
begin
if(!rst_n) rx1<=1'b0;
else rx1<=rx;
end
assign rx_start = ~rx & rx1;
//-------------------波特率控制------------
wire bps_start;
reg bps_start_rx,bps_start_tx;
reg [3:0] rx_num,tx_num; // 2^4-1=15
[email protected](posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
bps_start_rx<=1'b0;
bps_start_tx<=1'b0;
end
else if(rx_start) bps_start_rx<=1'b1;
//接收完資料後 開始傳送資料
else if(rx_num==10)
begin
bps_start_rx<=1'b0;
bps_start_tx<=1'b1;
end
//傳送完資料後 無需產生波特率
else if(tx_num==10)
bps_start_tx<=1'b0;
end
assign bps_start = bps_start_rx|bps_start_tx;
//------------------產生波特率--------------
//9600
parameter bps_cnt=5208; //50Mhz / 9600 = 5208.3......
parameter bps_cnt_half=2604;
reg [12:0] cnt;
[email protected](posedge clk or negedge rst_n)
begin
if(!rst_n) cnt<=13'b0;
else if(cnt==bps_cnt) cnt<=13'b0;
else if(bps_start) cnt<=cnt+1'b1;
else cnt<=13'b0;
end
//--------------------------------------------
reg [7:0] rx_data,tx_data;
//測試是否收到資料
assign sw=rx_data;
//---------------------接收資料--------------
//receive
[email protected](posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
rx_num<=4'b0;
rx_data<=8'b0;
end
else if(cnt==bps_cnt_half)
begin
if(bps_start_rx)
begin
rx_num<=rx_num+1'b1;
case(rx_num)
1:rx_data[0]<=rx;
2:rx_data[1]<=rx;
3:rx_data[2]<=rx;
4:rx_data[3]<=rx;
5:rx_data[4]<=rx;
6:rx_data[5]<=rx;
7:rx_data[6]<=rx;
8:rx_data[7]<=rx;
9:tx_data<=rx_data;
endcase
end
end
else if(rx_num==10) rx_num<=4'b0;
end
//---------------------傳送資料--------------
//transport
[email protected](posedge clk or negedge rst_n)
begin
if(!rst_n) tx_num<=4'b0;
else if(cnt==bps_cnt_half)
begin
if(bps_start_tx)
begin
tx_num<=tx_num+1'b1;
case(tx_num)
0:tx<=1'b0;
1:tx<=tx_data[0];
2:tx<=tx_data[1];
3:tx<=tx_data[2];
4:tx<=tx_data[3];
5:tx<=tx_data[4];
6:tx<=tx_data[5];
7:tx<=tx_data[6];
8:tx<=tx_data[7];
9:tx<=1'b1;
endcase
end
else tx<=1'b1;
end
else if(tx_num==10) tx_num<=4'b0;
end
endmodule