硬件语言Verilog HDL牛客刷题day04 序列检测部分

时间:2020-12-27 01:08:37

1.VL25 输入序列连续的序列检测

1.题目:

请编写一个序列检测模块,检测输入信号a是否满足01110001序列,当信号满足该序列,给出指示信号match。

模块的接口信号图如下:

硬件语言Verilog HDL牛客刷题day04 序列检测部分

硬件语言Verilog HDL牛客刷题day04 序列检测部分

 

 硬件语言Verilog HDL牛客刷题day04 序列检测部分

 


2.解题思路

        2. 1 首先 暴力的手段, 使用 {} 组合逻辑 左移寄存器  最右边添加 a的值。 对比 寄存器的值输出 match 的值。 (  下下个状态 使用  always  的 非堵塞赋值可以)

        2.2 使用 三段的 状态机


3.解题代码

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input a,
	output reg match
	);
reg[7:0] gg;
always@(posedge clk or negedge rst_n)
	if(~rst_n)
		match <=0;
	else if(gg == 8'b0111_0001)
		match <= 1;
	else
		match <=0;

always@(posedge clk or negedge rst_n)
	if(~rst_n)
		begin
			gg <= 8'b0;
		end
	else
		begin
			gg <= {gg[6:0],a};
		end
endmodule


2.VL26 含有无关项的序列检测

1.题目:

请编写一个序列检测模块,检测输入信号a是否满足011XXX110序列(长度为9位数据,前三位是011,后三位是110,中间三位不做要求),当信号满足该序列,给出指示信号match。

硬件语言Verilog HDL牛客刷题day04 序列检测部分

硬件语言Verilog HDL牛客刷题day04 序列检测部分 

 


2.解题思路

        

    2. 1 首先 暴力的手段, 使用 {} 组合逻辑 左移寄存器  最右边添加 a的值。 对比 寄存器的值输出 match 的值。 (  下下个状态 使用  always  的 非堵塞赋值可以)

        2.2 使用 9 段的 状态机


3.解题代码

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input a,
	output reg match
	);
reg[8:0] gg;
always@(posedge clk or negedge rst_n)
	if(~rst_n)
		match <=0;
	else if(gg[8:6] == 3'b011 & gg[2:0] == 3'b110)
		match <= 1;
	else
		match <=0;

always@(posedge clk or negedge rst_n)
	if(~rst_n)
		begin
			gg <= 9'b0;
		end
	else
		begin
			gg <= {gg[7:0],a};
		end
endmodule


3.VL27  不重叠序列检测

1.题目:

请编写一个序列检测模块,检测输入信号(a)是否满足011100序列, 要求以每六个输入为一组,不检测重复序列,例如第一位数据不符合,则不考虑后五位。一直到第七位数据即下一组信号的第一位开始检测。当信号满足该序列,给出指示信号match。当不满足时给出指示信号not_match。

模块的接口信号图如下:

硬件语言Verilog HDL牛客刷题day04 序列检测部分

 硬件语言Verilog HDL牛客刷题day04 序列检测部分


2.解题思路

         1.在最后一个周期前判断 match 的输出值。 方法其他一样。

        


3.解题代码

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input data,
	output reg match,
	output reg not_match
	);

reg [5:0] seq;
reg [3:0] counter;
 
always@(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        seq <= 6'b0;
        match <= 1'b0;
        not_match <= 1'b0;
    end
    else
        seq <= { seq[4:0], data };
end
 
always@(posedge clk) begin
    if(!rst_n) begin
        counter <= 0;
    end
    else if(counter=='d5)
        counter <= 0;
    else begin
        counter <= counter + 1;
    end
end
 
always@(posedge clk)begin
    if( {seq[4:0],data}==6'b011100 && counter=='d5 ) begin
        match <= 1;
    end
    else begin
        match <= 0;
    end
end
 
always@(posedge clk)begin
    if( {seq[4:0],data}!=6'b011100 && counter=='d5 ) begin
        not_match <= 1;
    end
    else begin
        not_match <= 0;
    end
end
endmodule


4.VL28  输入序列连续的序列检测

1.题目:

请编写一个序列检测模块,输入信号端口为data,表示数据有效的指示信号端口为data_valid。当data_valid信号为高时,表示此刻的输入信号data有效,参与序列检测;当data_valid为低时,data无效,抛弃该时刻的输入。当输入序列的有效信号满足0110时,拉高序列匹配信号match。

模块的接口信号图如下:

硬件语言Verilog HDL牛客刷题day04 序列检测部分

硬件语言Verilog HDL牛客刷题day04 序列检测部分 


2.解题思路

        2.1 1.在最后一个周期前判断 match 的输出值。 方法其他一样。

 


3.解题代码

`timescale 1ns/1ns
module sequence_detect(
	input clk,
	input rst_n,
	input data,
	input data_valid,
	output reg match
	);

reg[3:0] gg; //数据储存寄存器

always@(posedge clk or negedge rst_n)
	if(~rst_n)
		begin
			gg <= 4'b0;
		end
	else
		begin
			if(data_valid == 1'b1)
				gg <= {gg[2:0],data};
			else
				gg <= 4'b0000;
		end

always@(posedge clk or negedge rst_n)
	if(~rst_n)
		begin
			match <=0;
		end
	else 
		begin
			if(data_valid && gg[2 : 0] == 3'b011 && !data )// 假如是 gg == 4'b0110 他是下一个时刻 match =1 , 
				begin
					match <=1;
				end
			else
				begin
					match <=0;
				end
		end




  
endmodule


5.做这个部分总的感受 和 学到新的知识

5.1 周期延时问题。

   //输出,使用时序将match延后一个周期,不延后可以用assign  match = (curr_state == S8);
    //注意,使用assign需将match类型改为wire
    /*always@(posedge clk or negedge rst_n) begin /延时
        if(rst_n == 0)
            match <= 0;
        else
            match = (curr_state == S4);
    end*/
    assign match = (curr_state == S4);//不延时

5.2堵塞 赋值 和非堵塞赋值

 5.2.1一个链接:

Verilog语法之六:阻塞赋值与非阻塞赋值 - 知乎 (zhihu.com)

5.2.2我的理解: 堵塞赋值  等于 立即赋值。

                     非堵塞赋值  等于  模块结束后 赋值。 

                所以状态机 里面的顺序可以理解了。 

                always 并行的。 但是 下一个状态 nextstatu  是 阻塞赋值。 立即赋值

                                             statu 是  非堵塞赋值。 是在 neststatu 后面赋值。 

5.2.3 关于输出的周期问题

        首先使用 always 的非堵塞赋值 会延时1 个周期。

        使用  assign  赋值  输出会在下一个周期执行。