这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » [求助]谁能帮我编译一下这个vhdl程序,我已经花了将近两个星期在这个程序上面了

共1条 1/1 1 跳转至

[求助]谁能帮我编译一下这个vhdl程序,我已经花了将近两个星期在这个程序上面了。

菜鸟
2005-04-11 00:21:13     打赏
错误检测与纠正电路的设计与实现(程序在最下面)

  在一些电磁环境比较恶劣的情况下,一些大规模集成电路常常会受到干扰,导致不能正常工作。特别是像RAM这种利用双稳态进行存储的器件,往往会在强干扰下发生翻转,使原来存储的"0"变为"1",或者"1"变为"0",造成的后果往往是很严重的。例如导致一些控制程序跑飞,存储的关键数据出错等等。现在,随着芯片集成度的增加,发生错误的可能性也在增大。在一些特定的应用中,这已经成为一个不能忽视的问题。例如在空间电子应用领域,单粒子翻转效应就成为困扰设计师的一个难题。

  在这种情况下,我们可以采用错误检测与纠正EDAC(Error Detection And Correction)电路来有效地减少或避免这种情况的出现。根据检错、纠错的原理,主要思想是在数据写入时,根据写入的数据生成一定位数的校验码,与相应的数据一起保存起来;当读出时,同时也将校验码读出,进行判决。如果出现一位错误则自动纠正,将正确的数据送出,并同时将改正以后的数据回写覆盖原来错误的数据;如果出现两位错误则产生中断报告,通知CPU进行异常处理。所有这一切动作都是靠硬件设计自动完成的,具有实时性和自动完成的特点。通过这样的EDAC电路,能大大提高系统的抗干扰能力,从而提高系统的可靠性。

  当然,有一些现成的集成电路芯片可以完成上述功能,如74系列的74630芯片等。但由于嵌入式系统中,往往由于集成化的需要,要将这样的功能集成到FPGA中去实现,因此采用VHDL语言进行设计具有灵活性和通用性的特点。

1 检错与纠错原理

  首先来看看检错和纠错的基本原理。进行差错控制的基本思想是在信息码组中以一定规则加入不同方式的冗余码,以便在信息读出的时候依靠多余的监督码或校验码来发现或自动纠正错误。

  针对误码发生的特点,即错误发生的随机性和小概率性,它几乎总是随机地影响某个字节中的某一位(bit),因此,如果能够设计自动纠正一位错误,而检测两位错误的编码方式,就可以大大的提高系统的可靠性。

  现在我们以16位的CPU数据总线为例,假定信息源的位数为16,要构造一种能够纠正一位错误,检查两位错误的编码方式。根据"纠错定?quot;,需要设计最小汉明距离≥4的码组。我们可以采用线形分组码,利用线性分组码的概念可以构造六位监督码,它们由如下线性关系产生:

  其中,d0~d15为16位数据(15为最高位MSB,0为最低位LSB),C0~C5为产生的六位监督码,表示进行异或运算。 在数据读出时,我们只需要考察伴随式S=[S0 S1 S2 S3 S4 S5],其中:

  很容易证明,根据伴随式进行误差诊断,符合表 1所列情况。

表1

当S = [0 0 0 0 0 0]时,数据正确无误; 当S = [0 0 1 0 1 1]时,数据错一位,并且错误发生在d0位,可将d0位的数据取反加以纠正; 当S = [0 0 1 1 0 1]时,数据错一位,并且错误发生在d1位,可将d1位的数据取反加以纠正; . . . 当S= [1 1 0 1 0 0]时,数据错一位,并且错误发生在d15位,可将d15位的数据取反加以纠正; 当S = [0 0 0 0 0 1]时,数据错一位,并且错误发生在C0位; . . . 当S = [1 0 0 0 0 0]时,数据错一位,并且错误发生在C5位; 当S为其它情况时,至少发生两位错误。

  可以看出,这种编码方式可以满足自动纠正一位错误,而发现两位错误的要求。下面就进一步讨论如何用电路来实现。

2 EDAC电路的设计

  EDAC电路必须配合CPU的读写时序进行工作,不同类型CPU的时序往往是不一样的。一般来说,总可以分为读周期和写周期。在写周期时,按照上面的设计逻辑,根据16位数据位生成6位的校验字,这时,数据位是输入,校验位是输出,并在该写周期中将数据位和校验位都存储到相应的存储器位置中去,这种情况比较简单。在读周期时,情况复杂些,可以设计成三步完成。第一步,在CPU读信号来之前,由于存储器地址和片选信号已经有效,可先将数据位和校验位读入,这时,数据位和校验位都是作为输入。第二步,在读信号来时,将数据位、校验位锁存,同时进行检测,如果无错,则不进行任何处理,直接将数据输出;如果发现二位错,则产生中断;如果是一位错,在输出上有所反应,并进入下一步。第三步,如果是数据位出错,将其自动更正,并将正确的值再回写到相应的内存地址中,将正确的数据值输出到数据总线;如果是校验位出错,可以直接将正确的数据位输出到数据总线上。这部分功能是EDAC功能的核心,可以用VHDL语言来实现,以下是设计思路。

(1)对输入的设计

① 数据位和校验位的输入。

② 控制端的输入。经过前面的分析,一共有四种状态(写一种状态、读三种状态),可以设计两个控制端,设为C0、C1。其功能见表 2。

表2

(2)对输出的设计

① 数据位和校验位的输出。其中校验位的输出在读周期和写周期有所不同:在写周期校验位输出是生成的校验位;而读周期就没有必要输出校验位了,可以设计为输出伴随式S。

② 错误标记输出。在应用中,可以设计两种错误标记输出,分别记为ERR和INT。其中ERR输出"1"表示数据位有错误产生,包括可自动纠正的一位错误和两位或两位以上错误。INT输出"1"则表示发生了两位或以上错误,无法自动纠正,向CPU申请中断,由CPU进行异常处理。 在表2中,总结了上面所描述的功能设计。

  图1为EDAC部分逻辑等效图。

  由于逻辑关系已经非常明确了,下面讨论采用VHDL语言实现上述EDAC模块的功能。可以有两种方法来实现VHDL编程,即RTL级语言描述和行为级语言描述。其中RTL级描述的实现难度比较大,需要根据前面设计的逻辑功能,转换为基本的门来描述;有效率高和受逻辑综合软件的影响小等优点,但可读性差,实现起来比较困难。因此我们采用的是行为级描述,根据四个输入作敏感量,用一个进程(process)就可以实现。编程思路是:根据控制端C0和C1进行判断,如果是写周期,直接将输入的数据相应位进行异或后输出;如果是读周期,先生成伴随式S,然后判断S,用CASE语句执行相应的输出。需要强调的是在不需要输出的时候,要把输出端用高阻封住。

  利用这个EDAC模块再辅以简单的外围电路就可以实现较强的EDAC功能,可以把这一部分整个电路都集成到FPGA中。

3 仿真结果

  仿真环境:MAX+plus II 10.0。   仿真模拟器件:FLEX 10K系列,EPF10K10LC84-3。   信号功能说明见表 3。

(1)写周期的仿真

  图 2所示仿真图中,275~500 ns仿真了一个写周期,数据输入是AA55,而校验位输出是00,通过验证是符合上面的设计逻辑的。

(2)读周期的仿真

在读周期的仿真中,我们模拟了以下四种情况。

① 正确的读周期:出现在650~975ns,校验位、数据位都是正确值。

② 数据位出现一位错误:图2中1.25~1.65 μs模拟了数据位产生一位错误的情况。数据正确的情况下应该是AA55,但现在d8位发生了错误,读入的数据变为AB55,可以看出数据已经被自动更正为AA55;同时,ERR输出"1"表明有错误发生,CBOUT输出为23,即100011,从表 1可以看出是d8位发生了错误。

③ 校验位出现一位错误:图2中1.8~2.0μs模拟了校验位产生一位错误的情况。校验位正确的情况下应该是00,但现在C2位发生了错误,读入的数据变为04,可以看出数据没变,仍为正确值AA55;同时,ERR没有输出,CBOUT输出为04,即000100,从表一可以看出是C2位发生了错误。

④ 发生了两位错误:图 2中2.4~2.75μs模拟了数据位产生两位错误的情况。数据正确的情况下应该是AA55,但现在d8位和d0位发生了错误,读入的数据变为AB54,可以看出EDAC电路已经无法自动更正。 ERR和INT同时输出"1"表明有多位错误发生,INT信号可以向CPU申请中断,用中断服务程序进行异常处理。

  可以看出仿真结果可以满足设计时的思想,能够起到自动纠正一位错误和检测两位错误的功能。

结 语

  本文利用纠错编码的基本知识,提出了一种简单实用的能自动纠正一位错误和检查两位错误的编码方法,并且通过VHDL语言编程,用FPGA器件来实现。在我们自己的嵌入式系统中,EDAC电路已经得到了应用和验证。现在越来越多的嵌入式系统对可靠性要求越来越高,采用EDAC技术可以简单有效地提高系统的容错能力;但针对不同系统,EDAC和CPU的时序配合可能会有所不同。例如,对于一些时钟频率比较高的CPU,可能需要插入等待周期等等,但由于采用VHDL语言进行设计,有很大的灵活性,稍加改动就可以满足不同场合的需求。

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_arith.all;

entity edac is

port(c0, c1: in std_logic;

dbin: in unsigned (15 downto 0);

cbin: in unsigned (5 downto 0);

dbout: out unsigned (15 downto 0);

cbout: out unsigned (5 downto 0);

err, int: out std_logic

);

end edac;

architecture edac of edac is

signal dbs: unsigned (15 downto 0);

signal cbs: unsigned (5 downto 0);

signal cbt: unsigned (5 downto 0);

begin

process(c0,c1,dbin,cbin)

variable temp: std_logic;

begin

if (c1='0') and (c0='0') then

cbout(0)<=dbin(0) xor dbin(1) xor dbin(3) xor dbin(4) xor dbin(8) xor dbin(9) xor dbin(10) xor dbin(13);

cbout(1)<=dbin(0) xor dbin(2) xor dbin(3) xor dbin(5) xor dbin(6) xor dbin(8) xor dbin(11) xor dbin(14);

cbout(2)<=dbin(1) xor dbin(2) xor dbin(4) xor dbin(5) xor dbin(7) xor dbin(9) xor dbin(12) xor dbin(15);

cbout(3)<=dbin(0) xor dbin(1) xor dbin(2) xor dbin(6) xor dbin(7) xor dbin(10) xor dbin(11) xor dbin(12);

cbout(4)<=dbin(3) xor dbin(4) xor dbin(5) xor dbin(6) xor dbin(7) xor dbin(13) xor dbin(14) xor dbin(15);

cbout(5)<=dbin(8) xor dbin(9) xor dbin(10) xor dbin(11) xor dbin(12) xor dbin(13) xor dbin(14) xor dbin(15);

err<='0';

int<='0';

dbout<="ZZZZZZZZZZZZZZZZ";

else

cbt(0)<=not(dbs(0) xor dbs(1) xor dbs(3) xor dbs(4) xor dbs(8) xor dbs(9) xor dbs(10) xor dbs(13) xor cbs(0));

cbt(1)<=not(dbs(0) xor dbs(2) xor dbs(3) xor dbs(5) xor dbs(6) xor dbs(8) xor dbs(11) xor dbs(14) xor cbs(1));

cbt(2)<=not(dbs(1) xor dbs(2) xor dbs(4) xor dbs(5) xor dbs(7) xor dbs(9) xor dbs(12) xor dbs(15) xor cbs(2));

cbt(3)<=not(dbs(0) xor dbs(1) xor dbs(2) xor dbs(6) xor dbs(7) xor dbs(10) xor dbs(11) xor dbs(12) xor cbs(3));

cbt(4)<=not(dbs(3) xor dbs(4) xor dbs(5) xor dbs(6) xor dbs(7) xor dbs(13) xor dbs(14) xor dbs(15) xor cbs(4));

cbt(5)<=not(dbs(8) xor dbs(9) xor dbs(10) xor dbs(11) xor dbs(12) xor dbs(13) xor dbs(14) xor dbs(15) xor cbs(5));

if (c1='0') and (c0='1') then

dbs<=dbin;

cbs<=cbin;

err<='0';

int<='0';

dbout<="ZZZZZZZZZZZZZZZZ";

cbout<="ZZZZZZ";

elsif (c1='1') then

case cbt is

when "110100" =>

err<='1';

int<='0';

if (c0='0') then

dbout(0)<=not(dbs(0));

for i in 1 to 15 loop

dbout(i)<=dbs(i);

end loop;

cbout<=cbt;

end if;

when "110010" =>

err<='1';

int<='0';

if (c0='0') then

dbout(0)<=dbs(0);

dbout(1)<=not(dbs(1));

for i in 2 to 15 loop

dbout(i)<=dbs(i);

end loop;

cbout<=cbt;

end if;

when "110001" =>

err<='1';

int<='0';

if (c0='0') then

dbout(0)<=dbs(0);

dbout(1)<=dbs(1);

dbout(2)<=not(dbs(2));

for i in 3 to 15 loop

dbout(i)<=dbs(i);

end loop;

cbout<=cbt;

end if;

when "101100" =>

err<='1';

int<='0';

if (c0='0') then

for i in 0 to 2 loop

dbout(i)<=dbs(i);

end loop;

dbout(3)<=not(dbs(3));

for i in 4 to 15 loop

dbout(i)<=dbs(i);

end loop;

cbout<=cbt;

end if;

when "101010" =>

err<='1';

int<='0';

if (c0='0') then

for i in 0 to 3 loop

dbout(i)<=dbs(i);

end loop;

dbout(4)<=not(dbs(4));

for i in 5 to 15 loop

dbout(i)<=dbs(i);

end loop;

cbout<=cbt;

end if;

when "101001" =>

err<='1';

int<='0';

if (c0='0') then

for i in 0 to 4 loop

dbout(i)<=dbs(i);

end loop;

dbout(5)<=not(dbs(5));

for i in 6 to 15 loop

dbout(i)<=dbs(i);

end loop;

cbout<=cbt;

end if;

when "100101" =>

err<='1';

int<='0';

if (c0='0') then

for i in 0 to 5 loop

dbout(i)<=dbs(i);

end loop;

dbout(6)<=not(dbs(6));

for i in 7 to 15 loop

dbout(i)<=dbs(i);

end loop;

cbout<=cbt;

end if;

when "100011" =>

err<='1';

int<='0';

if (c0='0') then

for i in 0 to 6 loop

dbout(i)<=dbs(i);

end loop;

dbout(7)<=not(dbs(7));

for i in 8 to 15 loop

dbout(i)<=dbs(i);

end loop;

cbout<=cbt;

end if;

when "011100" =>

err<='1';

int<='0';

if (c0='0') then

for i in 0 to 7 loop

dbout(i)<=dbs(i);

end loop;

dbout(8)<=not(dbs(8));

for i in 9 to 15 loop

dbout(i)<=dbs(i);

end loop;

cbout<=cbt;

end if;

when "011010" =>

err<='1';

int<='0';

if (c0='0') then

for i in 0 to 8 loop

dbout(i)<=dbs(i);

end loop;

dbout(9)<=not(dbs(9));

for i in 10 to 15 loop

dbout(i)<=dbs(i);

end loop;

cbout<=cbt;

end if;

when "010110" =>

err<='1';

int<='0';

if (c0='0') then

for i in 0 to 9 loop

dbout(i)<=dbs(i);

end loop;

dbout(10)<=not(dbs(10));

for i in 11 to 15 loop

dbout(i)<=dbs(i);

end loop;

cbout<=cbt;

end if;

when "010101" =>

err<='1';

int<='0';

if (c0='0') then

for i in 0 to 10 loop

dbout(i)<=dbs(i);

end loop;

dbout(11)<=not(dbs(11));

for i in 12 to 15 loop

dbout(i)<=dbs(i);

end loop;

cbout<=cbt;

end if;

when "010011" =>

err<='1';

int<='0';

if (c0='0') then

for i in 0 to 11 loop

dbout(i)<=dbs(i);

end loop;

dbout(12)<=not(dbs(12));

for i in 13 to 15 loop

dbout(i)<=dbs(i);

end loop;

cbout<=cbt;

end if;

when "001110" =>

err<='1';

int<='0';

if (c0='0') then

for i in 0 to 12 loop

dbout(i)<=dbs(i);

end loop;

dbout(13)<=not(dbs(13));

for i in 14 to 15 loop

dbout(i)<=dbs(i);

end loop;

cbout<=cbt;

end if;

when "001101" =>

err<='1';

int<='0';

if (c0='0') then

for i in 0 to 13 loop

dbout(i)<=dbs(i);

end loop;

dbout(14)<=not(dbs(14));

dbout(15)<=dbs(15);

cbout<=cbt;

end if;

when "001011" =>

err<='1';

int<='0';

if (c0='0') then

for i in 0 to 14 loop

dbout(i)<=dbs(i);

end loop;

dbout(15)<=not(dbs(15));

cbout<=cbt;

end if;

when "111110" =>

err<='1';

int<='0';

if (c0='0') then

dbout<=dbs;

cbout<=cbt;

end if;

when "111101" =>

err<='1';

int<='0';

if (c0='0') then

dbout<=dbs;

cbout<=cbt;

end if;

when "111011" =>

err<='1';

int<='0';

if (c0='0') then

dbout<=dbs;

cbout<=cbt;

end if;

when "110111" =>

err<='1';

int<='0';

if (c0='0') then

dbout<=dbs;

cbout<=cbt;

end if;

when "101111" =>

err<='1';

int<='0';

if (c0='0') then

dbout<=dbs;

cbout<=cbt;

end if;

when "011111" =>

err<='1';

int<='0';

if (c0='0') then

dbout<=dbs;

cbout<=cbt;

end if;

when "111111" =>

err<='0';

int<='0';

if (c0='0') then

dbout<=dbs;

cbout<=cbt;

end if;

when others =>

err<='1';

int<='1';

if (c0='0') then

dbout<=dbs;

cbout<=cbt;

end if;

end case;

end if;

end if;

if (c1='1') and (c0='0') then

cbout<=cbt;

end if;

end process;

end edac;




关键词: 求助     谁能     帮我     编译     一下     这个     程序     已经         

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]