设为首页收藏本站 今天是: 2019-12-15    美好的一天,从现在开始

明德扬论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 511|回复: 0

边缘检测工程:指令检测模块代码解析

[复制链接]
发表于 2019-11-28 18:14:42 | 显示全部楼层 |阅读模式

马上注册,看完整文章,学更多FPGA知识。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
边缘检测工程:指令检测模块代码解析
作者:小黑同学
本文为明德扬原创文章,转载请注明出处!

本模块的功能,是从一串输入的数据中,检测出指令头55D5,检测出包文头后,获取到紧接着的4个数据(2字节),并按字节为单位送给下游模块。指令头和无效数据则丢弃。

输入的包文指令格式:

1.png

输入的数据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。


一、设计架构

检测出指令头的方法如下:


2.png


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


3.png


计数器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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
module opcode_dect(
    clk         ,
    rst_n       ,
    din         ,
    din_vld     ,
[size=10.5000pt]
    dout_vld    ,
    dout
    );
[size=10.5000pt]
    //参数定义
    parameter      DOUT_W = 8;
    parameter      DIN_W  = 4;
[size=10.5000pt]
    //输入信号定义
    input               clk     ;
    input               rst_n   ;
    input[DIN_W-1:0]    din     ;
    input               din_vld ;
[size=10.5000pt]
    wire [DIN_W-1:0]    din     ;
    wire                din_vld ;
    //输出信号定义
    output[DOUT_W-1:0]  dout    ;
    output              dout_vld;
[size=10.5000pt]
    //输出信号reg定义
    reg   [DOUT_W-1:0]  dout    ;
    reg                 dout_vld;
[size=10.5000pt]
    //中间信号定义
    reg      [2-1:0]           cnt0;
    wire                   add_cnt0;
    wire                   end_cnt0;
[size=10.5000pt]
    reg      [2-1:0]           cnt1;
    wire                   add_cnt1;
    wire                   end_cnt1;
[size=10.5000pt]
    reg      [11:0]         din_tmp;
    wire     [15:0]         din_top;
    reg                       flag_add ;
[size=10.5000pt]
    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
[size=10.5000pt]
    assign add_cnt0 = flag_add&&din_vld;
    assign end_cnt0 = add_cnt0 && cnt0== 2-1;
[size=10.5000pt]
    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
[size=10.5000pt]
    assign add_cnt1 = end_cnt0;
    assign end_cnt1 = add_cnt1 && cnt1== 2-1;

    assign din_top = {din_tmp[11:0],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
[size=10.5000pt]
    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[7:0],din};
        end
    end
[size=10.5000pt]
    always  @(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            dout <= 0;
        end
        else if(din_vld)begin
            dout <= {dout[3:0],din};
        end
    end
[size=10.5000pt]
    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
    end
endmodule
[size=10.5000pt]
[size=10.5000pt]

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





上一篇:边缘检测工程:串口接收模块代码解析
下一篇:基于FPGA的边缘检测工程按键部分详细解析
1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香! 鲜花榜单
FPGA视频课程  培训班 FPGA学习资料
吴老师 18022857217(微信同号) Q1241003385
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


QQ|手机版|MDYBBS ( 粤ICP备16061416号

GMT+8, 2019-12-15 20:26 , Processed in 0.573264 second(s), 24 queries , File On.

Powered by Discuz! X3.4

本论坛由广州健飞通信有限公司所有

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表