邊緣檢測項目:指令檢測模塊代碼解析
本文爲明德揚原創文章,禁止轉載
本模塊的功能,是從一串輸入的數據中,檢測出指令頭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。
二、信號的意義
三、參考代碼
module 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_W-1:0] din ;
input din_vld ;
wire [DIN_W-1:0] din ;
wire din_vld ;
//輸出信號定義
output[DOUT_W-1:0] dout ;
output dout_vld;
//輸出信號reg定義
reg [DOUT_W-1:0] dout ;
reg dout_vld;
//中間信號定義
reg [2-1:0] cnt0;
wire add_cnt0;
wire end_cnt0;
reg [2-1:0] cnt1;
wire add_cnt1;
wire end_cnt1;
reg [11:0] din_tmp;
wire [15:0] 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[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
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
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
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