欢迎光临散文网 会员登陆 & 注册

【基于FPGA的图像处理工程】边缘检测工程之sccb传输模块代码解析

2023-07-29 07:15 作者:明德扬易老师  | 我要投稿

【基于FPGA的图像处理工程】

                                                                     —边缘检测工程:sccb传输模块代码解析


本文为明德扬原创文章,转载请注明出处!
Sccb传输模块的功能: 按照sccb传输协议的时序,传输上游模块的摄像头配置指令。

 一、        设计架构

   下图是官方中给出的SCCB时序图,虽然是三线的但是我们也可以用来学习二线的时序。


 1.   协议开始:在SIO_C高电平期间,SIO_D由高变低,表示传输的开始。如上图所示,在开始数据传输时,SIO_C要先处于高电平,由SIO_D(即本模块中的 sio_d_w 信号)先保持一段时间高电平并产生下降沿来标志传输开始,其中SIO_D 变低到 SIO_C 变低,最少 100ns。



2.        协议结束:在SIO_C高电平期间,SIO_D由高变低,表示数据传输的停止。如上图所示,在停止数据传输时,SIO_C也要首先置于高电平,由SIO_D(即本模块中的sio_d_w信号)产生上升沿并保持一段时间来标志传输结束,其中 SIO_C 变高到 SIO_D 变高,最少100ns。


     3.        其他时候 ,SIO_D 只能在 SIO_C=0 时才变化。


  4.        时序图中的 SIO_D 和 SIO_C,分别是本模块中的 sio_d_w 和 sio_c 信号。
  5.        写寄存器的过程:a.协议开始;b.发送设备ID编号,等待;c. 发送要存入的寄存器地址,等待;d.发送要写入的数据;e.协议结束。

 6.        读寄存器的时序:a.协议开始;b.发送设备ID编号,等待;c. 发送要读取的寄存器地址,等待;d. 协议结束;e.协议开始;f. 发送设备ID编号,等待;g. 读取Byte数据,NACK=1;h. 协议结束。


本模块计数器的架构图如下所示


A、Count_sck:时钟计数器。使用此计数器,来对传输1位数据时钟进行计数。本模块时钟是25M,周期为40ns,而SCCB传输1bit本模块设定为 120*40ns,所以此计数器每次要数120个。
B、Count_bit:位计数器。使用此计数器,要对传输1个阶段的位进行计数。根据sccb传输协议,读寄存器时序和写寄存器时序的位长度都是不一样的,可以通过变量bit_num来确定。C、Count_duan:阶段计数器。使用此计数器,对读或者写的阶段进行计数。根据sccb传输协议,读寄存器状态需要两个阶段,而写寄存器状态只有一个阶段,所以通过变量duan_num来确定。


 二、        举例说明

收到写使能 wen=1(同一时刻过来了 写数据wdata 和 寄存器地址数据sub_addr )时,产生如下波形。

 如上图所示,收到 wen=1,并且 sub_addr=8’h12 和 wdata=8’h04,这意味着要向地址为8’h12的寄存器写数据8’h04因此各个信号如下变化:
sio_c 和 sio_d_w:波形首先产生了开始位。然后依次发送 8’h42(固定值)和 x=1,发送 8’h12(sub_addr)和 x=1,发送 8’h04(wdata)和 x=1。之后是结束位,最后是 2 个间隔位(固定发 11)。 至此整个过程结束。en_sio_d_w:在收到 wr_en=1 开始,en_sio_d_w 就为 1,直到最后结束。
收到读使能ren=1(同一时刻过来了寄存器地址数据sub_addr,而wdata不关心)时,产生如下波形。

如上图所示,收到ren=1,并且sub_addr=8’h12(注意要展开来看,看rd_en=1时刻) ,这意味着要读地址为8’h12的寄存器的数据,因此各个信号如下变化sio_c、sio_d_w、rdata和rdata_vld:波形首先产生了开始位;然后依次发送8’h42(固定值)和x=1;然后再发送8’h12(sub_addr)和x=1,然后是结束位和间隔位。之后又是开始位,发送8’h43(固定值)和x=1。之后在8个sio_c周期内,取sio_d_r的值并保存到rdata中(8个值保存后,就可以产生1个时钟周期的rdata_vld=1脉冲)。最后是结束位和间隔位(固定发11)。 至此整个过程结束。en_sio_d_w:在收到rd_en=1开始,en_sio_d_w就为1,直到读取数据为0,读取数据后为1,整个过程结束后又为0。

本模块准备好指示信号rdy在整个波形产生期间,以及wen=1和ren=1时,均为0(rdy可以组合逻辑产生并输出)。

      
 三、        信号意义


   四、参考代码

  下面展出本模块的设计,欢迎进一步交流,如果需要源代码,欢迎与本人联系。

  1. module sccb(

  2.     clk       ,

  3.     rst_n     ,

  4.     ren       ,

  5.     wen       ,

  6.     sub_addr  ,

  7.     rdata     ,

  8.     rdata_vld ,

  9.     wdata     ,

  10.     rdy       ,

  11.     sio_c     ,

  12.     sio_d_r   ,

  13.     en_sio_d_w,

  14.     sio_d_w         

  15. );


  16.     //参数定义

  17.     parameter      SIO_C  = 120 ;


  18.     //输入信号定义

  19.     input               clk      ;//25m

  20.     input               rst_n    ;

  21.     input               ren      ;

  22.     input               wen      ;

  23.     input [7:0]         sub_addr ;

  24.     input [7:0]         wdata    ;


  25.     //输出信号定义

  26.     output[7:0]         rdata    ;

  27.     output              rdata_vld;

  28.     output              sio_c    ;//208kHz

  29.     output              rdy      ;


  30.     input               sio_d_r   ;

  31.     output              en_sio_d_w;

  32.     output              sio_d_w   ;

  33.     reg                 en_sio_d_w;

  34.     reg                 sio_d_w   ;


  35.     //输出信号reg定义

  36.     reg [7:0]           rdata    ;

  37.     reg                 rdata_vld;

  38.     reg                 sio_c    ;

  39.     reg                 rdy      ;


  40.     //中间信号定义

  41.     reg  [7:0]          count_sck     ;

  42.     reg  [4:0]          count_bit     ;

  43.     reg  [1:0]          count_duan    ;

  44.     reg                 flag_add      ;

  45.     reg                 flag_sel        ;

  46.     reg  [4:0]          bit_num       ;

  47.     reg  [1:0]          duan_num      ;

  48.     reg  [29:0]         out_data      ;


  49.     wire                add_count_sck ;

  50.     wire                end_count_sck ;

  51.     wire                add_count_bit ;

  52.     wire                end_count_bit ;

  53.     wire                add_count_duan;

  54.     wire                end_count_duan;

  55.     wire                sio_c_h2l     ;

  56.     wire                sio_c_l2h     ;

  57.     wire                out_data_time ;

  58.     wire                rdata_time    ;

  59.     wire [7:0]          rd_com        ;

  60.    

  61.     always  @(posedge clk or negedge rst_n)begin

  62.         if(rst_n==1'b0)begin

  63.             count_sck <= 0;

  64.         end

  65.         else if(add_count_sck)begin

  66.             if(end_count_sck)begin

  67.                 count_sck <= 0;

  68.             end

  69.             else begin

  70.                 count_sck <= count_sck + 1;

  71.             end

  72.         end

  73.     end


  74.     assign add_count_sck = flag_add  ;

  75.     assign end_count_sck = add_count_sck && count_sck == SIO_C-1;


  76.     always  @(posedge clk or negedge rst_n)begin

  77.         if(rst_n==1'b0)begin

  78.             count_bit <= 0;

  79.         end

  80.         else if(add_count_bit)begin

  81.             if(end_count_bit)begin

  82.                 count_bit <= 0;

  83.             end

  84.             else begin

  85.                 count_bit <= count_bit + 1;

  86.             end

  87.         end

  88.     end


  89.     assign add_count_bit = end_count_sck;

  90.     assign end_count_bit = add_count_bit && count_bit == bit_num+2-1;


  91.     always  @(posedge clk or negedge rst_n)begin

  92.         if(rst_n==1'b0)begin

  93.             count_duan <= 0;

  94.         end

  95.         else if(add_count_duan)begin

  96.             if(end_count_duan)begin

  97.                 count_duan <= 0;

  98.             end

  99.             else begin

  100.                 count_duan <= count_duan + 1;

  101.             end

  102.         end

  103.     end


  104.     assign add_count_duan = end_count_bit;

  105.     assign end_count_duan = add_count_duan && count_duan == duan_num-1;


  106.     always  @(posedge clk or negedge rst_n)begin

  107.         if(rst_n==1'b0)begin

  108.             flag_add <= 0;

  109.         end

  110.         else if(ren || wen)begin

  111.             flag_add <= 1;

  112.         end

  113.         else if(end_count_duan)begin

  114.             flag_add <= 0;

  115.         end

  116.     end


  117.     always  @(posedge clk or negedge rst_n)begin

  118.         if(rst_n==1'b0)begin

  119.             flag_sel <= 0;

  120.         end

  121.         else if(wen)begin

  122.             flag_sel <= 0;

  123.         end

  124.         else if(ren)begin

  125.             flag_sel <= 1;

  126.         end

  127.     end


  128.     always  @(*)begin

  129.         if(flag_sel==1)begin

  130.             bit_num = 21;

  131.             duan_num = 2;

  132.         end

  133.         else begin

  134.             bit_num = 30;

  135.             duan_num = 1;

  136.         end

  137.     end


  138.     always  @(posedge clk or negedge rst_n)begin

  139.         if(rst_n==1'b0)begin

  140.             sio_c <= 1;

  141.         end

  142.         else if(sio_c_h2l)begin

  143.             sio_c <= 0;

  144.         end

  145.         else if(sio_c_l2h)begin

  146.             sio_c <= 1;

  147.         end

  148.     end


  149.     assign sio_c_h2l = count_bit >= 0 && count_bit < (bit_num-2) && add_count_sck && count_sck == SIO_C-1;

  150.     assign sio_c_l2h = add_count_sck && count_sck == SIO_C/2-1;



  151.     always @ (*)begin

  152.         if(flag_sel==1)begin

  153.             out_data <= {1'h0,rd_com,1'h1,sub_addr,1'h1,1'h0,1'h1,9'h0};

  154.         end

  155.         else begin

  156.             out_data <= {1'h0,8'h42,1'h1,sub_addr,1'h1,wdata,1'h1,1'h0,1'h1};

  157.         end

  158.     end


  159.     assign rd_com = (flag_sel==1 && count_duan == 0)? 8'h42 : 8'h43;


  160.     always  @(posedge clk or negedge rst_n)begin

  161.         if(rst_n==1'b0)begin

  162.             en_sio_d_w <= 0;

  163.         end

  164.         else if(ren || wen)begin

  165.             en_sio_d_w <= 1;

  166.         end

  167.         else if(end_count_duan)begin

  168.             en_sio_d_w <= 0;

  169.         end

  170.         else if(flag_sel==1 && count_duan == 1 && count_bit == 10 && add_count_sck && count_sck == 1-1)begin

  171.             en_sio_d_w <= 0;

  172.         end

  173.         else if(flag_sel==1 && count_duan == 1 && count_bit == 18 && add_count_sck && count_sck == 1-1)begin

  174.             en_sio_d_w <= 1;

  175.         end

  176.     end



  177.     always  @(posedge clk or negedge rst_n)begin

  178.         if(rst_n==1'b0)begin

  179.             sio_d_w <= 1;

  180.         end

  181.         else if(out_data_time)begin

  182.             sio_d_w <= out_data[30-count_bit-1];

  183.         end

  184.     end


  185.     assign out_data_time = count_bit >= 0 && count_bit < bit_num && add_count_sck && count_sck == SIO_C/4-1;


  186.     always  @(posedge clk or negedge rst_n)begin

  187.         if(rst_n==1'b0)begin

  188.             rdata <= 0;

  189.         end

  190.         else if(rdata_time)begin

  191.             rdata[17-count_bit] <= sio_d_r;

  192.         end

  193.     end


  194.     assign rdata_time = flag_sel==1 && count_duan==1 && count_bit>=10 && count_bit<18 && add_count_sck && count_sck==SIO_C/4*3-1;


  195.     always  @(posedge clk or negedge rst_n)begin

  196.         if(rst_n==1'b0)begin

  197.             rdata_vld <= 0;

  198.         end

  199.         else if(flag_sel==1 && end_count_duan)begin

  200.             rdata_vld <= 1;

  201.         end

  202.         else begin

  203.             rdata_vld <= 0;

  204.         end

  205.     end


  206.     always  @(*)begin

  207.         if(ren || wen || flag_add)begin

  208.             rdy = 0;

  209.         end

  210.         else begin

  211.             rdy = 1;

  212.         end

  213.     end


  214. endmodule



 复制代码

明德扬专注FPGA研究,我司正在连载两本书籍:《基于FPGA至简设计法实现的图像边缘检测系统》(http://www.fpgabbs.cn/forum.php?mod=viewthread&tid=691)、《ASIC和FPGA时序约束理论与应用》(http://www.fpgabbs.cn/forum.php?mod=viewthread&tid=705),有兴趣点击观看。


【基于FPGA的图像处理工程】边缘检测工程之sccb传输模块代码解析的评论 (共 条)

分享到微博请遵守国家法律