《VHDL 数字电路设计教程》电工版/第9章:典型电路设计分析

《VHDL 数字电路设计教程》电工版/第9章:典型电路设计分析9.1桶形移位寄存器桶形移位寄存器的电路结构如下图所示。该电路包括3个独立的桶形移位器,左侧为第一级寄存器,只有1个‘0’连接到左下角的一个复用器上,第二级有2个‘0’,第三级有4个‘0’。对于位宽更高的矢量,将采用这种逐级加倍插入‘0’的方法来构造桶形移位寄存器。…

9.1    桶形移位寄存器

    桶形移位寄存器的电路结构如下图所示。该电路包括3个独立的桶形移位器,左侧为第一级寄存器,只有1个‘0’连接到左下角的一个复用器上,第二级有2个‘0’,第三级有4个‘0’。对于位宽更高的矢量,将采用这种逐级加倍插入‘0’的方法来构造桶形移位寄存器。

                                《VHDL 数字电路设计教程》电工版/第9章:典型电路设计分析

---------------------桶形移位寄存器------------------------
LIBRARY ieee;  
USE ieee.std_logic_1164.all;
-----------------------------------------------------------
ENTITY barrel IS
	PORT(
		inp	:	IN	STD_LOGIC_VECTOR(7 DOWNTO 0);
		shift	:	IN	STD_LOGIC_VECTOR(2 DOWNTO 0);		--移动的位数,用二进制数表示
		outp	:	OUT	STD_LOGIC_VECTOR(7 DOWNTO 0)
		); 
END	barrel; 
----------------------------------------------------------
ARCHITECTURE behavior OF barrel IS
BEGIN
	PROCESS(inp,shift)
		VARIABLE temp1	:	STD_LOGIC_VECTOR(7 DOWNTO 0);
		VARIABLE temp2	:	STD_LOGIC_VECTOR(7 DOWNTO 0);
	BEGIN
		----------------------1st shifter-----------------
		IF	(shift(0) = '0') THEN
			temp1 := inp;
		ELSE
			temp1(0) := '0';
			FOR	i IN 1 TO inp'HIGH LOOP
				temp1(i) := inp(i-1);
			END LOOP;
		END IF;
		----------------------2st shifter-----------------
		IF	(shift(1) = '0') THEN
			temp2 := temp1;
		ELSE
			FOR	i IN 0 TO 1 LOOP
				temp2(i) := '0';
			END LOOP;
			FOR	i IN 2 TO inp'HIGH LOOP
				temp2(i) := temp1(i-2);
			END LOOP;
		END IF;
		----------------------3st shifter----------------
		IF	(shift(2) = '0') THEN
			outp <= temp2;
		ELSE
			FOR	i IN 0 TO 3 LOOP
				outp(i) <= '0';
			END LOOP;
			FOR	i IN 4 TO inp'HIGH LOOP
				outp(i) <= temp2(i-4);
			END LOOP;
		END IF;
	END PROCESS;
END behavior;

9.2    逐级进位和超前进位加法器

    逐级进位加法器

  •     优点:需要较少的硬件资源
  •     缺点:完成一次计算所需的时延较大(原因:每个全加器的输出结果都依赖于前一级产生的进位)
  •     1位全加器FAU:a和b是输入位,cin是进位输入位,s是求和的结果,cout是进位输出位。当输入位有奇数个‘1’时,s必定是‘1’,而当有两个或更多的输入为‘1’时,cout必定是‘1’。逻辑表达式如下:
s=a XOR b XOR cin                        --a 异或 b:a和b不同时结果为1,反之为0
cout=(a AND b)OR(a AND cin)OR(b AND cin)

    下图给出了一个4位无符号的逐级进位加法器,对每一位都使用了全加器FAU,同时给出了1位全加器的真值表。

                     《VHDL 数字电路设计教程》电工版/第9章:典型电路设计分析

---------------------4位无符号数的逐级进位加法器------------------------
LIBRARY ieee;  
USE ieee.std_logic_1164.all;
-----------------------------------------------------------
ENTITY adder_cripple IS
	GENERIC(
		n  :   INTEGER	:=4
		);
	PORT(
		a		:	IN	STD_LOGIC_VECTOR(n-1 DOWNTO 0);
		b		:	IN	STD_LOGIC_VECTOR(n-1 DOWNTO 0);
		cin		:	IN	STD_LOGIC;		
		s		:	OUT	STD_LOGIC_VECTOR(n-1 DOWNTO 0);
		cout	        :	OUT	STD_LOGIC		
		); 
END	adder_cripple; 
----------------------------------------------------------
ARCHITECTURE adder OF adder_cripple IS
	SIGNAL c	:	STD_LOGIC_VECTOR(n DOWNTO 0);
BEGIN
	c(0) <= cin;
	G1:FOR i IN 0 TO n-1 GENERATE
	   s(i)	        <= 	a(i) XOR b(i) XOR c(i);
	   c(i+1)	<=	(a(i) AND b(i))	OR
				(a(i) AND c(i))	OR
				(b(i) AND c(i));
	END GENERATE;
	cout <= c(n);
END adder;
  •     注意:对于操作符中预定义的“+”操作符,加法器可以直接通过此操作符来实现,且此时综合工具一般会采用逐级进位加法器来实现目标电路。如果不希望采用这种方法,则必须在代码描述上清晰地体现出来。

    

    超前进位加法器

  •     优点:运行速度较快
  •     缺点:硬件的复杂程度增加
  •     运算原理:根据1位全加器的真值表有:

    ①\[{S_i} = \overline {
{A_i}} {B_i}\overline {
{C_i}}  +{A_i}\overline {
{B_i}}  \cdot \overline {
{C_i}}  + \overline {
{A_i}} \cdot \overline {
{B_i}} {C_i} + {A_i}{B_i}{C_i} = \left( {
{A_i} \oplus{B_i}} \right)\overline {
{C_i}}  + \overline {\left( {
{A_i} \oplus {B_i}}\right)} {C_i} = {A_i} \oplus {B_i} \oplus {C_i}\]

    ②\[{C_{i + 1}} = {A_i}{B_i}\overline {
{C_i}}  + {A_i}{B_i}{C_i} + \overline {
{A_i}} {B_i}{C_i} + {A_i}\overline {
{B_i}} {C_i} = {A_i}{B_i} + \left( {
{A_i} \oplus {B_i}} \right){C_i}\]

        此时令:进位产生信号(generate)\[{G_i} = {A_i} *{B_i}\],进位传递信号(propagate)\[{P_i} = {A_i}\oplus {B_i}\],则有\[{C_{i + 1}} ={G_i} + {P_i} * {C_i}\]

    另外,4位超前进位加法器的电路结构图如下所示:

                                《VHDL 数字电路设计教程》电工版/第9章:典型电路设计分析

    现在假设有两个输入矢量:a=a(n-1)a(n-2)…a(1)a(0)和b=b(n-1)b(n-2)…b(1)b(0),那么相应的generate矢量为g=g(n-1)g(n-2)…g(1)g(0),相应的propagate矢量为p=p(n-1)p(n-2)…p(1)p(0)。其中

    g(j) = a(j) AND b(j)

    p(j) = a(j) XOR b(j)

    现在假设进位矢量c=c(n)c(n-1)c(n-2)…c(1)c(0)且\[{C_{i + 1}} ={C_i} * {P_i} + {G_i}\], 即有:    

    c(0) = cin

    c(1) = c(0)p(0)+g(0)

    c(2) = c(1)p(1)+g(1) = (c(0)p(0)+g(0))p(1)+g(1) = c(0)p(0)p(1)+g(0)p(1)+g(1)

    c(3) = c(2)p(2)+g(2) = (c(0)p(0)p(1)+g(0)p(1)+g(1))p(2)+g(2) = c(0)p(0)p(1)p(2)+g(0)p(1)p(2)+g(1)p(2)+g(2)

    c(4) = c(3)p(3)+g(3) = (c(0)p(0)p(1)p(2)+g(0)p(1)p(2)+g(1)p(2)+g(2))p(3)+g(3) 

                                   = c(0)p(0)p(1)p(2)p(3)+g(0)p(1)p(2)p(3)+g(1)p(2)p(3)+g(2)p(3)+g(3),等等。

    注意:上面的表达式没有一个取决于前级进位输出的计算结果,这是超前进位加法器电路执行速度快的根本原因。另一方面,这种方式会使硬件电路的复杂程度增加,所以只能用于实现位数不是很多的加法器(如4位),位宽更高的超前进位加法器就需要将上述小规模电路组合起来了。 

    4位超前进位加法器:  

-----------------------------------------------------------
LIBRARY	ieee;
USE	ieee.std_logic_1164.all;
-----------------------------------------------------------
ENTITY CLA_Adder IS
	PORT(	a:		IN	STD_LOGIC_VECTOR(3 DOWNTO 0);
			b:		IN	STD_LOGIC_VECTOR(3 DOWNTO 0);
			cin:	IN	STD_LOGIC;
			s:		OUT	STD_LOGIC_VECTOR(3 DOWNTO 0);
			cout:	OUT	STD_LOGIC
		);
END CLA_Adder;
-----------------------------------------------------------
ARCHITECTURE CLA_Adder OF CLA_Adder IS
	SIGNAL c: STD_LOGIC_VECTOR(4 DOWNTO 0);
	SIGNAL p: STD_LOGIC_VECTOR(3 DOWNTO 0);
	SIGNAL g: STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
	---------------------PGU:------------------------------
	G1:	FOR i IN 0 TO 3 GENERATE
		p(i) <= a(i) XOR b(i);			--异或
		g(i) <= a(i) AND b(i);		
		s(i) <= p(i) XOR c(i);
	END GENERATE;
	---------------------CLAU:-----------------------------
	c(0) <= cin;
	c(1) <= (cin AND p(0)) OR
			g(0);
	c(2) <= (cin AND p(0) AND p(1)) OR
			(g(0) AND p(1)) OR
			g(1);
	c(3) <= (cin AND p(0) AND p(1) AND p(2)) OR
			(g(0) AND p(1) AND p(2)) OR
			(g(1) AND p(2)) OR
			g(2);
	c(4) <= (cin AND p(0) AND p(1) AND p(2) AND p(3)) OR
			(g(0) AND p(1) AND p(2) AND p(3)) OR
			(g(1) AND p(2) AND p(3)) OR
			(g(2) AND p(3)) OR
			g(3);
	cout <= c(4);
END	CLA_Adder;
-----------------------------------------------------------

9.3    定点除法

    注意:预定义运算符“/”只能进行2^n类型的除法运算,其运算本质实际上就是移位操作

    除法电路的算法

    假设要计算 y=a/b,其中a>b ,且a是 位二进制数。假设:a=“1011”,b=“0011”(这里左边可补0可不补0),改除法运算的结果是y=“0011”和余数“0010”.该除法算法如下表:  

除法算法
索引i 与a相关的输入a_inp(i) 比较 与b相关的输入b_inp(i) 商y(i) 操作
3 1011 < 0011000 0 none
2 1011 < 0001100 0 none
1 1011 > 0000110 1 a_inp(0)=a_inp(1)-b_inp(1)
0 0101 > 0000011 1 rem=a_inp(0)-b_inp(0)
0010(rem

    对于除法运算有:

    ①i 的范围为 (n-1 downto 0);

     ②b_inp(i) 为b 左移 i 位,低位补零;

     ③与a相关的输入中,a_inp(n-1) = a,另有

                                                            《VHDL 数字电路设计教程》电工版/第9章:典型电路设计分析

     其中余数 rem=a_inp(-1) 且遵循上述等式;

    ④商

《VHDL 数字电路设计教程》电工版/第9章:典型电路设计分析

    VHDL除法器:

-----------------------------------------------------------
library	ieee;
use	ieee.std_logic_1164.all;
-----------------------------------------------------------
entity	divider is
	generic(n: integer	:=	4);
	port(
		a:		in 	integer range 0 to 15;
		b:		in 	integer range 0 to 15;
		y:		out	std_logic_vector( n-1 downto 0 );
		rest:	out	integer	range 0 to 15;
		err:	out	std_logic
		);
end	divider;
-----------------------------------------------------------
architecture rtl of divider is
begin
	process	(a,b)								--“process”中为顺序描述
		variable temp1:	integer	range 0	to 15;
		variable temp2:	integer	range 0	to 15;
	begin
		--------------Error and initialization-------------
		temp1	:=	a;
		temp2	:=	b;
		if	(b = 0)	then
			err	<=	'1';
		else
			err	<=	'0';
		end	if;
		-------------------------y:------------------------
		for i in n-1 downto 0 loop
			if	(temp1	>=	temp2*2**i)	then
				y(i)	<=	'1';
				temp1	:=	temp2*2**i;
			else
				y(i)	<=	'0';
			end	if;
		end	loop;
		----------------------Remainder--------------------
		rest	<=	temp1;
	end process;
end	rtl;

9.4    串行数据接收器

    串行数据接收器如下图所示,包括时钟信号(clk)、复位信号(rst)、串行数据输入端口(din)和并行数据输出端口(data),以及产生了两个指示信号:err(错误指示信号)和data_valid(有效数据指示信号)。

《VHDL 数字电路设计教程》电工版/第9章:典型电路设计分析

    输入信号是一个字符流。每个完整的字符包含10位,第1位是起始位,当其为高时标志一个字符的开始,电路开始接受后面的数据。

  •     判断方法:reg(0)=‘1’。

    接下来的7位是有效数据,第9位是奇偶校验位,当数据中1的个数是偶数时其值应该为‘0’,奇数时则为‘1’

  •     判断方法:

    统计有效数据的奇偶位数 temp0 = reg(1) XOR reg(2) XOR reg(3) XOR reg(4) XOR reg(5) XOR reg(6) XOR reg(7)
    上式中异或 XOR的作用:不同(奇数)为‘1’相同(偶数)为‘0’
    奇偶位数与奇偶校验位比较 temp1 = temp0 XOR reg(8)
    上式中异或 XOR的作用:不同为‘1’(错误)相同为‘0’(正确)

    第10位是终止位,如果传输正确,其值应该为‘1’,且当接收电路发现奇偶校验错误或结束位不是‘1’时将发出错误指示。

  •     判断方法:temp2 = temp1 OR ( NOT reg(9) ),表示“有‘1’为‘1’”。

    当数据接收正确时,存储在内部寄存器中的数据并行输出data,同时data_valid有效。

-----------------------------------------------------------
library	ieee;
use	ieee.std_logic_1164.all;
-----------------------------------------------------------
entity	receiver is
	port(
		clk:		in	bit;
		rst:		in	bit;
		din:		in	bit;
		data:		out	bit_vector(6 downto 0);
		err:		out	bit;
		data_vaild:	out	bit
		);
end	receiver;
-----------------------------------------------------------
architecture rtl of receiver is
begin
	process(clk,rst)
		variable count:	integer range 0 to 10;
		variable reg:	bit_vector(9 downto 0);
		variable temp:	bit;
	begin
		if	rst = '0' then
			count		:=	0;
			reg		:=	(reg'range => '0');
			-- reg		    :=	(others => '0');
			-- reg		    :=	"0000000000";
			temp		:=	'0';
			err		<=	'0';
			data_vaild	<=	'0';
		elsif clk'event and clk = '1'	then
			if	(reg(0) = '0' and din = '1') then
				reg(0) := '1';
			elsif reg(0) = '1' then
				count := count+1;
				if	count<10 then
					reg(count) := din;
				elsif count=10 then
					temp 	:=	(reg(1) xor reg(2) xor reg(3) xor	--优先级:not>or>xor
							reg(4) xor reg(5) xor reg(6) xor
							reg(7) xor reg(8)) or not reg(9);
					err	<=	temp;
					count	:=	0;
					reg(0)	:=	din;
					if	temp = '0' then
						data <= reg(7 downto 1);	--在没有新的有效数据输入之前,输出数据始终保持为原来的值。
						data_vaild <= '1';		--在第一次有效数据输入后,数据有效指示信号变为高,后面一直为高。
					end	if;
				end	if;
			end	if;
		end	if;
	end	process;
end	rtl;

9.5    并/串变换器

    并/串变换器是一个使用移位寄存器的典型例子,作用是将并行的数据块以串联的方式连续输出。

    转换器的电路结构如下图所示。当load有效时,并行输入数据d(7:0)被同步储存在移位寄存器中,且当load保持为高时,MSB即d(7)在输出端始终保持有效。一旦load返回‘0’,接下来移位寄存器的各个位将在每个时钟上升沿依次出现在输出端口dout上,8位数据全部发送完毕后,输出端在下一次数据传输之前一直保持低电平。

    《VHDL 数字电路设计教程》电工版/第9章:典型电路设计分析

---------------------------------------------------------
library	ieee;
use	ieee.std_logic_1164.all;
---------------------------------------------------------
entity	serial_converter is
	port(
		clk:	in	std_logic;
		load:	in	std_logic;
		d:	in	std_logic_vector(7 downto 0);
		dout:	out	std_logic
		);
end	serial_converter;
---------------------------------------------------------
architecture serial_converter of serial_converter is
	signal	reg:	std_logic_vector(7 downto 0);
begin
	process(clk,load)
	begin
		if	clk'event and clk = '1' then
			if	load = '1' then
				reg <= d;
			else
				reg <= reg(6 downto 0)&'0';
			end	if;
		end if;
	end	process;
	dout <= reg(7);
end	serial_converter;
---------------------------------------------------------

9.6    一个7段显示器的应用例题

    利用SSD(seven-segment display,7段显示器)来设计一个小游戏,其中电路的顶层结构如下图所示,包括两个输入信号(clk和stop)和一个输出信号(dout(6:0)),输出信号连接到SSD上且分别对应着a~g。

《VHDL 数字电路设计教程》电工版/第9章:典型电路设计分析

    所设计的电路要求如下:SSD的各个段(除去g段)连续地按照顺时针方向转动,为了使循环运动的视觉效应更连贯,相邻两端在点亮的时间上略微重叠。因此,点亮的次序应该是a-ab-b-bc-c-cd-d-de-e-ef-f-fa-a,其中系统在a、b、c等状态停留时间time1较长,在ab、bc、cd等状态停留时间time2较短。另外,如果stop为‘1’,则电路返回状态a,并在stop变低之前一直保持。状态图如下:

《VHDL 数字电路设计教程》电工版/第9章:典型电路设计分析

--------------------------------------------------------------
library	ieee;
use	ieee.std_logic_1164.all;
--------------------------------------------------------------
entity	ssd_game2	is
	port(
		clk:	in	bit;
		stop:	in	bit;
		dout:	out	bit_vector(6 downto 0)
		);
end	ssd_game2;
--------------------------------------------------------------
architecture	fsm	of	ssd_game2	is
	constant	time1:	integer	:=	4;
	constant	time2:	integer	:=	2;
	type	states	is	(a,ab,b,bc,c,cd,d,de,e,ef,f,fa);
	signal	present_state,	next_state:	states;
	signal	count:	integer	range	0	to	time1;
	signal	flip:	bit;				--通过该信号来指出计数器该计数到time1还是time2
begin
	-------------------Lower section of FSM-------------------
	process(clk,stop)
	begin
		if	stop = '1'	then
			present_state <= a;
		elsif	clk'event and clk = '1'	then
			if	(flip = '1' and count = time1)	or
				(flip = '0' and count = time2)	then	--根据不同的计数器确定不同状态保持的时长
				count <= 0;
				present_state <= next_state;
			else
				count <= count+1;
			end if;
		end	if;
	end	process;
	-------------------Upper section of FSM-------------------
	process(present_state)
	begin
		case	present_state	is
			when	a	=>
				dout <= "1000000";		--LSB即g段始终为'0',不亮
				flip <= '1';
				next_state <= ab;
			when	ab	=>
				dout <= "1100000";
				flip <= '0';
				next_state <= b;
			when	b	=>
				dout <= "0100000";
				flip <= '1';
				next_state <= bc;
			when	bc	=>
				dout <= "0110000";
				flip <= '0';
				next_state <= c;
			when	c	=>
				dout <= "0010000";
				flip <= '1';
				next_state <= cd;
			when	cd	=>
				dout <= "0011000";
				flip <= '0';
				next_state <= d;
			when	d	=>
				dout <= "0001000";
				flip <= '1';
				next_state <= de;
			when	de	=>
				dout <= "0001100";
				flip <= '0';
				next_state <= e;
			when	e	=>
				dout <= "0000100";
				flip <= '1';
				next_state <= ef;
			when	ef	=>
				dout <= "0000110";
				flip <= '0';
				next_state <= f;
			when	f	=>
				dout <= "0000010";
				flip <= '1';
				next_state <= fa;
			when	fa	=>
				dout <= "1000010";
				flip <= '0';
				next_state <= a;
		end	case;
	end	process;
end	fsm;

9.7    信号发生器

    要求如下图所示:

《VHDL 数字电路设计教程》电工版/第9章:典型电路设计分析

    实现该电路需要4个寄存器,其中3个用于计数器,另外1个用于波形输出。

    采用FSM进行设计    

----------------------------------------------------------------------
library	ieee;
use	ieee.std_logic_1164.all;
----------------------------------------------------------------------
entity	signal_gen	is
	port(
		clk:	in	std_logic;
		wave:	out	std_logic
		);
end	signal_gen;
----------------------------------------------------------------------
architecture	fsm	of	signal_gen	is
	type	states	is	(zero,	one,	two,	three,	four,	five,
						six,	seven);
	signal	present_state,	next_state:	states;
	signal	temp:	std_logic;
begin
	---------------------Lower section of FSM:------------------------
	process(clk)
	begin
		if	clk'event	and	clk	=	'1'	then
			present_state	<=	next_state;
			wave	<=	temp;				--采用状态机设计风格#2,在上升沿将寄存器的值输出,
		end	if;						--因为在信号发生器中不允许出现毛刺。
	end	process;
	---------------------Upper section of FSM:------------------------
	process(present_state)
	begin
		case	present_state	is
			when	zero	=>
				temp	<=	'0';
				next_state	<=	one;
			when	one	=>
				temp	<=	'1';
				next_state	<=	two;
			when	two	=>
				temp	<=	'0';
				next_state	<=	three;
			when	three	=>
				temp	<=	'1';
				next_state	<=	four;
			when	four	=>
				temp	<=	'1';
				next_state	<=	five;
			when	five	=>
				temp	<=	'1';
				next_state	<=	six;
			when	six	=>
				temp	<=	'0';
				next_state	<=	seven;
			when	seven	=>
				temp	<=	'0';
				next_state	<=	zero;
		end	case;
	end	process;
end	fsm;
------------------------------------------------------------------------

    采用传统方法进行设计

-----------------------------------------------------------------------------------------
library	ieee;
use	ieee.std_logic_1164.all;
-----------------------------------------------------------------------------------------
entity	signal_gen1	is
	port(
		clk:	in	std_logic;
		wave:	out	std_logic
		);
end	signal_gen1;
------------------------------------------------------------------------------------------
architecture	arch1	of	signal_gen1	is
begin
	process
		variable	count:	integer	range	0	to	7;
	begin
		wait	until	clk'event	and	clk	=	'1';
		case	count	is
			when	0	=>	wave	<=	'0';
			when	1	=>	wave	<=	'1';
			when	2	=>	wave	<=	'0';
			when	3	=>	wave	<=	'1';
			when	4	=>	wave	<=	'1';
			when	5	=>	wave	<=	'1';
			when	6	=>	wave	<=	'0';
			when	7	=>	wave	<=	'0';
		end	case;
		count	:=	count	+	1;
	end	process;
end	arch1;
--------------------------------------------------------------------------------------------
--由于在使用wait until语句时,process没有敏感信号列表,所以其必须是process中的第一条语句;
--wait until语句后面只有一个信号条件表达式,更适合用于实现同步电路;
--当wait until语句的条件满足时,process内部的代码就执行一遍。
--------------------------------------------------------------------------------------------

9.10    存储器设计

    ROM只读存储器

    ROM的原型结构图如下:

《VHDL 数字电路设计教程》电工版/第9章:典型电路设计分析

    因为它是只读存储器,所以不需要时钟和写使能信号,且电路内部包括预先储存的内容,并且由输入的地址(addr)来选择将哪个存储空间中的内容传送给输出端。

    实现该ROM时,由于没有使用时钟信号,所以没有占用寄存器资源。ROM是通过使用逻辑门构成查找表(LUT: Look Up Table)的方式来实现的。

-------------------------------------------------------------------
library	ieee;
use	ieee.std_logic_1164.all;
-------------------------------------------------------------------
entity	rom	is
	generic(
		bits:	integer	:=	8;			--# of bits per word
		words:	integer	:=	8			--# of words in the memory
		);
	port(
		addr:	in	integer	range	0	to	words-1;
		data:	out	std_logic_vector(bits-1	downto	0)
		);
end	rom;
-------------------------------------------------------------------
architecture	rom	of	rom	is
	type	vector_array	is	array	(0	to	words-1)	of
		std_logic_vector	(bits-1	downto	0);
	constant	memory:	vector_array	:=	("00000000",
							"00000010",
							"00000100",
							"00001000",
							"00010000",
							"00100000",
							"01000000",
							"10000000");
begin
	data	<=	memory(addr);
end	rom;
-------------------------------------------------------------------

    输入/输出数据总线分离的RAM

    具有独立输入/输出数据总线的RAM(随机存储器)的结构如下:

《VHDL 数字电路设计教程》电工版/第9章:典型电路设计分析

    如果写使能信号(wr_ena)有效,在一个时钟上升沿出现时,data_in上的数据将被存储到地址总线(addr)所选择的位置上。另外,data_out上始终显示当前地址总线(addr)所选择的存储单元中的内容。

----------------------------------------------------------------
library	ieee;
use	ieee.std_logic_1164.all;
----------------------------------------------------------------
entity	ram	is
	generic(
		bits:	integer	:=	8;			--	#每字的字宽
		words:	integer	:=	16			--	#储存器中的字数
		);
	port(
		clk:		in	std_logic;
		wr_ena:		in	std_logic;
		addr:		in	integer	range	0	to	words-1;
		data_in:	in	std_logic_vector(bits-1	downto	0);
		data_out:	out	std_logic_vector(bits-1	downto	0)
		);
end	ram;
----------------------------------------------------------------
architecture	ram	of	ram	is
	type	vector_array	is	array	(0	to	words-1)	of
		std_logic_vector	(bits-1	downto	0);
	signal	memory:	vector_array;
begin
	process(clk,wr_ena)
	begin
		if	wr_ena	=	'1'	then
			if	clk'event	and	clk	=	'1'	then
				memory(addr)	<=	data_in;
			end	if;
		end	if;
	end	process;
	data_out	<=	memory(addr);
end ram;
-----------------------------------------------------------------

    具有双向I/O数据总线的RAM

    总体结构如下图所示:

《VHDL 数字电路设计教程》电工版/第9章:典型电路设计分析

    工作原理:当wr_ena为低时,寄存器的输出与它的输入相连,同时总线处于数据输出状态,相应地址选择的数据被输出到总线上。当wr_ena有效时,数据总线上的数据直接与d连接,在下一个始终周期的上升沿到达时,数据被写入到寄存器中。

----------------------------------------------------------------
library	ieee;
use	ieee.std_logic_1164.all;
----------------------------------------------------------------
entity	ram4	is
	generic(
		bits:	integer	:=	8;			--	#每字的字宽
		words:	integer	:=	16			--	#储存器中的字数
		);
	port(
		clk:	in	std_logic;
		wr_ena:	in	std_logic;
		addr:	in	integer	range	0	to	words-1;
		bidir:	inout	std_logic_vector(bits-1	downto	0)
		);
end	ram4;
----------------------------------------------------------------
architecture	ram	of	ram4	is
	type	vector_array	is	array	(0	to	words-1)	of
		std_logic_vector	(bits-1	downto	0);
	signal	memory:	vector_array;
begin
	process(clk,wr_ena)
	begin
		if	wr_ena	=	'0'	then
			bidir	<=	memory(addr);
		else
			-- bidir	<=	(others => 'z');
			if	clk'event	and	clk	=	'1'	then
				memory(addr)	<=	bidir;
			end	if;
		end	if;
	end	process;	
end ram;
-----------------------------------------------------------------

今天的文章《VHDL 数字电路设计教程》电工版/第9章:典型电路设计分析分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/12937.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注