最近正在学习Systemverilog,记录一下用SV写一个序列检测器。
序列检测器的功能:当输入"10010"序列时检测器能够识别到。
实现方式:通过状态机实现got1--->>got10--->>got100--->>got1001--->>got10010。
废话不多说直接上代码:
Design:
module seq_10010_det
(
input logic clk,
input logic rst,
input logic sin,
output logic dout
);
typedef enum logic [4:0] { idle, got_1, got_10, got_100, got_1001, got_10010} state_t;
state_t st;
always_ff @(posedge clk)begin
if(rst) st <= idle;
else begin
case(st)
idle:if(sin == 1'b1) st <= got_1;
else st <= idle;
got_1: if(sin == 1'b0) st <= got_10;
else st <= got_1;
got_10: if(sin == 1'b0) st <= got_100;
else st <= got_1;
got_100: if(sin == 1'b1) st <= got_1001;
else st <= idle;
got_1001: if(sin == 1'b0) st <= got_10010;
else st <= got_1;
got_10010: st <= idle;
default: st <= idle;
endcase
end
end
always_comb begin
dout = (st == got_10010);
end
endmodule
Testbench
`timescale 1ns / 1ps
module tb_seq_10010_det();
logic clk = 1'b0;
logic rst = 1'b1;
logic sin = 1'b0;
logic dout;
always #5 clk = ~clk;
initial begin
#100;
rst = 1'b0;
#100;
sin = 1'b1;
#10;
sin = 1'b0;
#10;
sin = 1'b1;
#10;
sin = 1'b1;
#10;
sin = 1'b0;
#10;
sin = 1'b0;
#10;
sin = 1'b1;
#10;
sin = 1'b0;
#10;
#100;
$finish;
end
seq_10010_det dut
(
/* input logic */ .clk ( clk )
/* input logic */ ,.rst ( rst )
/* input logic */ ,.sin ( sin )
/* output logic */ ,.dout ( dout )
);
endmodule
Wave
可以看到,在SV中reg和wire信号都可以统一用“logic”代替(logic声明信号类型非常方便,因为在verilog中reg是有歧义的,reg信号不一定是寄存器类型,在SV中工具会自动推断logic是reg还是wire),SV中的时序逻辑用“always_ff”, 组合逻辑用"always_comb", 此外在SV中还增加了枚举类“enum”,上面状态的定义就是用的这种方式。