明德扬吴老师 发表于 2019-11-28 18:14:42

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

【基于FPGA的图像处理工程】                                                                     —边缘检测工程:指令检测模块代码解析作者:小黑同学本文为明德扬原创文章,转载请注明出处!
本模块的功能,是从一串输入的数据中,检测出指令头55D5,检测出包文头后,获取到紧接着的4个数据(2字节),并按字节为单位送给下游模块。指令头和无效数据则丢弃。
输入的包文指令格式:

输入的数据din为4比特,假设其依次输入:5、5、d、5、0、2、9、9、1、5、5、d、5、0、1、0、3其中前两个字节55d5就表示指令头,后一个字节02表示地址,再一个字节99表示数据。紧跟着后面的1为无效数据,往后又检测到55d5,则01为地址,03为数据。把指令头、无效的数据过滤掉(即dout_vld为0),最终输出以字节为单位的02、99、01、03。

一、设计架构
检测出指令头的方法如下:



检测出包文头后,需要对后面的4个数据进行计数。每2个数据组成1个字节,一共有2个字节。所以指令检测模块采用两个计数器的结构,这两个计数器分别对应接收一个字节需要的数据个数和接收字节数,其结构图如下所示:



计数器cnt0:数据个数计数器。对接收一个字节需要的数据进行计数,接收一个字节需要2个数据。该计数器的计数周期为2。计数器cnt1:字节数计数器。对接收的字节数进行计数,地址加上数据共两个字节。该计数器的计数周期为2。

二、信号的意义

信号类型意义
clk输入信号时钟信号。
rst_n输入信号复位信号,低电平有效。
din输入信号输入的数据,位宽为4bit
din_vld输入信号输入数据有效指示信号。当其为1时,表示输入的数据有效,为0时表示输入数据无效。
dout输出信号输出数据,位宽为8bit(1字节)。设计逻辑:在取数据状态时,每2个数据拼接成1字节输出。
dout_vld输出信号输出数据有效指示信号,位宽为1bit。设计逻辑:在取数据状态,每取到1个字节数据就输出1个有效指示停车。
cnt0中间信号数据个数计数器。用于对接收一个字节需要的数据个数进行计数,接收一个字节需要两个输入数据。该计数器的计数周期为2。
add_cnt0中间信号数据个数计数器加1条件。设计逻辑:在取数据状态,输入有效此信号就有效。
end_cnt0中间信号数据个数计数器的结束条件。设计逻辑:接收一个字节需要两个数据,所以数到两个就结束。
cnt1中间信号字节数计数器。用于对地址和数据的字节数进行计数,地址和数据各占一个字节。该计数器的计数周期为2。
add_cnt1中间信号字节数计数器加1条件。设计逻辑:每接收完1个字节,此计数器就加1。
end_cnt1中间信号字节计数器结束条件。设计逻辑:地址和数据共两个字节,所以数到两个就结束。
din_tmp中间信号输入数据din的寄存器信号。位宽为12位,由高到低,每4位组成一组数据,分别存储的din之前三个有效数据。详细请看设计架构部分。
din_top中间信号指令头有效指示信号。设计逻辑:当前输入数据和之前的三个数据组成55D5时,就表示检测到指令头。
flag_add中间信号取数据状态指示信号。当为1时,表示检测到包文头,此时处于取数据状态。设计逻辑:指令头有效时,就变1;当取完4个数据后就变0。


三、参考代码
下面展出本模块的设计,欢迎进一步交流,如果需要源代码,欢迎与本人联系QQ:1817866119


123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116module opcode_dect(    clk         ,    rst_n       ,    din         ,    din_vld   ,     dout_vld    ,    dout    );     //参数定义    parameter      DOUT_W = 8;    parameter      DIN_W= 4;     //输入信号定义    input               clk   ;    input               rst_n   ;    input    din   ;    input               din_vld ;     wire     din   ;    wire                din_vld ;    //输出信号定义    outputdout    ;    output            dout_vld;     //输出信号reg定义    reg   dout    ;    reg               dout_vld;     //中间信号定义    reg               cnt0;    wire                   add_cnt0;    wire                   end_cnt0;     reg               cnt1;    wire                   add_cnt1;    wire                   end_cnt1;     reg               din_tmp;    wire            din_top;    reg                     flag_add ;     always @(posedge clk or negedge rst_n)begin      if(!rst_n)begin            cnt0 <= 0;      end      else if(add_cnt0)begin            if(end_cnt0)                cnt0 <= 0;            else                cnt0 <= cnt0 + 1;      end    end     assign add_cnt0 = flag_add&&din_vld;    assign end_cnt0 = add_cnt0 && cnt0== 2-1;     always @(posedge clk or negedge rst_n)begin       if(!rst_n)begin            cnt1 <= 0;      end      else if(add_cnt1)begin            if(end_cnt1)                cnt1 <= 0;            else                cnt1 <= cnt1 + 1;      end    end     assign add_cnt1 = end_cnt0;    assign end_cnt1 = add_cnt1 && cnt1== 2-1;
    assign din_top = {din_tmp,din}==16'h55d5;        always@(posedge clk or negedge rst_n)begin      if(rst_n==1'b0)begin            flag_add <= 0;      end      else if(din_vld&&flag_add==0&&din_top)begin            flag_add <= 1;      end      else if(end_cnt1)begin            flag_add <= 0;      end    end     always@(posedge clk or negedge rst_n)begin      if(rst_n==1'b0)begin            din_tmp <= 0;      end      else if(din_vld&&flag_add==0)begin            din_tmp <= {din_tmp,din};      end    end     always@(posedge clk or negedge rst_n)begin      if(rst_n==1'b0)begin            dout <= 0;      end      else if(din_vld)begin            dout <= {dout,din};      end    end     always@(posedge clk or negedge rst_n)begin      if(rst_n==1'b0)begin            dout_vld <= 1'b0;      end      else if(end_cnt0)begin            dout_vld <= 1'b1;      end      else begin            dout_vld <= 1'b0;      end    endendmodule

明德扬专注FPGA研究,我司正在连载两本书籍: 《基于FPGA至简设计法实现的图像边缘检测系统》(http://www.fpgabbs.cn/forum.php?mod=viewthread&tid=691)、《ASIC和FPGA时序约束理论与应用》(http://www.fpgabbs.cn/forum.php?mod=viewthread&tid=705),有兴趣点击阅读。也欢迎加入群(838209674),及时获取最新的文章信息,个性化问题也可以找我哦:Q1817866119(N老师)。
页: [1]
查看完整版本: 【基于FPGA的图像处理工程】边缘检测工程之指令检测模块代码解析