串并串转换(2)---- 串到并 + 并转串再转并

串转并程序说明

  • 判断启动脉冲
  1. 根据上一篇文章提到,此处将SCL为高时,SDA由高变低做为“启动脉冲”;再以SCL为高时将SDA数据串行输出存储起来。同样, 启动脉冲来到时间提前不知道,相较接收方系统时钟而言是异步信号(虽然仿真时都用的一个时钟),处理成同步信号来使用这个启动脉冲。

  2. 回答上一文提到的,当以下降沿的脉冲做启动脉冲时,沿同步的结果应为:(不同于以上升沿做启动脉冲
    对齐结果 = (~i_data_com_dl) &&(i_data_com); //SDA信号即是用i_data_com接收的

  3. 启动脉冲延迟锁存如下:

    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
    
  4. 此处和之前有点不同,之前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
    
  5. 波形示意如下:
    在这里插入图片描述 注意这里是以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
    1. 错在:always @ (posedge i_sys_clk,negedge i_rst_n) ...... (这句话用了好多次了,这次出错了)
      第一:敏感表要是有好几个敏感信号a、b等,则不要忘了任一个敏感信号满足条件都会触发always,所以需要用 if 进行判断;
      第二:每一个 if 都是先判断敏感表,再判断其他东西:

    2. 错误代码:

      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 
      
    3. 准确写法:

      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
      
    4. 借鉴


  • 报错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电平总是为低
    1. 错误代码:
      在这里插入图片描述

    2. 错因:非阻塞赋值没考虑到(这次作业被这个东西坑了好多次),试验一下下面两句:

      //		if(1) o_scl_clk <= 1'b0;	
      //		if(1) o_scl_clk <= 1'b1; //结果总为1,即非阻塞赋值取最后一个		
      
    3. 准确写法:

      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
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值