【基于FPGA的图像处理工程】边缘检测工程之sccb传输模块代码解析
【基于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可以组合逻辑产生并输出)。


三、 信号意义

四、参考代码
下面展出本模块的设计,欢迎进一步交流,如果需要源代码,欢迎与本人联系。
module sccb(
clk ,
rst_n ,
ren ,
wen ,
sub_addr ,
rdata ,
rdata_vld ,
wdata ,
rdy ,
sio_c ,
sio_d_r ,
en_sio_d_w,
sio_d_w
);
//参数定义
parameter SIO_C = 120 ;
//输入信号定义
input clk ;//25m
input rst_n ;
input ren ;
input wen ;
input [7:0] sub_addr ;
input [7:0] wdata ;
//输出信号定义
output[7:0] rdata ;
output rdata_vld;
output sio_c ;//208kHz
output rdy ;
input sio_d_r ;
output en_sio_d_w;
output sio_d_w ;
reg en_sio_d_w;
reg sio_d_w ;
//输出信号reg定义
reg [7:0] rdata ;
reg rdata_vld;
reg sio_c ;
reg rdy ;
//中间信号定义
reg [7:0] count_sck ;
reg [4:0] count_bit ;
reg [1:0] count_duan ;
reg flag_add ;
reg flag_sel ;
reg [4:0] bit_num ;
reg [1:0] duan_num ;
reg [29:0] out_data ;
wire add_count_sck ;
wire end_count_sck ;
wire add_count_bit ;
wire end_count_bit ;
wire add_count_duan;
wire end_count_duan;
wire sio_c_h2l ;
wire sio_c_l2h ;
wire out_data_time ;
wire rdata_time ;
wire [7:0] rd_com ;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
count_sck <= 0;
end
else if(add_count_sck)begin
if(end_count_sck)begin
count_sck <= 0;
end
else begin
count_sck <= count_sck + 1;
end
end
end
assign add_count_sck = flag_add ;
assign end_count_sck = add_count_sck && count_sck == SIO_C-1;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
count_bit <= 0;
end
else if(add_count_bit)begin
if(end_count_bit)begin
count_bit <= 0;
end
else begin
count_bit <= count_bit + 1;
end
end
end
assign add_count_bit = end_count_sck;
assign end_count_bit = add_count_bit && count_bit == bit_num+2-1;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
count_duan <= 0;
end
else if(add_count_duan)begin
if(end_count_duan)begin
count_duan <= 0;
end
else begin
count_duan <= count_duan + 1;
end
end
end
assign add_count_duan = end_count_bit;
assign end_count_duan = add_count_duan && count_duan == duan_num-1;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
flag_add <= 0;
end
else if(ren || wen)begin
flag_add <= 1;
end
else if(end_count_duan)begin
flag_add <= 0;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
flag_sel <= 0;
end
else if(wen)begin
flag_sel <= 0;
end
else if(ren)begin
flag_sel <= 1;
end
end
always @(*)begin
if(flag_sel==1)begin
bit_num = 21;
duan_num = 2;
end
else begin
bit_num = 30;
duan_num = 1;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
sio_c <= 1;
end
else if(sio_c_h2l)begin
sio_c <= 0;
end
else if(sio_c_l2h)begin
sio_c <= 1;
end
end
assign sio_c_h2l = count_bit >= 0 && count_bit < (bit_num-2) && add_count_sck && count_sck == SIO_C-1;
assign sio_c_l2h = add_count_sck && count_sck == SIO_C/2-1;
always @ (*)begin
if(flag_sel==1)begin
out_data <= {1'h0,rd_com,1'h1,sub_addr,1'h1,1'h0,1'h1,9'h0};
end
else begin
out_data <= {1'h0,8'h42,1'h1,sub_addr,1'h1,wdata,1'h1,1'h0,1'h1};
end
end
assign rd_com = (flag_sel==1 && count_duan == 0)? 8'h42 : 8'h43;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
en_sio_d_w <= 0;
end
else if(ren || wen)begin
en_sio_d_w <= 1;
end
else if(end_count_duan)begin
en_sio_d_w <= 0;
end
else if(flag_sel==1 && count_duan == 1 && count_bit == 10 && add_count_sck && count_sck == 1-1)begin
en_sio_d_w <= 0;
end
else if(flag_sel==1 && count_duan == 1 && count_bit == 18 && add_count_sck && count_sck == 1-1)begin
en_sio_d_w <= 1;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
sio_d_w <= 1;
end
else if(out_data_time)begin
sio_d_w <= out_data[30-count_bit-1];
end
end
assign out_data_time = count_bit >= 0 && count_bit < bit_num && add_count_sck && count_sck == SIO_C/4-1;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
rdata <= 0;
end
else if(rdata_time)begin
rdata[17-count_bit] <= sio_d_r;
end
end
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;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
rdata_vld <= 0;
end
else if(flag_sel==1 && end_count_duan)begin
rdata_vld <= 1;
end
else begin
rdata_vld <= 0;
end
end
always @(*)begin
if(ren || wen || flag_add)begin
rdy = 0;
end
else begin
rdy = 1;
end
end
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),有兴趣点击观看。