一、新建工程
- 参见 玩转Zynq连载17——新建Vivado工程,这里不再另行说明。
- 更改编辑器 T o o l s → s e t t i n g s → T e x t E d i t o r → C u r r e n t E d i t o r Tools\rightarrow settings\rightarrow Text Editor \rightarrow Current Editor Tools→settings→TextEditor→CurrentEditor即可进行选择,点击 C u s t o m E d i t o r Custom Editor CustomEditor 可以选择选项中没有的编辑器,具体方法参见 Vivado加上VsCode让你的生活更美好。
二、编写Verilog
- 左边导航栏(Flow Navigator)选择 A d d S o u r c e s → A d d o r c r e a t e d e s i g n s o u r c e s → C r e a t e F i l e Add Sources \rightarrow Add\ or\ create\ design\ sources\rightarrow Create\ File AddSources→Add or create design sources→Create File 命名后即可添加Verilog文件,点击 S o u r c e s ( 导 航 栏 右 上 ) → H i e r a r c h y → D e s i g n S o u r c e s Sources(导航栏右上) \rightarrow Hierarchy\rightarrow Design\ Sources Sources(导航栏右上)→Hierarchy→Design Sources 即可找到刚刚兴建的文件,双击打开。
- 代码实例说明:
//功能:实现111序列检测器(使用FSM状态机)
module sequence_111(
input en, //输入使能(高位有效)
input clk, //输入时钟
input rst, //复位信号(高位有效)
input m_sequence, //输入序列信号
output reg out_en, //输出使能信号(高位有效)
output reg detection //输出检测信号(高位有效)
);
//所有十种状态
parameter s0 = 4'b0000;
parameter s1 = 4'b0001;
parameter s2 = 4'b0010;
parameter s3 = 4'b0011;
parameter s4 = 4'b0100;
parameter s5 = 4'b0101;
parameter s6 = 4'b0110;
parameter s7 = 4'b0111;
parameter s8 = 4'b1000;
parameter s9 = 4'b1001;
reg [3:0] state; //当前状态
reg [1:0] counter; //计数(确保有足够序列读入)
reg out_en_temp; //用于输出使能信号延迟
//计数(确保有足够序列读入),确保有至少三个输入
always @(posedge clk)
begin
if(rst)
counter <= 2'b0;
else
begin
if(en && (counter <= 2'b01))
counter <= counter + 2'b01;
else
counter <= counter;
end
end
//根据计数器当前数值作输出使能判断
always @(posedge clk)
begin
if(rst)
out_en_temp <= 1'b0;
else
begin
if(en && (counter == 2'b10))
out_en_temp <= 1'b1;
else
out_en_temp <= 1'b0;
end
end
//时钟延迟
always @(posedge clk)
begin
if(rst)
out_en <= 1'b0;
else
out_en <= out_en_temp;
end
//状态转移
always @(posedge clk)
begin
if(rst)
state <= s0;
else
begin
if(en)
begin
case (state)
s0: begin
if(m_sequence)
state <= s1;
else
state <= s0;
end
s1: begin
if(m_sequence)
state <= s3;
else
state <= s2;
end
s2: begin
if(m_sequence)
state <= s5;
else
state <= s4;
end
s3: begin
if(m_sequence)
state <= s7;
else
state <= s6;
end
s4: begin
if(m_sequence)
state <= s1;
else
state <= s0;
end
s5: begin
if(m_sequence)
state <= s3;
else
state <= s2;
end
s6: begin
if(m_sequence)
state <= s5;
else
state <= s4;
end
s7: begin
if(m_sequence)
state <= s8;
else
state <= s6;
end
s8: begin
if(m_sequence)
state <= s9;
else
state <= s6;
end
s9: begin
if(m_sequence)
state <= s7;
else
state <= s6;
end
default: state <= state;
endcase
end
else
state <= state;
end
end
//输出检测信号
always @(posedge clk)
begin
if(rst)
detection <= 1'b0;
else
begin
case(state)
s7: detection <= 1'b1;
default:detection <= 1'b0;
endcase
end
end
endmodule
- 状态转移图 绘图工具参考一款用于绘制状态机转换图和流程图的web在线绘图工具
其中 s 8 s8 s8与 s 9 s9 s9状态为避免检测到1111或者11111连续输出检测有效而设置的状态。
三、TestBench
- 左边导航栏(Flow Navigator)选择
A
d
d
S
o
u
r
c
e
s
→
A
d
d
o
r
c
r
e
a
t
e
s
i
m
u
l
a
t
i
o
n
s
o
u
r
c
e
s
→
C
r
e
a
t
e
F
i
l
e
Add Sources \rightarrow Add\ or\ create\ simulation\ sources\rightarrow Create\ File
AddSources→Add or create simulation sources→Create File 命名后即可添加Verilog文件(可以在主文件名后加
_tb
),点击 S o u r c e s ( 导 航 栏 右 上 ) → H i e r a r c h y → s i m u l a t i o n S o u r c e s → s i m _ 1 Sources(导航栏右上) \rightarrow Hierarchy\rightarrow simulation\ Sources\rightarrow sim\_1 Sources(导航栏右上)→Hierarchy→simulation Sources→sim_1 即可找到刚刚兴建的文件,双击打开。 - 代码实例说明:
`timescale 1ns / 1ps //定义模块的仿真时的时间单位和时间精度
module sequence_111_tb();
//一般将待测试模块的输入设置为reg,输出设置为wire即可
reg en;
reg clk;
reg rst;
reg m_sequence;
wire out_en;
wire detection;
//待测试模块例化 ,第一个名称为待测试模块名称,第二个名称符合命名规范随意设置一个名称即可
//输入输出设置按如下形式设置,testbench中名称最好沿用待测试文件中名称,方便编写
sequence_111 sequence_111_1 (
.en(en),
.clk(clk),
.rst(rst),
.m_sequence(m_sequence),
.out_en(out_en),
.detection(detection)
);
//起始语句,只执行一次
//#10表示样式十个单位时间(本文一个单位时间设置为1ns)
initial
begin
clk <= 0;
en <= 0;
rst <= 1;
m_sequence <= 1;
#10
begin
en <= 1;
rst <= 0;
end
#10 m_sequence = 1;
#10 m_sequence = 1;
#10 m_sequence = 0;
#10 m_sequence = 0;
#10 m_sequence = 1;
#10 m_sequence = 1;
#10 m_sequence = 1;
#10 m_sequence = 1;
#10 m_sequence = 0;
#10 m_sequence = 0;
#10 m_sequence = 0;
end
//设置时钟
always #5 clk <= ~clk;
endmodule
- 仿真结果
由图可见序列检测正常