使用verilog编写一个包含6个状态的状态机,使用do文件进行仿真(对上一篇文章中的do文件相关内容进行补充)
本状态机的状态示意图
1/0的意思是指输入的值为1,并且在该状态下输出0
状态机的程序代码
module mealy(
input wire clk,//如果没有说就是定义了一个一位的
input wire rst_n,
input wire A,
output reg K
);
parameter s1 = 6'b00_0001; //6个状态 推荐使用独热码
parameter s2 = 6'b00_0010;
parameter s3 = 6'b00_0100;
parameter s4 = 6'b00_1000;
parameter s5 = 6'b01_0000;
parameter s6 = 6'b10_0000;
reg [5:0] Curr_st;
// reg [5:0] Next_st;
// always @*
// Curr_st = Next_st; //只要next的值发生变化,就会立刻传给Curr
always @(posedge clk or negedge rst_n)
if(rst_n == 1'b0)
Curr_st<=s1;
else
case(Curr_st)
s1: if(A == 1'b1)
Curr_st <= s2;
else
Curr_st <= s1;
s2: if(A == 1'b1)
Curr_st <= s3;
else
Curr_st <= s1;
s3: if(A == 1'b1)
Curr_st <= s4;
else
Curr_st <= s1;
s4: if(A == 1'b0)
Curr_st <= s5;
s5: if(A == 1'b1)
Curr_st <= s6;
else
Curr_st <= s1;
s6: Curr_st <= s1;
default:Curr_st <= s1;
endcase
always@(posedge clk or negedge rst_n)
if(rst_n == 1'b0)
K <= 1'b0;
else if(Curr_st == s5 && A==1'b1)
K <= 1'b1;
else
K <= 1'b0;
endmodule
测试文件代码
`timescale 1ns/1ns
module tb_mealy;
reg sclk,rst_n;
reg a_in;
wire K_out;
initial begin
sclk =0;
rst_n = 0;
#100 rst_n = 1;
end
initial begin
#200;
rand_bit();
end
always #10 sclk <= ~sclk;
mealy mealy_inst(
.clk (sclk),
.rst_n (rst_n),
.A (a_in),
.K (K_out)
);
task rand_bit();
integer i;
begin
for(i=0; i<255; i=i+1)
begin
@(posedge sclk);
a_in <= {$random}%2; //产生0和1
end
end
endtask
endmodule
使用do文件仿真
使用do文件的时候就不要添加中文注释,否则大部分情况下modelsim都会报错,在任何情况下使用大括号都要注意加上空格
.main clear
vlib ./lib/
vlib ./lib/work_a/
vlib ./lib/design/
#映射逻辑库 这里分别要将不同文件的编译之后的结果放在不同的文件中
vmap base_space ./lib/work_a/
vmap design ./lib/design/
#编译文件
vlog -work base_space ./tb_mealy.v
vlog -work design ./../design/*.v
#-t指的是运行仿真的时间精度是ns
#-L 链接库关键字
vsim -t ns -voptargs=+acc -L base_space -L design base_space.tb_mealy #前面两个-L是因为编译之后的文件所存放的文件夹
#添加虚拟信号 其目的就是把一些二进制显示的数据比如我们这里的各个状态变成通俗好看的虚拟信号 其具体的含义就是只要看到01则转化为 s1
#写这一部分的代码时一定要注意大括号前后的空格
virtual type {
{01 s1}
{02 s2}
{04 s3}
{08 s4}
{10 s5}
{20 s6}
} vir_new_signal
add wave -divider {tb_mealy_1}
add wave tb_mealy/*
add wave -divider {mealy}
#顶层/例化的名字/* 其中*号是通配符,匹配所有信号
add wave tb_mealy/mealy_inst/*
#创建一个vir_new_signal 类型的信号,也就是把Curr_st类型进行转换
virtual function {(vir_new_signal)tb_mealy/mealy_inst/Curr_st} new_state
add wave -color red tb_mealy/mealy_inst/new_state
run 100us