概述
主要内容
- 串转并程序说明
- 并串并整体联调
- 遇到的错误记录
串转并程序说明
- 判断启动脉冲
-
根据上一篇文章提到,此处将SCL为高时,SDA由高变低做为“启动脉冲”;再以SCL为高时将SDA数据串行输出存储起来。同样, 启动脉冲来到时间提前不知道,相较接收方系统时钟而言是异步信号(虽然仿真时都用的一个时钟),处理成同步信号来使用这个启动脉冲。
-
回答上一文提到的,当以下降沿的脉冲做启动脉冲时,沿同步的结果应为:(不同于以上升沿做启动脉冲)
对齐结果 = (~i_data_com_dl) &&(i_data_com); //SDA信号即是用i_data_com接收的
-
启动脉冲延迟锁存如下:
always @ (posedge i_sys_clk,negedge i_rst_n)begin if(!i_rst_n)begin i_data_com_dl <= 1'b0; end else begin i_data_com_dl <= i_data_com; end end
-
此处和之前有点不同,之前startpulse是一个脉冲,冲一下就没了,这里 i_data_com 即是SDA数据线,传输数据会变化,所以这里加了个标志位startFlag 和 endFlag,如下:觉得这里不加scl也行
always @ (posedge i_sys_clk,negedge i_rst_n)begin if(!i_rst_n)begin startFlag <= 1'd0; end else begin if(i_data_com_dl && (~i_data_com) && i_scl_clk)begin startFlag <= 1'd1; end else if(endFlag)begin //endFlag时sclk_clk定是低电平的,不会冲突 startFlag <= 1'd0; end else begin startFlag <= startFlag; end end end
-
波形示意如下:
注意这里是以sys_clk做为沿判断的!其频率一般比SCL高(如上文中的分频),(主要是要让上升沿检测SDA高低电平的变化,这个变化因此不能太短)。
- 串行数据接收
一位位接收串行数据,在FPGA内保存在一个“多位数组”里。通过接收个数来看收够没有。ps:again,注意非阻塞赋值时分支判断的条件。
这里串转并很有意思:always @(posedge i_scl_clk, negedge i_rst_n)begin if(!i_rst_n)begin //初始化 end else if(startFlag)begin if(r_cnt >= 10'd32)begin r_cnt <= 10'b0; endFlag <= 1'b1; o_sda_data_parallel <= r_data; end //这里只是重新赋给另一个变量来输出显示 else begin r_data <= {r_data[30:0],i_data_com}; r_cnt <= r_cnt + 10'b1; endFlag <= 1'b0; end end else begin r_data <= r_data; end end
r_data <= {r_data[30:0],i_data_com};
r_data共32位,使用位拼接,每次r_data去低31位做为新r_data的高31位,新来的data_com做为最低位(因为发送方已协调好先发送的最高位),相当于起到移位的作用。
并串并整体联调
-
调用多个文件
`include "parallel_com.v" //嗯,没错,有个单词写错了,估计就我一个作业里写的这个错词哈哈 `include "com_parallel.v"
主程序中就是例化parallel_com、com_parallel 这两个module;
注意调用的两个文件(.v就行)需要与调用它们工程文件(.qpf)放在一起。
- 仿真结果
遇到的错误记录
报错
:cannot match operand(s) in the condition to the corresponding edges in the enclosing event control of the always construct
-
错在:
always @ (posedge i_sys_clk,negedge i_rst_n) ......
(这句话用了好多次了,这次出错了)
第一:敏感表要是有好几个敏感信号a、b等,则不要忘了任一个敏感信号满足条件都会触发always,所以需要用 if 进行判断;
第二:每一个 if 都是先判断敏感表,再判断其他东西: -
错误代码:
always @(posedge i_sys_clk or negedge i_rst_n) begin if(!i_rst_n) begin ... end else if(phase_cnt == 10'd39)//这里错,得先是敏感表的判断 end else begin ... end if(phase_cnt == 10'd39) //这里错,没有判断敏感表 end else begin end end
-
准确写法:
always @(posedge i_sys_clk or negedge i_rst_n) begin if(!i_rst_n) begin ... end else begin //把其他的判断都放在这里else里,即是sys_clk的触发时间里 if(phase_cnt == 10'd39) begin end else begin end if(phase_cnt == 10'd39) begin end else begin end //...... end end
-
借鉴
-
报错
:module "xxx" cannot be declared more than once
帮同学排错,没有给我发工程,只发了.v 文件,我就自己新建工程,再直接再quartus II里建三个.v 文件分别存同学的代码。错因
:因为直接在工程里新建了三个.v程序,所以三者是并列在这个工程下了,解决方法:
方一,把我 ·include “xxxfile.v” 语句注释调就好了,但是要设置我的主程序为top file;
方二,点击files左边栏,把xxxfile.v delete,就可以用include了;(此时三个.v 文件是已保存在同一工程下)
SCL电平总是为低
-
错误代码:
-
错因:非阻塞赋值没考虑到
(这次作业被这个东西坑了好多次),试验一下下面两句:// if(1) o_scl_clk <= 1'b0; // if(1) o_scl_clk <= 1'b1; //结果总为1,即非阻塞赋值取最后一个
-
准确写法:
always @ (posedge i_sys_clk , negedge i_rst_n) begin if(!i_rst_n) begin ...... end else begin if(phase0 == 1'b1) begin o_scl_clk <= 1'b1; end else if(phase2 == 1'b1) begin//这两个得何在一个if & else里 o_scl_clk <= 1'b0; end else o_scl_clk <= o_scl_clk; end end
-
end~
最后
以上就是迅速小霸王为你收集整理的串并串转换(2)---- 串到并 + 并转串再转并的全部内容,希望文章能够帮你解决串并串转换(2)---- 串到并 + 并转串再转并所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复