快讯
HOME
快讯
正文内容
nand的vhdl VHDL描述基本逻辑门
发布时间 : 2024-11-25
作者 : 小编
访问数量 : 23
扫码分享至微信

VHDL描述基本逻辑门

简单地说,逻辑门是数字电路的基本结构,所有数字电路都由与门和、与非门、或非和反相器组成。逻辑门电路常用于各种电子设备硬件,如计算机、数字手表、电视、手机…

1,非门,又称反相器,简称非门,是逻辑电路的基本单元。非门有一个输入和一个输出端。当其输入端为高电平(逻辑1)时输出端为低电平(逻辑0),当其输入端为低电平时输出端为高电平。也就是说,输入端和输出端的电平状态总是反相的。非门的逻辑功能相当于逻辑代数中的非,电路功能相当于反相,这种运算亦称非运算。

非门符号

非门真值表

非门真值表

VHDL 代码

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity NOT_GATE is

Port ( A : in STD_LOGIC;

B : out STD_LOGIC);

end NOT_GATE;

architecture Behavioral of NOT_GATE is

begin

B <= NOT A;

end Behavioral;

仿真波形

非门仿真波形

2,与门是执行“与”运算的基本逻辑门电路。有多个输入端,一个输出端。当所有的输入同时为高电平(逻辑1)时,输出才为高电平,否则输出为低电平(逻辑0)。

与门符号

与门真值表

与门真值表

VHDL 代码

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity AND_GATE is

Port ( A : in STD_LOGIC;

B : in STD_LOGIC;

C : out STD_LOGIC);

end AND_GATE;

architecture Behavioral of AND_GATE is

begin

C <= A AND B;

end Behavioral;

仿真波形图

与门仿真波形图

3,与非门是数字电路的一种基本逻辑电路。若当输入均为高电平,则输出为低电平;若输入中至少有一个为低电平,则输出为高电平。与非门是与门和非门的叠加。

与非门符号

与非门真值表

与非门真值表

VHDL 代码

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity NAND_GATE is

Port ( A : in STD_LOGIC;

B : in STD_LOGIC;

C : out STD_LOGIC);

end NAND_GATE;

architecture Behavioral of NAND_GATE is

begin

C <= A NAND B;

end Behavioral;

与非门仿真波形图

4,或门又称或电路、逻辑和电路。或门有多个输入端,一个输出端,只要输入中有一个为高电平时(逻辑“1”),输出就为高电平(逻辑“1”);只有当所有的输入全为低电平(逻辑“0”)时,输出才为低电平(逻辑“0”)。

或门符号

或门真值表

或门真值表

VHDL 代码

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity OR_GATE is

Port ( A : in STD_LOGIC;

B : in STD_LOGIC;

C : out STD_LOGIC);

end OR_GATE;

architecture Behavioral of OR_GATE is

begin

C <= A OR B;

end Behavioral;

或门仿真波形图

或门仿真波形图

5,或非门是数字逻辑电路中的基本元件,实现逻辑或非功能。有多个输入端,一个输出端,多输入或非门可由2输入或非门和反相器构成。只有当两个输入A和B为低电平时输出为高电平。

或非门符号

或非门真值表

或非门真值表

VHDL 代码

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity NOR_GATE is

Port ( A : in STD_LOGIC;

B : in STD_LOGIC;

C : out STD_LOGIC);

end NOR_GATE;

architecture Behavioral of NOR_GATE is

begin

C <= A NOR B;

end Behavioral;

或非门仿真波形图

或非门仿真波形图

6,异或门是数字逻辑中实现逻辑异或的逻辑门。有多个输入端、1个输出端。若两个输入的电平相异,则输出为高电平1;若两个输入的电平相同,则输出为低电平0。亦即,如果两个输入不同,则异或门输出高电平。

异或门符号

异或门真值表

异或门真值表

VHDL 代码

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity XOR_GATE is

Port ( A : in STD_LOGIC;

B : in STD_LOGIC;

C : out STD_LOGIC);

end XOR_GATE;

architecture Behavioral of XOR_GATE is

begin

C <= A XOR B;

end Behavioral;

异或门仿真波形图

异或门仿真波形图

7,同或门也称为异或非门,是数字逻辑电路的基本单元,有2个输入端、1个输出端。当2个输入端中有且只有一个是低电平时,输出为低电平。亦即当输入电平相同时,输出为高电平。

同或门符号

同或门真值表

同或门真值表

VHDL 代码

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity XNOR_GATE is

Port ( A : in STD_LOGIC;

B : in STD_LOGIC;

C : out STD_LOGIC);

end XNOR_GATE;

architecture Behavioral of XNOR_GATE is

begin

C <= A XNOR B;

end Behavioral;

同或门仿真波形图

同或门仿真波形图

System C的模块和过程

模块和过程

本节包含一个完整的简单设计,以演示SystemC中模块和过程的使用。为了简单起见,它是非常低的级别-而不是您通常期望的系统级别设计语言中的编码样式!

展示的要点是

建立阶层

所述sc_signal原始信道

(专用)端口

进程(SC_METHOD,SC_THREAD,SC_CTHREAD)

一个简单的测试台

SystemC背景

为什么要查看模块和流程?原因是SystemC旨在应付硬件和软件,并允许对大型系统进行建模。

进程是与其他进程同时运行的一小段代码。几乎所有已开发的高级系统级设计(SLD)工具都使用流程网络的基础模型。SystemC提供了支持独立(并行/并行)代码段网络构建的过程。

SLD需要处理大型设计。为了解决这个问题,通常使用层次结构。层次结构是通过使用模块在SystemC中实现的,该模块可以使用端口链接到其他模块。模块允许单独进行一项设计。模块可以包含进程和其他模块的实例。

实例设计

该设计包括一个EXOR门和四个NAND门。同样,必须注意,这不是典型的设计风格-很好理解。设计看起来像这样

第一步是对“与非”门建模。NAND门是组合电路;它的输出纯粹是输入值的函数。它没有内存,并且不需要时钟。因此,模型可以使用最简单的SystemC进程SC_METHOD。

SC_METHOD只是C ++函数。因此,SystemC类库必须使它们的行为像进程一样。尤其是

SystemC类库包含一个仿真内核,这是一段代码,用于模拟时间的流逝,并在函数的输入发生更改时调用函数以计算其输出。

该函数必须声明为SC_METHOD,并且对其输入敏感。

这是一个与非门的代码,位于一个文件nand.h中

#include“ systemc.h”SC_MODULE(nand2)//声明nand2 sc_module{

sc_in <布尔> A,B; //输入信号端口

sc_out <布尔> F; //输出信号端口

void do_nand2()//一个C ++函数

{

F.write(!(A.read()&& B.read()));

}

SC_CTOR(nand2)// nand2的构造函数

{

SC_METHOD(do_nand2); //向内核注册do_nand2

敏感<< A << B; //敏感度列表

}};

SystemC中的层次结构是使用类sc_module创建的。sc_module可以直接使用,也可以使用宏SC_MODULE “隐藏” 。上面的示例SC_MODULE创建了一个名为nand2的sc_module类对象。

接下来是声明的输入和输出端口。通常,使用类sc_port声明端口。例如,将声明 使用sc_signal的输入端口

sc_port <sc_signal_in_if <bool>,1> A,B;

但正如您所看到的,这是很多输入。为了方便起见,还可以创建和使用专用端口。sc_in是sc_signal类的专用端口的示例。

端口可以是任何C ++或SystemC类型-该示例使用内置的C ++类型bool。

接下来,声明完成工作的函数。输入和输出(专用)端口包括方法read()和write(),以允许读写端口。读取A和B,计算NAND函数,然后使用write()方法将结果写入F。

请注意,由于=运算符和类型转换运算符已被重载,因此您通常可以不使用read()和write()方法而逃脱。所以你可以写

F =!(A && B);

但是使用read()和write()是一个好习惯,因为它有助于C ++编译器消除表达式的歧义。

编写函数do_nand2()之后,将为sc_module实例nand2提供一个构造函数。SystemC使用宏SC_CTOR提供了一种简便的方法。构造函数执行以下操作

创建层次结构(在这种情况下为无)

将功能注册为模拟内核中的进程

声明流程的敏感度列表

也可以在此处初始化需要初始化的任何内容,例如,可以初始化类数据成员。

在上面的示例中,构造函数声明do_nand2是SC_METHOD,并说端口A和B上的任何事件都必须使内核运行该函数(从而为F计算一个新值)。

层次结构

EXOR门由NAND门的四个副本(或实例)组成。这是通过使用EXOR门构造器连接NAND门实例来实现的。这是EXOR门的代码

#include“ systemc.h”#include“ nand2.h”SC_MODULE(exor2){

sc_in <布尔> A,B;

sc_out <布尔> F;

nand2 n1,n2,n3,n4;

sc_signal <布尔> S1,S2,S3;

SC_CTOR(exor2):n1(“ N1”),n2(“ N2”),n3(“ N3”),n4(“ N4”)

{

n1.A(A);

n1.B(B);

n1.F(S1);

n2.A(A);

n2.B(S1);

n2.F(S2);

n3.A(S1);

n3.B(B);

n3.F(S3);

n4.A(S2);

n4.B(S3);

n4.F(F);

}};

该开始看起来与NAND门非常相似,但请注意,它包括文件nand2.h。这允许访问包含与非门的模块。

创建模块exor2,并声明端口。请注意,由于这是层次结构的不同级别,因此允许重复使用名称A,B 和F。

原始图显示了一些“线段”以连接NAND门。这些通过声明创建 sc_signal小号S1, S2和S3。 sc_signal是带有模板参数的类,该模板参数指定信号可以保存的数据类型- 在此示例中为bool。sc_signal是基本通道的一个示例,它是SystemC类库中的内置通道。它的行为类似于VHDL中的信号。

EXOR门的构造函数比NAND门的构造函数复杂,因为它必须具有nand2的四个实例。在端口声明之后,声明了nand2的四个实例:n1,n2,n3和n4。必须为每个实例赋予标签。通过使用exor2构造函数上的初始化器列表,将四个标签“ N1”,“ N2”,“ N3”和“ N4”传递给nand2实例的构造函数。

最后,将端口连接起来。如图所示,这是在构造函数中完成的。

试验台

为了测试设计,有一个激励发生器。这是另一个模块,与上面的非常相似。唯一重要的一点是,它使用线程(SC_THREAD),这是一种可以挂起的进程。这是stim.h的代码

#include“ systemc.h”SC_MODULE(刺激){

sc_out <bool> A,B;

sc_in <bool> Clk;

无效StimGen()

{

A.write(false);

B.write(false);

等待();

A.write(false);

B.write(true);

等待();

A.write(true);

B.write(false);

等待();

A.write(true);

B.write(true);

等待();

sc_stop();

}

SC_CTOR(刺激)

{

SC_THREAD(StimGen);

敏感<< Clk.pos();

}};

请注意对sc_stop()的最终调用,这将使模拟停止。监视代码看起来非常相似,因此被省略了-它位于mon.h文件中。

这是顶层-位于文件main.cpp中,该文件包含上述所有子模块

#include“ systemc.h”#include“ stim.h”#include“ exor2.h”#include“ mon.h”int sc_main(int argc,char * argv []){

sc_signal <bool> ASig,BSig,FSig;

sc_clock TestClk(“ TestClock”,10,SC_NS,0.5);

刺激Stim1(“ Stimulus”);

Stim1.A(ASig);

Stim1.B(BSig);

Stim1.Clk(TestClk);

exor2 DUT(“ exor2”);

DUT.A(ASig);

DUT.B(BSig);

DUT.F(FSig);

mon Monitor1(“ Monitor”);

Monitor1.A(ASig);

Monitor1.B(BSig);

Monitor1.F(FSig);

Monitor1.Clk(TestClk);

sc_start(); //永远运行

返回0;}

包含模块的头文件,声明进行连接的顶级信号以及使用sc_clock创建的时钟;然后每个模块都被实例化并连接。

此后,调用sc_start()将启动模拟,并且模拟将永久运行(或者直到遇到刺激模块中对sc_stop()的调用)。

这是此示例的输出

时间ABF

0秒0 0 1

10 ns 0 0 0

20 ns 0 1 1

30 ns 1 0 1

40 ns 1 1 0

如果您看一下,您会发现一些很奇怪的东西-时间0的第一行说F为1(真),而A和B为0-这不是一个非常有说服力的EXOR门!到10 ns时,一切都应达到预期。在时间0发生了什么事?

模拟

SystemC库包含一个仿真内核。这决定了要运行的进程(软件线程)。在时间0,所有SC_METHOD和SC_THREAD将以不确定的顺序运行,直到它们暂停。然后,当出现时钟沿时,SC_CTHREAD将运行。

上面的问题是由于多种情况造成的

所述sc_clock语句结果在上升沿在时间0,因此监视器和刺激的过程将运行(在未定义的顺序,它不知道其将第一运行)

C ++中的变量并不总是具有定义的初始值(除非将其声明为静态)。因此,F持有的数据值恰好是从1开始(真)

所述do_nand2 SC_METHOD运行在时间0,和时间表˚F更新,但˚F是一个信号,它不能立即更新,因此该值1是仍然存在的监视处理运行时。

为了证明是这种情况,可以修改sc_clock语句以延迟时钟的第一个边沿,如下所示

sc_clock TestClk(“ TestClock”,10,SC_NS,0.5,1,SC_NS);

最后的1个SC_NS参数指定在第一个时钟沿出现之前的1 ns延迟。现在时间已经过去,所以F将被更新。这是对应的输出

时间ABF

1 ns 0 0 0

11 ns 0 0 0

21 ns 0 1 1

31 ns 1 0 1

41 ns 1 1 0

现在您可以看到F总是正确的。

结论

总结了模块和流程的快速浏览。您已经了解了了解SystemC仿真内核的并发本质以及sc_signal基本通道的行为的重要性。

您还看到了一些在顶层模块中实例化底层模块的基本示例,以及如何使用sc_main。

相关问答

vhdl 中信号都能进行哪些运算?

VHDL提供了6种预定义的运算操作符,分别是:赋值运算符,逻辑运算符,算术运算符,关系运算符,移位运算符,并置运算符。VHDLl赋值运算符:在VHDL中,赋值运...如果...

 橡实啄木鸟  楠竹产地 
王经理: 180-0000-0000(微信同号)
10086@qq.com
北京海淀区西三旗街道国际大厦08A座
©2024  上海羊羽卓进出口贸易有限公司  版权所有.All Rights Reserved.  |  程序由Z-BlogPHP强力驱动
网站首页
电话咨询
微信号

QQ

在线咨询真诚为您提供专业解答服务

热线

188-0000-0000
专属服务热线

微信

二维码扫一扫微信交流
顶部