首先得说明一下,在下刚学FPGA,不知道多模块怎么来写,或是说有什么技巧,连小白也算不上,只是参考黑金代码,以自己的理解,记录编写串口接收程序的过程,还望得到烧友指点。
设引脚rx_Pin_In是接收上位机信号。由图可见,当有数据的时候,它会拉低电平来提醒一句,“嗨,数据到了”。如果此时设置好了波特率,就可以开始数据接收工作。在接收完毕一帧数据后,恢复高电平。我们可对接收到的数据处理,并且可以等待加一个低电平的到来在进行此操作。现在我想实现的功能是上位机发送数据,串口接收后发给led,实现对led亮灭的控制。显然,实现该功能需要俩个模块,一个是实现数据的接收rx_control_module.v,另一个是实现对led的亮灭控制(led_Control_module.v)。而数据接收需要三个条件:来了低电平信号,有匹配的波特率,还得对数据接收。所以我们需要三个模块完成,一是检测信号(rx_detect_module;)、二是波特率计数:rx_bps_module;、三是数据接收控制:rx_receive_module。接下来,咱就拿出一张纸,画画看,串口接收在FPGA当中是怎样工作的。
首先,先把那五个模块及引脚rx_Pin_In写上,接下来的一切动作都是由rx_Pin_In而起的。我们要接收数据肯定要先对信号(低电平)进行检查,否则,怎么开始呢?故先关注rx_detect_module.v(信号检测模块),这里要实现数据的电平检测,并不断的发送给数据接收模块。别的不管,先input rx_pin_in;再output L_sig(输出低电平) ;。这个模块的任务就完成了。
现由L_sig,信号传给了数据接收控制模块(rx_receive_module.v)。按理说下面就该对这个模块进行描述了。毕竟人家都不断给咱信号了,咱不能不干活呀。但还真不能干,得设置波特率呀,没有波特率还接收个毛线。所以走,设置波特率去,然后跟他要个信号,就可以工作了,出发~
“欢迎光临波特率计数模块(rx_bps_module),在这里您将得到你想要的一切”
“给我个接收数据的信号就可以了。”
“好,请掏钱”
“纳尼??!!,还要钱?”
“不给我钱(信号),我凭什么给你呢,想骗吃骗喝啊,滚~~”
出门不能忘了带钱啊,要不然人家不待见。回去拿钱吧。
(PS:想让人家工作,得给信号。起初还真的忘了)
回到数据接收控制模块(rx_receive_module.v),得弄个output bps_count;(波特率计数),相对应的在模块中reg bps_work;(波特率工作)。走,这回看他还咋不让俺们进。
“欢迎光临波特率计数模块(rx_bps_module),在这里您将得到你想要的一切”
“给,input bps_count;(波特率计数)”
“请问您要多少的波特率”
“9600吧”
“请告诉我详细信息,马上配置”
“晶振50MHZ,周期的中间取走,output BPS_CLK;(采集数据),9600 bps传输速度使一位数据的周期是1/9600 = 0.000104166667,以50MHZ时钟频率要得到上述的定时则需计数N = 0.000104166667 /(1/50M) = 5208,由于从零开始算起则为5207。中间取样为2604”这时,波特率计数模块(rx_bps_module)先input bps_count;(波特率计数),再reg [12:0] BPS_Conut;(计数) BPS_Conut=5027时归零,等于2604时读出即output BPS_CLK;说白了,波特率设置就是个计数器。现在他配置好了,等咱需要的时候给他个信号他就工作,加工,并且给咱带来了BPS_CLK,有它,咱可以就收数据了。 走,回数据接收控制模块(rx_receive_module.v),在这个模块主要就是对一帧一帧的数据度,这里采用case(i)来读,首先,i=0的时候,若~L_sig=1,则bps_work=1;通知波特率计数模块(rx_bps_module)工作,并i+1。i=1时,if(BPS_CLK)i<=i+1,就是起始位了,起始位忽略。在i=2~9时候是接收数据的。所以当 i=2~9时,只要来了波特率,咱就开始从rx_pin_in接收数据,就定义个 reg [7:0]rData;吧,接收数据。i=10的时候奇偶校验位,i+1。i=11的时候,停止位。接收完了,波特率不用计数了,咱该收工了吧?不行不行绝对不行,波特率计数模块(rx_bps_module.v)很靠谱,你不让他停他一直工作,所以,bps_work=0;您停吧。 好了,接收工作咱干完了,剩下的就是把接收的数据发送给led_Control_module.v模块,那什么时候发呢?当然是接收完就发啊,FPGA这么讲效率,拖个毛线。所以,在i=12的时候,不仅要让bps_work停止,还要让led_Control_module.v接收数据,故reg led_begin =1,output led_Begin_work;现在告诉这个模块要工作了。 但是!工作要干什么? 答:接收数据 好!不要忘了带数据,故output RX_Data; assign RX_Data = rData; assign led_Begin_work = led_begin; 来到了led_Control_module.v(led灯控制模块),因为led_Begin_work=1;传输数据。传输完了呢?即在i=13的时候led_begin=0。结束工作!好了完成了,哈哈。接收数据搞定了。
一直在想,人家怎么从无到有建一个模块的,我不知道,现在想先一个一个小模块,再和在一起。先挑个软柿子捏。
1、 rx_detect_module.v模块,input rx_pin_in; output L_sig ;
2、 波特率模块(rx_bps_module)也比较简单,就它吧。 Input bps_count;rx_receive_module模块来的计数标志位 reg [12:0] BPS_Conut;(计数) 2^13 = 8 192>5027,BPS_Conut=5027时归零,等于2604时读出即output BPS_CLK;
rx_receive_module.v模块感觉挺复杂的,信号多,不好写,就写led_Control_module.v模块吧。因为他就和rx_receive_module.v相关。 Input led_Begin_work; input RX_Data; Output led; 就差rx_receive_module,想想它怎么写: Input rx_pin_in(数据) L_Sig(低电平) BPS_CLK(波特率计满) Output BPS_Conut,(波特率计数信号) led_Begin_work(开始信号)RX_Data(传值)、
还有俩个模块,胜利在望啊。 先rx_control_module.v模块。把那三个综合一下,进的进,出的出,模块之间的wire 就OK啦。
- module rx_receive_module(
- clk,rst_n,
- rx_Pin_In,L_Sig,BPS_CLK,
- BPS_Conut,led_Begin_work,RX_Data
- );
-
- input clk ;
- input rst_n;
- input rx_Pin_In;
- input L_Sig;
- input BPS_CLK;
- output BPS_Conut;
- output led_Begin_work;
- output [7:0] RX_Data;
- reg [3:0] i;
- reg [7:0] data;
- reg bps_Begin;
- reg led_Begin;
- always @(posedge clk or negedge rst_n)
- if(!rst_n)
- begin
- i <= 4'd0;
- data <= 8'd0;
- bps_Begin <= 1'b0;
- led_Begin <= 1'b0;
- end
- else
- case(i)
- 4'd0:
- if(!L_Sig)
- begin
- i <= i+1'b1;
- bps_Begin <= 1'b1;
- end
-
- 4'd1:
- if(BPS_CLK)
- i <= i+1'b1;
-
- 4'd2,4'd3,4'd4,4'd5,4'd6,4'd7,4'd8,4'd9:
- if(BPS_CLK)
- begin
- i <= i+1'b1;
- data[i-2] <= rx_Pin_In;
- end
-
- 4'd10:
- if(BPS_CLK)
- i = i+1'b1;
-
- 4'd11:
- if(BPS_CLK)
- i= i +1'b1;
-
- 4'd12:
- begin
- i <= i +1'b1;
- bps_Begin <= 1'b0;
- led_Begin <= 1'b1;
- end
-
- 4'd13:
- begin
- i <= 4'd0;
- led_Begin <= 1'b0;
- end
- endcase
-
- assign BPS_Conut = bps_Begin;
- assign led_Begin_work = led_Begin;
- assign RX_Data = data;
-
- endmodule
-
-
-
复制代码
|