2018年7月24日
uart 接收 部分測試成功,多謝開源騷客 鄧堪文老師 ,想學的同學可以微信公眾號搜索開源騷客
好啦!言歸正傳。

1.先附上老師的時序圖,自己有點懶不想畫,rx_t、rx_tt、rx_ttt分別對應源碼中的rx_r1、rx_r2、rx_r2。
認真理解時序圖,代碼具體怎么實現就好理解了。

2.需要說明的是baud_cnt這個計數器,他是波特率的計數器,計數原理了解這個公式

3.剩下的就自己結合一下源碼
1 `define SIM 2 3 module uart_rx( 4 //system signale 5 input sclk , 6 input s_rst_n , 7 //uart interface 8 input rs232_rx , 9 //other 10 output reg [7:0] rx_data , 11 output reg po_flag 12 13 ); 14 15 //-----------------------------------------------------------------\ 16 //***********Difine Parameter and Internal signals***************** 17 //-----------------------------------------------------------------/ 18 `ifndef SIM 19 localparam BAUD_END = 5207 ; 20 `else 21 localparam BAUD_END = 55 ; 22 `endif 23 localparam BAUD_M = BAUD_END/2-1 ; 24 localparam BIT_END = 8 ; 25 26 27 reg rx_r1 ; 28 reg rx_r2 ; 29 reg rx_r3 ; 30 reg rx_flag ; 31 reg [12:0] baud_cnt ; 32 reg bit_flag ; 33 reg [3:0] bit_cnt ; 34 35 //==================================================================\ 36 //****************Main Code ********************************* 37 //==================================================================/ 38 39 //捕獲起始位下降沿 40 assign rx_neg = ~rx_r2 & rx_r3; 41 42 always @(posedge sclk ) begin 43 rx_r1 <= rs232_rx; 44 rx_r2 <= rx_r1; 45 rx_r3 <= rx_r2; 46 end 47 48 //接收數據標志 49 always @(posedge sclk or negedge s_rst_n) begin 50 if(s_rst_n == 1'b0) 51 rx_flag <= 1'b0; 52 else if(rx_neg == 1'b1) 53 rx_flag <= 1'b1; 54 else if(bit_cnt == 4'd0 && baud_cnt == BAUD_END) 55 rx_flag <= 1'b0; 56 end 57 58 //波特率生成 59 always @(posedge sclk or negedge s_rst_n ) begin 60 if(s_rst_n == 1'b0) 61 baud_cnt <= 13'd0; 62 else if(baud_cnt == BAUD_END) 63 baud_cnt <= 13'd0; 64 else if(rx_flag == 1'b1) 65 baud_cnt <= baud_cnt + 1'b1; 66 else 67 baud_cnt <= 13'd0; 68 end 69 70 //位接收有效 71 always @(posedge sclk or negedge s_rst_n) begin 72 if(s_rst_n == 1'b0) 73 bit_flag <= 1'b0; 74 else if (baud_cnt == BAUD_M) 75 bit_flag <= 1'b1; 76 else 77 bit_flag <= 1'b0; 78 end 79 80 //位計數 81 always @(posedge sclk or negedge s_rst_n) begin 82 if(s_rst_n == 1'b0) 83 bit_cnt <= 4'd0; 84 else if(bit_flag == 1'b1 && bit_cnt == BIT_END ) 85 bit_cnt <= 4'd0; 86 else if(bit_flag == 1'b1) 87 bit_cnt <= bit_cnt + 1'b1; 88 89 end 90 91 //串轉並 92 always @(posedge sclk or s_rst_n) begin 93 if(s_rst_n == 1'b0) 94 rx_data <= 8'd0; 95 else if (bit_flag == 1'b1 && bit_cnt >= 4'd1) 96 rx_data <= {rx_r2, rx_data[7:1]}; 97 end 98 //一位接收完成 99 always @(posedge sclk or s_rst_n) begin 100 if(s_rst_n == 1'b0) 101 po_flag <= 1'b0; 102 else if(bit_cnt == BIT_END && bit_flag == 1'b1) 103 po_flag <= 1'b1; 104 else 105 po_flag <= 1'b0; 106 end 107 108 endmodule
4.源碼這兒需要理解一下 `ifndef ,`else,`endif。這個是預編譯處理,詳情可以看這位大佬
https://blog.csdn.net/hision_fpgaer/article/details/50909653

5.測試文件,這里需要理解tast使用,以及外部數據文件的的用法(第26行)以及將文件里的數據如何存入二維數組中,tx_data文件就是一般的文本文件,這里設計的技巧太多,可以自己去查詢一下。
1 `timescale 1ns/1ns 2 module tb_uart_rx; 3 4 reg sclk; 5 reg s_rst_n; 6 reg rs232_tx; 7 8 wire po_flag; 9 wire [7:0] rx_data; 10 11 reg [7:0] mem_a[4:0]; 12 13 initial begin 14 sclk = 1; 15 s_rst_n = 0; 16 rs232_tx = 1; 17 #100 18 s_rst_n = 1; 19 #100 20 tx_tyte(); 21 end 22 23 always # 10 sclk = ~sclk; 24 25 26 initial $readmemh("./tx_data.txt",mem_a); 27 28 task tx_tyte(); 29 integer i ; 30 for(i = 0;i < 4; i = i +1) begin 31 tx_bit(mem_a[i]); 32 end 33 34 endtask 35 36 37 task tx_bit( 38 input [7:0] data 39 ); 40 integer i; 41 for(i = 0; i < 10; i = i+1)begin 42 case(i) 43 0: rs232_tx <= 1'b0; 44 1: rs232_tx <= data[0]; 45 2: rs232_tx <= data[1]; 46 3: rs232_tx <= data[2]; 47 4: rs232_tx <= data[3]; 48 5: rs232_tx <= data[4]; 49 6: rs232_tx <= data[5]; 50 7: rs232_tx <= data[6]; 51 8: rs232_tx <= data[7]; 52 9: rs232_tx <= 1'b1; 53 endcase 54 #560; 55 end 56 endtask 57 58 uart_rx uart_rx_inst( 59 //system signale 60 .sclk (sclk ), 61 .s_rst_n (s_rst_n ), 62 //uart interface 63 .rs232_rx (rs232_tx ), 64 //other 65 .rx_data (rx_data ), 66 .po_flag (po_flag ) 67 68 ); 69 70 71 endmodule

總結一些自己,大一下學期期末左右接觸到fpga,自己就愛好電子設計,大一一來就學了51單片機,下學期看着自己同學都報班32,學的都很好,而自己呢還在玩51,弄3D打印機,那個時候挺迷的。
后來不小心看到了fpga,自己仔細去查了,也與32做了比較,斟酌了很久,最后還是下決心學fpga,但是那個我是什么處境呢,同級的一起玩的32都會做很多東西了,自己有小小羞恥感,關鍵是學校沒有人學fpga或者說沒有人學的可以的,如果要學的話只能孤軍奮戰。
后來還是下決心買了板子,自學了一段時間,剛好暑假國賽,我也參加了,打擊很大啊,最后還用51做,太丟人了。國賽完,我就自己瞎學fpga,一直因為對fpga的真正的喜愛,以及他那強大而又神秘能力支撐着我學到現在。
剛開始都是看着大佬們的博客一路學習過來,這學期終於翻身了開始自己寫博客了,雖然技術含量有點低,哈哈哈,但是還是很開心。到現在差不多學fpga一年了,說實話fpga也讓我害怕,不光是她太難駕馭還有的是沒啥成就,看其他人啪啪啪的一下子做一堆東西,而自己控制個舵機都吃力。
現在這個暑假,馬上又要大三了,趁着時間很多,好好重頭在干一次,或許注定是孤獨的,我愛你fpga,希望你也愛我,啦啦啦啦啦啦啦!!!!!!!!!!!!!!
完工回去睡覺,fpga等我明天再來寵幸你!
2018年7月26日
uart發送部分以及收發整合,其實是昨天就完事兒了,有事給耽擱了,今天再補來得及。
先說發送部分
1.還是先看時序圖,信號都不用解釋,直接看圖。

2.仔細的同學發現bit_flag這個信號和接收的不一樣,這次是baud_cnt波特率計數器記完再觸發,而接收的是計數到一半觸發,這兩種方式作用相同,只是后者穩定一下,自己也可以改。
下面附上接收的源碼
1// `define SIM 2 module uart_tx( 3 //system signal 4 input sclk , 5 input s_rst_n , 6 //uart interface 7 output reg rs232_tx , 8 //other 9 input tx_trig , 10 input [7:0] tx_data 11 ); 12 13 //-----------------------------------------------------------------\ 14 //***********Difine Parameter and Internal signals***************** 15 //-----------------------------------------------------------------/ 16 17 `ifndef SIM 18 localparam BAUD_END = 5207 ; 19 `else 20 localparam BAUD_END = 56 ; 21 `endif 22 23 localparam BAUD_M = BAUD_END/2-1 ; 24 localparam BIT_END = 8 ; 25 26 reg [7:0] tx_data_r ; 27 reg tx_flag ; 28 reg [12:0] baud_cnt ; 29 reg bit_flag ; 30 reg [3:0] bit_cnt ; 31 32 33 //==================================================================\ 34 //****************Main Code ********************************* 35 //==================================================================/ 36 //tx_data_r 37 always @(posedge sclk or negedge s_rst_n) begin 38 if(s_rst_n == 1'b0) 39 tx_data_r <= 8'd0; 40 else if (tx_trig == 1'b1 && tx_flag == 1'b0) 41 tx_data_r <= tx_data; 42 end 43 44 //tx_flag 45 always @(posedge sclk or negedge s_rst_n) begin 46 if(s_rst_n == 1'b0) 47 tx_flag <= 1'b0; 48 else if(tx_trig == 1'b1 ) 49 tx_flag <= 1'b1; 50 else if (bit_cnt == BIT_END && bit_flag == 1'b1) 51 tx_flag <= 1'b0; 52 end 53 54 //波特率計數器 55 always @(posedge sclk or negedge s_rst_n) begin 56 if(s_rst_n == 1'b0) 57 baud_cnt <= 13'd0; 58 else if (baud_cnt == BAUD_END) 59 baud_cnt <= 13'd0; 60 else if(tx_flag == 1'b1) 61 baud_cnt <= baud_cnt +1'b1; 62 else 63 baud_cnt <= 13'd0; 64 end 65 66 //bit_flag 67 always @(posedge sclk or negedge s_rst_n) begin 68 if(s_rst_n == 1'b0) 69 bit_flag <= 1'b0; 70 else if(baud_cnt == BAUD_END) 71 bit_flag <= 1'b1; 72 else 73 bit_flag <= 1'b0; 74 end 75 76 //bit_cnt 77 always @(posedge sclk or negedge s_rst_n) begin 78 if(s_rst_n == 1'b0) 79 bit_cnt <= 4'd0; 80 else if(bit_flag == 1'b1 && bit_cnt == BIT_END) 81 bit_cnt <= 4'd0; 82 else if (bit_flag == 1'b1) 83 bit_cnt <= bit_cnt +1'b1; 84 85 end 86 87 //rs232_tx 88 always @(posedge sclk or negedge s_rst_n) begin 89 if(s_rst_n == 1'b0) 90 rs232_tx <= 1'b1; 91 else if(tx_flag == 1'b1) 92 case(bit_cnt) 93 0: rs232_tx <= 1'b0; 94 1: rs232_tx <= tx_data_r[0]; 95 2: rs232_tx <= tx_data_r[1]; 96 3: rs232_tx <= tx_data_r[2]; 97 4: rs232_tx <= tx_data_r[3]; 98 5: rs232_tx <= tx_data_r[4]; 99 6: rs232_tx <= tx_data_r[5]; 100 7: rs232_tx <= tx_data_r[6]; 101 8: rs232_tx <= tx_data_r[7]; 102 default:rs232_tx <= 1'b1; 103 endcase 104 else 105 rs232_tx <= 1'b1; 106 end 107 108 endmodule
3.下面附上接收部分的激勵源碼
1 `timescale 1ns/1ns 2 3 module tb_uart_tx; 4 5 reg sclk; 6 reg s_rst_n; 7 reg tx_trig; 8 reg [7:0] tx_data; 9 wire rs232_tx; 10 //----------------------------------difine system signales----------------- 11 initial begin 12 sclk = 1; 13 s_rst_n = 0; 14 #100 15 s_rst_n = 1; 16 end 17 18 always #10 sclk = ~sclk; 19 20 //----------------------------------------------------------------------- 21 initial begin 22 tx_data <= 8'd0; 23 tx_trig <= 0; 24 25 #200 26 tx_trig <= 1'b1; 27 tx_data <= 8'h55; 28 #20 29 tx_trig <= 1'b0; 30 31 #20000 32 tx_trig <= 1'b1; 33 tx_data <= 8'h78; 34 #20 35 tx_trig <= 1'b0; 36 37 #20000 38 tx_trig <= 1'b1; 39 tx_data <= 8'h53; 40 #20 41 tx_trig <= 1'b0; 42 43 end 44 45 uart_tx uart_tx_inst( 46 //system signal 47 .sclk (sclk ), 48 .s_rst_n (s_rst_n ), 49 //uart interface 50 .rs232_tx (rs232_tx ), 51 //other 52 .tx_trig (tx_trig ), 53 .tx_data (tx_data ) 54 ); 55 56 endmodule
最后收發整合前面接收和發送部分都做好的話,這個就很簡單了,但是這兒注意一個細節,把模塊第一行的 ” `define SIM“給注釋掉,這個是仿真用的,不然燒寫到板卡不對
1 module uart_top( 2 //system signals 3 input sclk , 4 input s_rst_n , 5 //UART Interface 6 input rs232_rx , 7 output wire rs232_tx 8 ); 9 10 //-----------------------------------------------------------------\ 11 //***********Difine Parameter and Internal signals***************** 12 //-----------------------------------------------------------------/ 13 wire [7:0] rx_data ; 14 wire tx_trig ; 15 //==================================================================\ 16 //****************Main Code ********************************* 17 //==================================================================/ 18 19 uart_rx uart_rx_inst( 20 //system signale 21 .sclk (sclk ), 22 .s_rst_n (s_rst_n ), 23 //uart interface 24 .rs232_rx (rs232_rx ), 25 //other 26 .rx_data (rx_data ), 27 .po_flag (tx_trig ) 28 29 ); 30 31 32 uart_tx uart_tx_inst( 33 //system signal 34 .sclk (sclk ), 35 .s_rst_n (s_rst_n ), 36 //uart interface 37 .rs232_tx (rs232_tx ), 38 //other 39 .tx_trig (tx_trig ), 40 .tx_data (rx_data ) 41 ); 42 43 44 endmodule
uart學習到此為止了,已完成
