综合优化(synthesize)是指将HDL语言,原理图等设计输入翻译成由与或非门,RAM,触发器等基本逻辑单元组成的逻辑连接,也就是所谓的逻辑网表,并根据目标与要求(约束条件)优化所生成的逻辑连接,输出edf和edn等文件。
综合过程包括两个内容,一是对硬件语言源代码输入进行编译与逻辑层次上的优化,二是对编译结果进行逻辑映射与结构层次上的优化,最后生成逻辑网表。
综合结果的优劣直接影响布局布线结果的最终效能。综合结果的优劣是以使设计芯片的物理面积最小和工作频率最高为指标。当两者发生冲突时,一般采用速度优先的原则。
*****************************************************************************
****该程序实现了8位的奇偶校验***********************************************
*****************************************************************************
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity parity_check is
generic(size : integer :=8);
port(data_in:in std_logic_vector(size - 1 downto 0);
even_odd:in std_logic;
pa_out:out std_logic_vector(size downto 0));
end parity_check;
architecture Behavioral of parity_check is
signal temp:std_logic;
begin
process(even_odd,data_in)
begin
if(even_odd='1') then
temp<=data_in(7) xor data_in(6) xor data_in(5) xor data_in(4) xor data_in(3)xor data_in(2) xor data_in(1) xor data_in(0);
else
temp<=data_in(7) xor data_in(6) xor data_in(5) xor data_in(4) xor data_in(3)xor data_in(2) xor data_in(1) xor data_in(0) xor '1';
end if;
end process;
pa_out<=temp&data_in;
end Behavioral;
*******************************************************************************
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.all;
USE ieee.numeric_std.ALL;
ENTITY test_vhd IS
END test_vhd;
ARCHITECTURE behavior OF test_vhd IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT parity_check
generic(size : integer := 8);
PORT(
data_in : IN std_logic_vector(size-1 downto 0);
even_odd : IN std_logic;
pa_out : OUT std_logic_vector(size downto 0)
);
END COMPONENT;
--Inputs
SIGNAL even_odd : std_logic := '0';
SIGNAL data_in : std_logic_vector(7 downto 0) := (others=>'0');
--Outputs
SIGNAL pa_out : std_logic_vector(8 downto 0);
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: parity_check PORT MAP(
data_in => data_in,
even_odd => even_odd,
pa_out => pa_out
);
tb : PROCESS
BEGIN
-- Wait 100 ns for global reset to finish
wait for 100 ns;
data_in(7 downto 0)<="10001111";
even_odd<='1';
wait for 100 ns;
data_in(7 downto 0)<="11110000";
even_odd<='0';
wait for 100 ns;
data_in(7 downto 0)<="10001111";
even_odd<='0';
wait for 100 ns;
data_in(7 downto 0)<="11110000";
even_odd<='1';
wait; -- will wait forever
END PROCESS
END;
*******************************************************************************
使用verilog 语言编写的奇偶校验
`define DELAY 1
module parity_check(data_in,pa_in,even_odd,pa_out,error);
input[7:0];
input pa_in;
input even_odd;
output pa_out;
output error;
wire [7:0] data_in;
wire pa_in;
wire even_odd;
wire pa_out;
wire error;
assign #`DELAY pa_out=even_odd ? ^data_in[7:0]:~^data_in[7:0];
assign #`DELAY error=even_odd ? ^(data_in[7:0],pa_in):~^(data_in[7:0],pa_in);
endmodule;
*******************************************************************************
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity parity_check1 is
generic(size : integer :=8);
port(data_in:in std_logic_vector(size-1 downto 0);
pa_in:in std_logic;
even_odd:in std_logic;
error:out std_logic;
pa_out:out std_logic);
end parity_check1;
architecture Behavioral of parity_check1 is
begin
process(data_in,pa_in,even_odd)
begin
if(even_odd='0') then
pa_out<= not (data_in(size-1) xor data_in(size -2) xor data_in(size-3) xor data_in(size-4) xor data_in(size-5) xor data_in(size-6) xor data_in(size-7) xor data_in(size-8));
error<=not (pa_in xor data_in(size-1) xor data_in(size -2) xor data_in(size-3) xor data_in(size-4) xor data_in(size-5) xor data_in(size-6) xor data_in(size-7) xor data_in(size-8));
else
pa_out<= data_in(size-1) xor data_in(size -2) xor data_in(size-3) xor data_in(size-4) xor data_in(size-5) xor data_in(size-6) xor data_in(size-7) xor data_in(size-8);
error<=pa_in xor data_in(size-1) xor data_in(size -2) xor data_in(size-3) xor data_in(size-4) xor data_in(size-5) xor data_in(size-6) xor data_in(size-7) xor data_in(size-8);
end if;
end process;
end Behavioral;
************************************************************************************
*******************************************************************************
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity parity_check1 is
generic(size : integer :=8);
port(data_in:in std_logic_vector(size-1 downto 0);
pa_in:in std_logic;
even_odd:in std_logic;
error:out std_logic;
pa_out:out std_logic);
end parity_check1;
architecture Behavioral of parity_check1 is
begin
process(data_in,pa_in,even_odd)
begin
if(even_odd='0') then
pa_out<= not (data_in(size-1) xor data_in(size -2) xor data_in(size-3) xor data_in(size-4) xor data_in(size-5) xor data_in(size-6) xor data_in(size-7) xor data_in(size-8));
error<=not (pa_in xor data_in(size-1) xor data_in(size -2) xor data_in(size-3) xor data_in(size-4) xor data_in(size-5) xor data_in(size-6) xor data_in(size-7) xor data_in(size-8));
else
pa_out<= data_in(size-1) xor data_in(size -2) xor data_in(size-3) xor data_in(size-4) xor data_in(size-5) xor data_in(size-6) xor data_in(size-7) xor data_in(size-8);
error<=pa_in xor data_in(size-1) xor data_in(size -2) xor data_in(size-3) xor data_in(size-4) xor data_in(size-5) xor data_in(size-6) xor data_in(size-7) xor data_in(size-8);
end if;
end process;
end Behavioral;
************************************************************************************
-- A First-in First-out Memory -- a first-in first out memory, uses a synchronising clock -- generics allow fifos of different sizes to be instantiated -- download from: www.fpga.com.cn & www.pld.com.cn library IEEE; use IEEE.Std_logic_1164.all; entity FIFOMXN is generic(m, n : Positive := 8); --m is fifo depth, n is fifo width port(RESET, WRREQ, RDREQ, CLOCK : in Std_logic; DATAIN : in Std_logic_vector((n-1) downto 0); DATAOUT : out Std_logic_vector((n-1) downto 0); FULL, EMPTY : inout Std_logic); end FIFOMXN; architecture V2 of FIFOMXN is type Fifo_array is array(0 to (m-1)) of Bit_vector((n-1) downto 0); signal Fifo_memory : Fifo_array; signal Wraddr, Rdaddr, Offset : Natural range 0 to (m-1); signal Rdpulse, Wrpulse, Q1, Q2, Q3, Q4 : Std_logic; signal Databuffer : Bit_vector((n-1) downto 0); begin --pulse synchronisers for WRREQ and RDREQ --modified for Synplify to a process sync_ffs : process begin wait until rising_edge(CLOCK); Q1 <= WRREQ; Q2 <= Q1; Q3 <= RDREQ; Q4 <= Q3; end process; --concurrent logic to generate pulses Wrpulse <= Q2 and not(Q1); Rdpulse <= Q4 and not(Q3); Fifo_read : process begin wait until rising_edge(CLOCK); if RESET = '1' then Rdaddr <= 0; Databuffer <= (others => '0'); elsif (Rdpulse = '1' and EMPTY = '0') then Databuffer <= Fifo_memory(Rdaddr); Rdaddr <= (Rdaddr + 1) mod m; end if; end process; Fifo_write : process begin wait until rising_edge(CLOCK); if RESET = '1' then Wraddr <= 0; elsif (Wrpulse = '1' and FULL = '0') then Fifo_memory(Wraddr) <= To_Bitvector(DATAIN); Wraddr <= (Wraddr + 1) mod m; end if; end process; Offset <= (Wraddr - Rdaddr) when (Wraddr > Rdaddr) else (m - (Rdaddr - Wraddr)) when (Rdaddr > Wraddr) else 0; EMPTY <= '1' when (Offset = 0) else '0'; FULL <= '1' when (Offset = (m-1)) else '0'; DATAOUT <= To_Stdlogicvector(Databuffer) when RDREQ = '0' else (others => 'Z'); end V2;V2;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
第一步,逻辑综合:假定project对应的verilog源文件为iseprj.v
输入:iseprj.v
输出:iseprj.ngc
报告文件
第二步,translate:
输入文件:
.ngc ---netlist files
.ucf ---constraint file
输出文件:
.ngd ----Native Generic Database file
报告文件
第三步,map:
输入文件:
.ngd ----Native Generic Database file
输出文件:
_map.ncd
报告文件
第四步,place&route:
输入文件:
_map.ncd
输出文件:
.ncd -----par 的ncd文件,用于生成bit 文件
报告文件
¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥
*.bit 下载配置文件。
*.bld 报告文件。
*.edn 网表文件。
*.dly 异步延时报告对于最坏的20个路径。
*.fdo 自动创建的仿真宏文件。
*.fnf 文件为floorplan 文件。
*.mpf 文件来存储对设计的物理约束。
*.mfp 由Floorplanner 产生的布局规划期的实现指导文件。
*.mrp 映射报告文件。
*.nav 报告文件和bld 一样的内容但是察看方式不同。
*.ngd 综合之后的包含了ucf和网表信息的文件。
*.ngc 包含了逻辑设计数据和约束的网表。
*.ncf 网表的约束文件工具自动生成与ucf一样但ucf优先级更高。
*.nmc 物理宏库单元文件包含了物理宏库的定义同时这个物理宏可以在FPGA底层编辑器中以及HDL编码中实例化。
*.nce 布局布线后设计。
*.ncd native circuit description 根据所选器件由ngd文件映射后生成的使用CLB和IOB描述一个提供给布局布线信息的文件。
*.pcf 物理约束文件,约束设计的物理位置,含有设计的时钟频率工作电压,All Location and Timing Constraints are written to a PC
F during MAP。
*.pwr 功耗报告文件。
*.pad 管脚约束报告。
*.par 布局布线报告。
*.sdf 布局布线后的延时反标文件。
*.twr 映射后静态时序报告。
*.twx 布局布线后静态时序报告。
*.ucf 用户约束文件。
*.v verilog文件。
*.vhd vhdl 文件。
*.xml为用户设置文件保存Xpower 的主要设置。
*********************************************************************************************************************************************************************
Input files to the Constraints Editor are:
· User constraints file (UCF ). Constraints created by the user are written to this file.
· XST Constraints File (XCF ). Constraints created for XST.
· Native generic database (NGD ) file. This file is sometimes called the design file, and serves as input to the mapper .
Constraints Editor saves the UCF or XCF(tm) when you use the Save or Save As commands.
During translation and implementation:
· NGDBuild uses the UCF and design source netlists to produce a native generic database (NGD) file.
· The NGD file is read by the MAP program, which generates a native circuit description (NCD) file and a physical constraints file (PCF).
· The implementation tools use the NCD and PCF files to produce a bitstream.
· XST uses the XCF file as its constraints specifications.
所谓的同步FIFO是指读写操作均在时钟的上升沿进行。
2.什么情况下用FIFO?
FIFO一般用于不同时钟域之间的数据传输,比如FIFO的一端时AD数据采集,另一端时计算机的PCI总线,假设其AD采集的速率为16位 100K SPS,那么每秒的数据量为100K×16bit=1.6Mbps,而PCI总线的速度为33MHz,总线宽度32bit,其最大传输速率为1056Mbps,在两个不同的时钟域间就可以采用FIFO来作为数据缓冲。另外对于不同宽度的数据接口也可以用FIFO,例如单片机位8位数据输出,而DSP可能是16位数据输入,在单片机与DSP连接时就可以使用FIFO来达到数据匹配的目的。
3.FIFO的一些重要参数
FIFO的宽度:也就是英文资料里常看到的THE WIDTH,它只的是FIFO一次读写操作的数据位,就像MCU有8位和16位,ARM 32位等等,FIFO的宽度在单片成品IC中是固定的,也有可选择的,如果用FPGA自己实现一个FIFO,其数据位,也就是宽度是可以自己定义的。
FIFO的深度:THE DEEPTH,它指的是FIFO可以存储多少个N位的数据(如果宽度为N)。如一个8位的FIFO,若深度为8,它可以存储8个8位的数据,深度为12 ,就可以存储12个8位的数据,FIFO的深度可大可小,个人认为FIFO深度的计算并无一个固定的公式。在FIFO实际工作中,其数据的满/空标志可以控制数据的继续写入或读出。在一个具体的应用中也不可能由一些参数算数精确的所需FIFO深度为多少,这在写速度大于读速度的理想状态下是可行的,但在实际中用到的FIFO深度往往要大于计算值。一般来说根据电路的具体情况,在兼顾系统性能和FIFO成本的情况下估算一个大概的宽度和深度就可以了。而对于写速度慢于读速度的应用,FIFO的深度要根据读出的数据结构和读出数据的由那些具体的要求来确定。
满标志:FIFO已满或将要满时由FIFO的状态电路送出的一个信号,以阻止FIFO的写操作继续向FIFO中写数据而造成溢出(overflow)。
空标志:FIFO已空或将要空时由FIFO的状态电路送出的一个信号,以阻止FIFO的读操作继续从FIFO中读出数据而造成无效数据的读出(underflow)。
读时钟:读操作所遵循的时钟,在每个时钟沿来临时读数据。
写时钟:写操作所遵循的时钟,在每个时钟沿来临时写数据。
读指针:指向下一个读出地址。读完后自动加1。
写指针:指向下一个要写入的地址的,写完自动加1。
读写指针其实就是读写的地址,只不过这个地址不能任意选择,而是连续的。
4.FIFO的分类
根均FIFO工作的时钟域,可以将FIFO分为同步FIFO和异步FIFO。同步FIFO是指读时钟和写时钟为同一个时钟。在时钟沿来临时同时发生读写操作。异步FIFO是指读写时钟不一致,读写时钟是互相独立的。
5.FIFO设计的难点FIFO设计的难点在于怎样判断FIFO的空/满状态。为了保证数据正确的写入或读出,而不发生益处或读空的状态出现,必须保证FIFO在满的情况下,不能进行写操作。在空的状态下不能进行读操作。怎样判断FIFO的满/空就成了FIFO设计的核心问题。由于同步FIFO几乎很少用到,这里只描述异步FIFO的空/满标志产生问题。
在用到触发器的设计中,不可避免的会遇到亚稳态的问题(关于亚稳态这里不作介绍,可查看相关资料)。在涉及到触发器的电路中,亚稳态无法彻底消除,只能想办法将其发生的概率将到最低。其中的一个方法就是使用格雷码。格雷码在相邻的两个码元之间只由一位变换(二进制码在很多情况下是很多码元在同时变化)。这就会避免计数器与时钟同步的时候发生亚稳态现象。但是格雷码有个缺点就是只能定义2^n的深度,而不能像二进制码那样随意的定义FIFO的深度,因为格雷码必须循环一个2^n,否则就不能保证两个相邻码元之间相差一位的条件,因此也就不是真正的各雷码了。第二就是使用冗余的触发器,假设一个触发器发生亚稳态的概率为P,那么两个及联的触发器发生亚稳态的概率就为P的平方。但这回导致延时的增加。亚稳态的发生会使得FIFO出现错误,读/写时钟采样的地址指针会与真实的值之间不同,这就导致写入或读出的地址错误。由于考虑延时的作用,空/满标志的产生并不一定出现在FIFO真的空/满时才出现。可能FIFO还未空/满时就出现了空/满标志。这并没有什么不好,只要保证FIFO不出现overflow or underflow 就OK了。
很多关于FIFO的文章其实讨论的都是空/满标志的不同算法问题。
在Vijay A. Nebhrajani的《异步FIFO结构》一文中,作者提出了两个关于FIFO空/满标志的算法。
第一个算法:构造一个指针宽度为N+1,深度为2^N字节的FIFO(为便方比较将格雷码指针转换为二进制指针)。当指针的二进制码中最高位不一致而其它N位都相等时,FIFO为满(在Clifford E. Cummings的文章中以格雷码表示是前两位均不相同,而后两位LSB相同为满,这与换成二进制表示的MSB不同其他相同为满是一样的)。当指针完全相等时,FIFO为空。这也许不容易看出,举个例子说明一下:一个深度为8字节的FIFO怎样工作(使用已转换为二进制的指针)。FIFO_WIDTH=8,FIFO_DEPTH= 2^N = 8,N = 3,指针宽度为N+1=4。起初rd_ptr_bin和wr_ptr_bin均为“0000”。此时FIFO中写入8个字节的数据。wr_ptr_bin =“1000”,rd_ptr_bin=“0000”。当然,这就是满条件。现在,假设执行了8次的读操作,使得rd_ptr_bin =“1000”,这就是空条件。另外的8次写操作将使wr_ptr_bin 等于“0000”,但rd_ptr_bin 仍然等于“1000”,因此FIFO为满条件。
显然起始指针无需为“0000”。假设它为“0100”,并且FIFO为空,那么8个字节会使wr_ptr_bin =“1100”,, rd_ptr_bin 仍然为“0100”。这又说明FIFO为满。
在Vijay A. Nebhrajani的这篇《异步FIFO结构》文章中说明了怎样运用格雷码来设置空满的条件,但没有说清为什么深度为8的FIFO其读写指针要用3+1位的格雷码来实现,而3+1位的格雷码可以表示16位的深度,而真实的FIFO只有8位,这是怎么回事?而这个问题在Clifford E. Cummings的文章中得以解释。三位格雷码可表示8位的深度,若在加一位最为MSB,则这一位加其他三位组成的格雷码并不代表新的地址,也就是说格雷码的0100表示表示7,而1100仍然表示7,只不过格雷码在经过一个以0位MSB的循环后进入一个以1为MSB的循环,然后又进入一个以0位MSB的循环,其他的三位码仍然是格雷码,但这就带来一个问题,在0100的循环完成后,进入1000,他们之间有两位发生了变换,而不是1位,所以增加一位MSB的做法使得该码在两处:0100~1000,1100~0000有两位码元发生变化,故该码以不是真正的格雷码。增加的MSB是为了实现空满标志的计算。Vijay A. Nebhrajani的文章用格雷码转二进制,再转格雷码的情况下提出空满条件,仅过两次转换,而Clifford E. Cummings的文章中直接在格雷码条件下得出空满条件。其实二者是一样的,只是实现方式不同罢了。
第二种算法:Clifford E. Cummings的文章中提到的STYLE #2。它将FIFO地址分成了4部分,每部分分别用高两位的MSB 00 、01、 11、 10决定FIFO是否为going full 或going empty (即将满或空)。如果写指针的高两位MSB小于读指针的高两位MSB则FIFO为“几乎满”,
若写指针的高两位MSB大于读指针的高两位MSB则FIFO为“几乎空”。
在Vijay A. Nebhrajani的《异步FIFO结构》第三部分的文章中也提到了一种方法,那就是方向标志与门限。设定了FIFO容量的75%作为上限,设定FIFO容量的25%为下限。当方向标志超过门限便输出满/空标志,这与Clifford E. Cummings的文章中提到的STYLE #2可谓是异曲同工。他们都属于保守的空满判断。其实这时输出空满标志FIFO并不一定真的空/满。
说到此,我们已经清楚地看到,FIFO设计最关键的就是产生空/满标志的算法的不同产生了不同的FIFO。但无论是精确的空满还是保守的空满都是为了保证FIFO工作的可靠。
6.关于FIFO的一点的思考
关于FIFO丢数据的问题,其实各位对同一个问题的理解有偏差,才造成了相互误解。如果在理想状况下(时钟同步不回出现错码),FIFO由读写指针控制是不会丢数的,(这不是废话吗,现实中哪来的理想状况!)且慢,我的意思是说丢数据并不是读写谁快谁慢造成的,在正确的设置空满标志算法的情况下,数据的overflow 和underflow 是不会发生的。而往往现实中因为亚稳态的存在,才出现了丢数的情况,也就是说是只要读写时钟不同步,在采样的过程中采样出错,使得本该是0100的变成了1101等等,就会出现读写的错误,我们称其为丢数,其原因就是在时钟同步指针的时候出现亚稳态,由于二进制码加1的时候很多位同时变化,所以很容易出现亚稳态。因此才用格雷码将此问题发生的概率比降到最小,其次用多余的触发器使其概率进一步降低,也就是说错误难免,但我们可以将其发生的概率降到最低,并且在出现错误时也不会错的态离谱(详见Vijay A. Nebhrajani的《异步FIFO结构》第二篇)。
二进制码指针并非不好用,在前面也提到了它有自身的优势,由于通过设置握手信号,指针可以有多位同时变化,二进制指针每次移动可以跳跃过任意的长度,这样给FIFO的某些功能的实现带来了方便(例如,硬件直接控制FIFO从缓存的数据流中丢弃一个出错的包);而格雷码指针一般只能做递增或递减的移动。设置握手信号虽然可以保证指针不出错,但这样你来我往的经过三四个回合才能开始传数据,所以对于高速的场合就不适用了。
--this is 同步fifo 8*8 (depth * width)
--language vhdl ,by chendafeng
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity fifo is
generic (n : positive := 8;
m : positive := 8);--n is the fifo's width and m is the fifo's depth
port(clk:in std_logic;
reset: in std_logic;
datain:in std_logic_vector(n-1 downto 0);
wrreq:in std_logic;
rdreq:in std_logic;
dataout:out std_logic_vector(n-1 downto 0);
empty:inout std_logic;
full:inout std_logic);
end fifo;
architecture Behavioral of fifo is
type fifo_mem is array((m-1) downto 0) of std_logic_vector((n-1) downto 0);
signal q1,q2,q3,q4,wrpulse,rdpulse:std_logic;
signal fifo_memory:fifo_mem;
signal databuffer:std_logic_vector(n-1 downto 0);
signal wraddr,rdaddr,offset:integer range 0 to (m-1);--range 0 to (m-1)
begin
tongbu:process(clk) ---脉冲同步
begin
if(clk'event and clk='1') then
q1<=wrreq;
q2<=q1;
q3<=rdreq;
q4<=q3;
end if;
end process;
wrpulse<=q2 and (not q1);
rdpulse<=q4 and (not q3);
fifo_read:process(clk,reset,rdpulse)
begin
if (clk'event and clk='1') then
if (reset='1') then
rdaddr<=0;
databuffer<=(others=>'0');
elsif (rdpulse='1' and empty='0') then
databuffer<=fifo_memory(rdaddr);
if(rdaddr/=rdaddr'right) then
rdaddr<=rdaddr+1;
else
rdaddr<=0;
end if;
end if;
end if;
end process;
fifo_write:process(clk,reset,wrpulse,datain)
begin
if(clk'event and clk='1') then
if( reset='1') then
wraddr<=0;
elsif(wrpulse='1' and full='0') then
fifo_memory(wraddr)<=datain;
if(wraddr/=wraddr'high) then
wraddr<=wraddr+1;
else
wraddr<=0;
end if;
end if;
end if;
end process;
fifo_offset:process(wraddr,rdaddr)
begin
if(wraddr>rdaddr) then
offset<=wraddr-rdaddr;
elsif(wraddr
offset<=(m-(rdaddr-wraddr));
else
offset<=0;
end if;
end process;
fifo_full_empty:process(offset)
begin
if(offset=offset'low) then
empty<='1';
full<='0';
elsif(offset=offset'high) then
empty<='0';
full<='1';
else
empty<='0';
full<='0';
end if;
end process;
fifo_out:process(rdreq,databuffer)
begin
if rdreq='0' then
dataout<=conv_std_logic_vector(databuffer,n);
else
dataout<="XXXXXXXX";
end if;
end process;
end Behavioral;
参考:http://blog.csdn.net/dafengchen/archive/2007/06/02/1635849.aspx
发表评论 评论 (2 个评论)