使用VIVADO编写简单的Verilog程序和Testbench

一、新建工程
  • 参见 玩转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 ToolssettingsTextEditorCurrentEditor即可进行选择,点击 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 AddSourcesAdd or create design sourcesCreate 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()HierarchyDesign 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

其中 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 AddSourcesAdd or create simulation sourcesCreate 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()Hierarchysimulation Sourcessim_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

  • 仿真结果
    在这里插入图片描述

由图可见序列检测正常

微信公众号:通信随笔XIDIAN

在这里插入图片描述

好的,下面是使用 VHDL 语言编写Vivado 计数器的代码和 testbench 程序: 计数器代码: ```vhdl library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity counter is Port ( clk : in STD_LOGIC; reset : in STD_LOGIC; enable : in STD_LOGIC; count : out STD_LOGIC_VECTOR(7 downto 0)); end counter; architecture Behavioral of counter is signal temp : unsigned(7 downto 0) := (others => '0'); begin process(clk, reset) begin if reset = '1' then temp <= (others => '0'); elsif rising_edge(clk) then if enable = '1' then temp <= temp + 1; end if; end if; end process; count <= std_logic_vector(temp); end Behavioral; ``` testbench 代码: ```vhdl library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity counter_tb is end counter_tb; architecture Behavioral of counter_tb is constant clk_period : time := 10 ns; signal clk : std_logic := '0'; signal reset : std_logic := '1'; signal enable : std_logic := '0'; signal count : std_logic_vector(7 downto 0); begin uut : entity work.counter port map(clk => clk, reset => reset, enable => enable, count => count); process begin reset <= '1'; enable <= '0'; wait for 100 ns; reset <= '0'; enable <= '1'; wait for 500 ns; enable <= '0'; wait for 100 ns; enable <= '1'; wait for 300 ns; enable <= '0'; wait for 100 ns; enable <= '1'; wait for 100 ns; enable <= '0'; wait for 100 ns; enable <= '1'; wait for 200 ns; enable <= '0'; wait for 100 ns; wait; end process; clk_process : process begin while true loop clk <= not clk; wait for clk_period / 2; end loop; end process; end Behavioral; ``` 以上是使用 VHDL 语言编写Vivado 计数器的代码和 testbench 程序,供参考。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xidian_hxc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值