马上注册,看完整文章,学更多FPGA知识。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
—边缘检测工程:指令检测模块代码解析 作者:小黑同学 本文为明德扬原创文章,转载请注明出处!
本模块的功能,是从一串输入的数据中,检测出指令头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。
二、信号的意义
信号 | | | | | | | | | | | | | | 输入数据有效指示信号。当其为1时,表示输入的数据有效,为0时表示输入数据无效。 | | | 输出数据,位宽为8bit(1字节)。 设计逻辑:在取数据状态时,每2个数据拼接成1字节输出。 | | | 输出数据有效指示信号,位宽为1bit。 设计逻辑:在取数据状态,每取到1个字节数据就输出1个有效指示停车。 | | | 数据个数计数器。用于对接收一个字节需要的数据个数进行计数,接收一个字节需要两个输入数据。该计数器的计数周期为2。 | | | 数据个数计数器加1条件。 设计逻辑:在取数据状态,输入有效此信号就有效。 | | | 数据个数计数器的结束条件。 设计逻辑:接收一个字节需要两个数据,所以数到两个就结束。 | | | 字节数计数器。用于对地址和数据的字节数进行计数,地址和数据各占一个字节。该计数器的计数周期为2。 | | | 字节数计数器加1条件。 设计逻辑:每接收完1个字节,此计数器就加1。 | | | 字节计数器结束条件。 设计逻辑:地址和数据共两个字节,所以数到两个就结束。 | | | 输入数据din的寄存器信号。位宽为12位,由高到低,每4位组成一组数据,分别存储的din之前三个有效数据。详细请看设计架构部分。 | | | 指令头有效指示信号。 设计逻辑:当前输入数据和之前的三个数据组成55D5时,就表示检测到指令头。 | | | 取数据状态指示信号。当为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] |
有兴趣点击阅读。也欢迎加入群(838209674),及时获取最新的文章信息,个性化问题也可以找我哦:Q1817866119(N老师)。
|