前言
正文
一、序列检测
VL25 输入序列连续的序列检测
要求
:请编写一个序列检测模块,检测输入信号a是否满足01110001序列,当信号满足该序列,给出指示信号match。
方法:
方法一
使用状态机,需要注意状态在不满足跳转的情况下,跳到哪里去
方法二
:使用序列缓存对比,通过移位+拼接对输入信号a进行缓存,缓存完成后和目标序列进行比较
//VL25 输入序列连续的序列检测
//方法一:使用状态机======================================
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
parameter S0 = 'b0,
S1 = 'b01,
S2 = 'b011,
S3 = 'b0111,
S4 = 'b0111_0,
S5 = 'b0111_00,
S6 = 'b0111_000,
S7 = 'b0111_0001;
reg [7:0] state;
reg [7:0] next_state;
always@(posedge clk or negedge rst_n)begin
if(!rst_n )begin
state <= S0;
end
else
state <= next_state;
end
always@(*)begin
case(state)
S0: next_state = (a)?S1:S0;
S1: next_state = (a)?S2:S0;
S2: next_state = (a)?S3:S0;
S3: next_state = (~a)?S4:S0;
S4: next_state = (~a)?S5:S1;
S5: next_state = (~a)?S6:S1;
S6: next_state = (a)?S7:S1;
S7: next_state = S0;
default:next_state = S0;
endcase
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n )begin
match <= 1'd0;
end
else if((state== S7))begin
match <= 1'd1;
end
else
match <= 1'd0;
end
endmodule
//方法二:使用序列缓存对比======================================
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
reg [7:0] a_reg;
always@(posedge clk or negedge rst_n)begin
if(!rst_n )begin
a_reg <= 8'd0;
end
else
a_reg <= {a_reg[6:0],a};
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n )begin
match <= 1'd0;
end
else if(a_reg == 8'b0111_0001)begin
match <= 1'd1;
end
else
match <= 1'd0;
end
endmodule
VL26 含有无关项的序列检测
最初我看到无关项,第一反应使用casez
表示哪些无关项,于是有了下面的错误
:
//VL26 含有无关项的序列检测
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
parameter S0 = 'b0,
S1 = 'b01,
S2 = 'b011,
S3 = 'b011?,
S4 = 'b011?_?,
S5 = 'b011?_??,
S6 = 'b011?_??1,
S7 = 'b011?_??11,
S8 = 'b011?_??110;
reg [8:0] state;
reg [8:0] next_state;
always@(posedge clk or negedge rst_n)begin
if(!rst_n )begin
state <= S0;
end
else
state <= next_state;
end
always@(*)begin
casez(state)
S0: next_state = (a)?S1:S0;
S1: next_state = (a)?S2:S0;
S2: next_state = S3;
S3: next_state = S4;
S4: next_state = S5;
S5: next_state = (a)?S6:S0;
S6: next_state = (a)?S7:S0;
S7: next_state = (~a)?S8:S0;
S8: next_state = S0;
default:next_state = S0;
endcase
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n )begin
match <= 1'd0;
end
else if((state == S7) && (a == 1'd0))begin
match <= 1'd1;
end
else
match <= 1'd0;
end
endmodule
仿真就会发现,状态部分是高阻态,及时到了S8,也不会将match拉高
还是用移位寄存的方法:(正确
)
//VL26 含有无关项的序列检测
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input a,
output reg match
);
reg [8:0] a_reg;
always@(posedge clk or negedge rst_n)begin
if(!rst_n )begin
a_reg <= 9'd0;
end
else
a_reg <= {a_reg[7:0],a};
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n )
match <= 1'd0;
else begin
casez(a_reg)
9'b011?_??110: match <= 1'd1;
default:match <= 1'd0;
endcase
end
end
endmodule
VL28 输入序列不连续的序列检测
题目描述:
请编写一个序列检测模块,输入信号端口为data,表示数据有效的指示信号端口为data_valid。当data_valid信号为高时,表示此刻的输入信号data有效,参与序列检测;当data_valid为低时,data无效,抛弃该时刻的输入。当输入序列的有效信号满足0110时,拉高序列匹配信号match
//VL28 输入序列不连续的序列检测
`timescale 1ns/1ns
module sequence_detect(
input clk,
input rst_n,
input data,
input data_valid,
output match
);
parameter S0 = 'b0,
S1 = 'b01,
S2 = 'b011,
S3 = 'b0110;
reg [3:0] state;
reg [3:0] next_state;
always@(posedge clk or negedge rst_n)begin
if(!rst_n )begin
state <= S0;
end
else
state <= next_state;
end
always@(*)begin
case(state)
S0:
if(data_valid && data)
next_state = S1;
else
next_state = S0;
S1:
if(data_valid && data)
next_state = S2;
else
next_state = S0;
S2:
if(data_valid && (~data))
next_state = S3;
else
next_state = S0;
S3: next_state = S0;
default:next_state = S0;
endcase
end
assign match = (state == S3)?1'd1:1'd0;
/* always@(posedge clk or negedge rst_n)begin
if(!rst_n )begin
match <= 1'd0;
end
else if(state == S3)begin
match <= 1'd1;
end
else
match <= 1'd0;
end */
endmodule
VL29 信号发生器
这道题我没有运行出来,但是在modelsim中运行出来了,可以参考评论区的答案: 评论区答案
//状态机方法
`timescale 1ns/1ns
module signal_generator(
input clk,
input rst_n,
input [1:0] wave_choise,
output reg [4:0]wave
);
//==========================================parameter===========================================================
parameter CNT_MAX = 12'd19;
parameter S0 = 'd0,
S1 = 'd1,
S2 = 'd2;
//==========================================reg=================================================================
reg [2:0] state;
reg [2:0] next_state;
reg [11:0] cnt_1249;
reg [11:0] cnt_san;
reg up ;
reg down;
//==========================================wire=================================================================
wire flage_9;
wire flage_19;
//==========================================assign=================================================================
assign flage_9 = (cnt_1249 == 'd9) ?1'd1:1'd0;
assign flage_19 = (cnt_1249 == 'd19)?1'd1:1'd0;
//==========================================always=================================================================
always@(posedge clk or negedge rst_n)begin
if(!rst_n )begin
cnt_san <= 'd0;
end
else if(up)begin
cnt_san <= cnt_san + 'd1;
end
else if(down)begin
cnt_san <= cnt_san - 'd1;
if(cnt_san == 'd0)
cnt_san <= cnt_san;
end
else if((state == S1)&&(next_state == S2))
cnt_san <= 'd0;
else
cnt_san <= cnt_san;
end
//assign cnt_1249 = (cnt_1249 == CNT_MAX)? 12'd0 : (cnt_1249 + 12'd1);
always@(posedge clk or negedge rst_n)begin
if(!rst_n )begin
cnt_1249 <= 'd0;
end
else if((cnt_1249 == CNT_MAX) ||((state == S0)&&(next_state == S1)) ||((state == S1)&&(next_state == S2)) ||((state == S2)&&(next_state == S0)))begin
cnt_1249 <= 'd0;
end
else
cnt_1249 <= cnt_1249 + 12'd1;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n )begin
up <= 1'd0;
down <= 1'd0;
end
else if(cnt_san == CNT_MAX-1)begin
up <= 1'd0;
down <= 1'd1;
end
else if(cnt_san == 'd0)begin
up <= 1'd1;
down <= 1'd0;
end
else begin
up <= up;
down <= down;
end
end
//==========================================状态机=================================================================
always@(posedge clk or negedge rst_n)begin
if(!rst_n )begin
state <= S0;
end
else
state <= next_state;
end
always@(*)begin
case(state)
S0:
if(wave_choise == 'd1)
next_state = S1;
else
next_state = S0;
S1:
if(wave_choise == 'd2)
next_state = S2;
else
next_state = S1;
S2:
if(wave_choise == 'd0)
next_state = S0;
else
next_state = S2;
default:next_state = S0;
endcase
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n )begin
wave <= 'd0;
end
else if((state == S0) && (flage_9))
wave <= 'd20;
else if((state == S0) && (flage_19))
wave <= 'd0;
else if((state == S0) && (~flage_19) && (~flage_9))
wave <= wave;
//锯齿波
else if((state == S1) && (cnt_1249 < 'd19))
wave <= wave + 'd1;
else if((state == S1) && (cnt_1249 == 'd19))
wave <= 'd0;
//三角波
else if((state == S2) && (cnt_san == 'd0))
wave <= 'd0;
else if(up)
wave <= wave + 'd1;
else if(down)begin
wave <= wave - 'd1;
if(wave == 'd0)
wave <= wave;
end
else
wave <= wave;
end
endmodule
VL30 数据串转并电路
分析:
data_b
:
- 什么时候改变:计数器计到5时才更新,且保持不变直到下一次更新
- 变成什么值:将cnt=5上升沿瞬间的data_a和data_b_reg[5:1]拼接即可(如果直接将data_b_reg打一拍赋值给data_b,那么cnt=5那一瞬间的值data_a就漏采了)
valid_b
:
- 什么时候改变:cnt=5拉高(cnt=5末尾处拉高)
- 其余时刻保持低电平
`timescale 1ns/1ns
module s_to_p(
input clk ,
input rst_n ,
input valid_a ,
input data_a ,
output reg ready_a ,
output reg valid_b ,
output reg [5:0] data_b
);
reg [5:0] data_b_reg;
reg [3:0] cnt_6;
always @(posedge clk or negedge rst_n ) begin
if(!rst_n)
ready_a <= 'd0;
else
ready_a <= 1'd1;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n )begin
cnt_6 <= 4'd0;
end
else if(cnt_6 == 'd5)
cnt_6 <= 4'd0;
else if(valid_a && ready_a)begin
cnt_6 <= cnt_6 + 4'd1;
end
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n )begin
data_b_reg <= 6'd0;
end
else if(valid_a)begin
data_b_reg <= {data_a,data_b_reg[5:1]};
end
else
data_b_reg <= data_b_reg;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n )begin
valid_b <= 1'd0;
end
else if((cnt_6 == 'd5)&& valid_a)begin
valid_b <= 1'd1;
end
else
valid_b <= 1'd0;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n )
data_b = 'd0;
else if(cnt_6 == 'd5)
data_b = {data_a,data_b_reg[5:1]};//将当前输入和寄存的值拼接,若果直接将寄存的值赋值给左边,会延迟一拍,会漏掉一个数据
else
data_b = data_b;
end
endmodule