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等我明天再来宠幸你!