testbench是一種驗(yàn)證的手段。首先,任何設(shè)計(jì)都是會(huì)有輸入輸出的。但是在軟環(huán)境中沒有激勵(lì)輸入,也不會(huì)對(duì)你設(shè)計(jì)的輸出正確性進(jìn)行評(píng)估。那么此時(shí)便有一種,模擬實(shí)際環(huán)境的輸入激勵(lì)和輸出校驗(yàn)的一種“虛擬平臺(tái)”的產(chǎn)生。在這個(gè)平臺(tái)上你可以對(duì)你的設(shè)計(jì)從軟件層面上進(jìn)行分析和校驗(yàn),這個(gè)就是testbench的含義。
testbench怎么寫
一個(gè)最基本的Testbench包含三個(gè)部分,信號(hào)定義、模塊接口和功能代碼。借用一下特權(quán)同學(xué)總結(jié)的編寫Testbench的三個(gè)基本步驟:
1、對(duì)被測(cè)試設(shè)計(jì)的頂層接口進(jìn)行例化;
2、給被測(cè)試設(shè)計(jì)的輸入接口添加激勵(lì);
3、判斷被測(cè)試設(shè)計(jì)的輸出相應(yīng)是否滿足設(shè)計(jì)要求。
逐步解決編寫Testbench的這三點(diǎn):
首先“對(duì)被測(cè)試設(shè)計(jì)的頂層接口進(jìn)行例化”,這一步相對(duì)比較簡(jiǎn)單,例化就是,但端口多時(shí)也夠喝一壺的,而且要分wire、reg,有時(shí)會(huì)弄錯(cuò),別難過,其實(shí)可以偷個(gè)懶,通過Quartus II自動(dòng)生成一個(gè)Testbench的模板,選擇Processing -》 Start -》 Start Test Bench Template Writer,等待完成后打開剛才生成的Testbench,默認(rèn)是保存在simulation\Modelsim文件夾下的.vt格式文件。這一步就不多講了,偷懶就挺好。
其次“給被測(cè)試設(shè)計(jì)的輸入接口添加激勵(lì)”,一般時(shí)序設(shè)計(jì)必然涉及到最基本的兩個(gè)信號(hào)——clk、rst_n(時(shí)鐘、復(fù)位),肯定有童鞋會(huì)講可以沒有rst_n,是可以沒有,但何必呢,讓代碼更健壯一點(diǎn)不很好嘛,別鉆牛角尖。下面攻克clk、rst_n的寫法:
首先先講一下timescale,因?yàn)橄胍M(jìn)行仿真首先要規(guī)定時(shí)間單位,而且最好在Testbench里面統(tǒng)一規(guī)定時(shí)間單位,而不要在工程代碼里定義,因?yàn)椴煌哪K如果時(shí)間單位不同可能會(huì)為仿真帶來一些問題,而timescale本身對(duì)綜合也就是實(shí)際電路沒有影響。 `timescale 1ns/ 1ps表示仿真的單位時(shí)間為1ns,精度為1ps。
上述三種代碼的目的就是產(chǎn)生系統(tǒng)時(shí)鐘,給clk一個(gè)初值后,不斷重復(fù)執(zhí)行:每10ns翻轉(zhuǎn)一次clk,從而生成一個(gè)周期為20ns,頻率50MHz的方波信號(hào)。第一、二種基本類似,第三種比較簡(jiǎn)單,少了一個(gè)initial,放在了always里初始化。
三種方法都無一例外地給clk賦了初值,因?yàn)樾盘?hào)的缺省值為Z,如果不賦初值,則反相后還是Z,時(shí)鐘就一直處于高阻Z狀態(tài)。小編同學(xué)一般選中第一種,看個(gè)人喜歡。
根據(jù)復(fù)位方式的不同,rst_n一般有兩種寫法:
上述兩種代碼的目的基本都是延時(shí)復(fù)位,但一個(gè)異步復(fù)位,一個(gè)同步復(fù)位,用途不同,小編同學(xué)一般使用異步復(fù)位。
最后“判斷被測(cè)試設(shè)計(jì)的輸出相應(yīng)是否滿足設(shè)計(jì)要求”。首先介紹最常用的兩個(gè)系統(tǒng)任務(wù)函數(shù)$stop和$finish。$stop代表暫停仿真后返回軟件操作主窗口,將控制權(quán)交給user;$finish代表終止仿真后關(guān)閉軟件操作主窗口。其他任務(wù)函數(shù)如$monitor、$display 、$time、$fwrite等也比較重要,用到的時(shí)候再一一介紹。為直觀介紹,使用一個(gè)例程來描述,下面是加法器的RTL代碼及Testbench:
?
注意了clk、rst_n后,其他端口根據(jù)需要相應(yīng)加測(cè)試信號(hào)即可,然后把RTL代碼及Testbench添加到Modelsim仿真觀察輸出波形等,以驗(yàn)證RTL代碼的正確與否,若與預(yù)期相符則驗(yàn)證結(jié)束,反之則修改代碼至與預(yù)期相符。
好了,Testbench就寫到這里,但沒有結(jié)束,實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn),下一篇將結(jié)合Modelsim,以可視化的方式繼續(xù)探討Testbench,深入了解仿真的意義。
testbench經(jīng)典教程VHDL
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
--use ieee.std_logic_unsigned.all;
entity cnt6 is
port
?。╟lr,en,clk :in std_logic;
q :out std_logic_vector(2 downto 0)
?。?
end entity;
architecture rtl of cnt6 is
signal tmp :std_logic_vector(2 downto 0);
begin
process(clk)
-- variable q6:integer;
begin
if(clk‘event and clk=’1‘) then
if(clr=’0‘)then
tmp《=“000”;
elsif(en=’1‘) then
if(tmp=“101”)then
tmp《=“000”;
else
tmp《=unsigned(tmp)+’1‘;
end if;
end if;
end if;
q《=tmp;
-- qa《=q(0);
-- qb《=q(1);
-- qc《=q(2);
end process;
end rtl;
六進(jìn)制計(jì)數(shù)器testbench的代碼
library ieee;
use ieee.std_logic_1164.all;
entity cnt6_tb is
end cnt6_tb;
architecture rtl of cnt6_tb is
component cnt6
port(
clr,en,clk :in std_logic;
q :out std_logic_vector(2 downto 0)
);
end component;
signal clr :std_logic:=‘0’;
signal en :std_logic:=‘0’;
signal clk :std_logic:=‘0’;
signal q :std_logic_vector(2 downto 0);
constant clk_period :time :=20 ns;
begin
instant:cnt6 port map
?。?/p>
clk=》clk,en=》en,clr=》clr,q=》q
?。?
clk_gen:process
begin
clk《=‘1’;
wait for clk_period/2;
clk《=‘0’;
end process;
clr_gen:process
begin
clr《=‘0’;
wait for 30 ns;
clr《=‘1’;
wait;
end process;
en_gen:process
begin
en《=‘0’;
wait for 50ns;
en《=‘1’;
wait;
end process;
end rtl;
其實(shí)testbench也有自己固定的一套格式,總結(jié)如下:
--測(cè)試平臺(tái)文件(testbench)的基本結(jié)構(gòu)
library ieee;
use ieee.std_logic_1164.all;
entity test_bench is --測(cè)試平臺(tái)文件的空實(shí)體(不需要端口定義)
end test_bench;
architecture tb_behavior of test_bench is
component entity_under_test --被測(cè)試元件的聲明
port(
list-of-ports-theri-types-and-modes
?。?
end component;
begin
instantiation:entity_under_test port map
?。?/p>
port-associations
?。?
process() --產(chǎn)生時(shí)鐘信號(hào)
……
end process;
process() --產(chǎn)生激勵(lì)源
……
end process;
end tb_behavior;
-------------------------------------------------------------------
--簡(jiǎn)單計(jì)數(shù)程序源碼
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_unsigned.all;
entity sim_counter is
port(
clk :in std_logic;
reset :in std_logic;
count :out std_logic_vector(3 downto 0)
?。?
end entity;
architecture behavioral of sim_counter is
signal temp :std_logic_vector(3 downto 0);
begin
process(clk,reset)
begin
if reset=‘1’ then
temp《=“0000”;
elsif clk‘event and clk=’1‘ then
temp《=temp+1;
end if;
end process;
count《=temp;
end behavioral;
-------------------------------------------------------------------
--簡(jiǎn)單計(jì)數(shù)程序,測(cè)試文件代碼(testbench)
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity counter_tb_vhd is --測(cè)試平臺(tái)實(shí)體
end counter_tb_vhd;
architecture behavior of counter_tb_vhd is
--被測(cè)試元件(DUT)的聲明
component sim_counter
port(
clk :in std_logic;
reset :in std_logic;
count :out std_logic_vector(3 downto 0)
?。?
end component;
--輸入信號(hào)
signal clk:std_logic:=’0‘;
signal reset :std_logic:=’0‘;
--輸出信號(hào)
signal count :std_logic_vector(3 downto 0);
constant clk_period :time :=20 ns; --時(shí)鐘周期的定義
begin
dut:sim_counter port map(
clk=》clk,reset=》reset,counter=》counter
);
clk_gen:process
begin
clk=’1‘;
wait for clk_period/2;
clk=’0‘;
wait for clk_period/2;
end process;
tb:process --激勵(lì)信號(hào)
begin
wait for 20 ns;
reset《=’1‘;
wait for 20 ns;
reset《=’0‘;
wait for 200 ns;
wait; --will wait forever;
end process;
end;
--激勵(lì)信號(hào)的產(chǎn)生方式
--1.以一定的離散時(shí)間間隔產(chǎn)生激勵(lì)信號(hào)的波形
--2.基于實(shí)體的狀態(tài)產(chǎn)生激勵(lì)信號(hào),也就是說基于實(shí)體的輸出響應(yīng)產(chǎn)生激勵(lì)信號(hào)
--兩種常用的復(fù)位信號(hào)
--1.周期性的激勵(lì)信號(hào),如時(shí)鐘
--2.時(shí)序變化的激勵(lì)型號(hào),如復(fù)位
--eg.產(chǎn)生不對(duì)稱時(shí)鐘信號(hào)
w_clk《=’0‘ after period/4 when w_clk=’1‘ else
’1‘ after 3*period/4 when w_clk=’0‘ else
’0‘;
--eg.產(chǎn)生堆成時(shí)鐘信號(hào),process語句
clk_gen1:process
constan clk_period := 40 ns;
begin
clk=’1‘;
wait for clk_period/2;
clk=’0‘;
wait for clk_period/2;
end process;
如果自己不想寫這些testbench的這些固定格式,可以在SIE里自動(dòng)生成testbench文件的模板
步驟:New Surce -》 VHDL Test Bench, 然后才會(huì)生成testbench
自動(dòng)生成的testbench模板格式如下:
-- Copyright (C) 1991-2008 Altera Corporation
-- Your use of Altera Corporation‘s design tools, logic functions
-- and other software and tools, and its AMPP partner logic
-- functions, and any output files from any of the foregoing
-- (including device programming or simulation files), and any
-- associated documentation or information are expressly subject
-- to the terms and conditions of the Altera Program License
-- Subscription Agreement, Altera MegaCore Function License
-- Agreement, or other applicable license agreement, including,
-- without limitation, that your use is for the sole purpose of
-- programming logic devices manufactured by Altera and sold by
-- Altera or its authorized distributors. Please refer to the
-- applicable agreement for further details.
-- ***************************************************************************
-- This file contains a Vhdl test bench template that is freely editable to
-- suit user’s needs .Comments are provided in each section to help the user
-- fill out necessary details.
-- ***************************************************************************
-- Generated on “03/13/2011 20:05:04”
-- Vhdl Test Bench template for design : cnt6
--
-- Simulation tool : ModelSim (VHDL)
--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY cnt6_vhd_tst IS
END cnt6_vhd_tst;
ARCHITECTURE cnt6_arch OF cnt6_vhd_tst IS
-- constants
-- signals
SIGNAL clk : STD_LOGIC;
SIGNAL clr : STD_LOGIC;
SIGNAL en : STD_LOGIC;
SIGNAL q : STD_LOGIC_VECTOR(2 DOWNTO 0);
COMPONENT cnt6
PORT (
clk : IN STD_LOGIC;
clr : IN STD_LOGIC;
en : IN STD_LOGIC;
q : OUT STD_LOGIC_VECTOR(2 DOWNTO 0)
?。?
END COMPONENT;
BEGIN
i1 : cnt6
PORT MAP (
-- list connections between master ports and signals
clk =》 clk,
clr =》 clr,
en =》 en,
q =》 q
?。?
init : PROCESS
-- variable declarations
BEGIN
-- code that executes only once
WAIT;
END PROCESS init;
always : PROCESS
-- optional sensitivity list
-- ( )
-- variable declarations
BEGIN
-- code executes for every event on sensitivity list
WAIT;
END PROCESS always;
END cnt6_arch;
評(píng)論
查看更多