如何在VHDL中汇总STD_LOGIC_VECTOR?

时间:2017-07-13 14:42:38

标签: vhdl add

我正在尝试将8个ADC的样本值相加。将它们除以8并通过DAC返回结果。我做了一个案例陈述,让用户可以在总结整个或只输出一个频道之间做出选择。 我遇到的问题是结果是“闪烁”。它经常做它必须做的事情,但有时它给出了看起来更高的值。 个别频道似乎也比总和值差得多。我觉得它综合了两种不同的东西,用于求和和个别频道或其他东西。 我认为它可能与我如何总结向量有关,但我没有足够的经验来判断我所做的事情是否错误。 有没有人知道我做错了什么。

代码:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY sum IS
PORT(
	CLK_IN				:	IN  STD_LOGIC; -- 200MHz
	RESET				:	IN  STD_LOGIC;
	SUM_EN				:	IN  STD_LOGIC;
	SUM_VALID			: 	IN  STD_LOGIC;
	
	CHANNEL_IN_1		:	IN  STD_LOGIC_VECTOR( 7 DOWNTO 0 ) := (others => '0');
	CHANNEL_IN_2		:	IN  STD_LOGIC_VECTOR( 7 DOWNTO 0 ) := (others => '0');
	CHANNEL_IN_3		:	IN  STD_LOGIC_VECTOR( 7 DOWNTO 0 ) := (others => '0');
	CHANNEL_IN_4		:	IN  STD_LOGIC_VECTOR( 7 DOWNTO 0 ) := (others => '0');
	CHANNEL_IN_5		:	IN  STD_LOGIC_VECTOR( 7 DOWNTO 0 ) := (others => '0');
	CHANNEL_IN_6		:	IN  STD_LOGIC_VECTOR( 7 DOWNTO 0 ) := (others => '0');
	CHANNEL_IN_7		:	IN  STD_LOGIC_VECTOR( 7 DOWNTO 0 ) := (others => '0');
	CHANNEL_IN_8		:	IN  STD_LOGIC_VECTOR( 7 DOWNTO 0 ) := (others => '0');
		
	MODE_DATA			:	IN	std_logic_vector(3 DOWNTO 0);

	DATA_OUT			:	OUT STD_LOGIC_VECTOR( 7 DOWNTO 0 ) := x"80";
	SUM_READY			:	OUT STD_LOGIC := '0');
END sum;

ARCHITECTURE behaviour OF sum IS

-- input output registers
	SIGNAL r_sum_en			: 	STD_LOGIC := '0';
	SIGNAL r_sum_en_edge	: 	STD_LOGIC := '0';
	SIGNAL r_sum_valid		: 	STD_LOGIC := '0';
	SIGNAL r_sum_ready		: 	STD_LOGIC := '0';
	SIGNAL r_channel_in_1 	: 	STD_LOGIC_VECTOR( 7 DOWNTO 0 ) := (others => '0');
	SIGNAL r_channel_in_2 	: 	STD_LOGIC_VECTOR( 7 DOWNTO 0 ) := (others => '0');
	SIGNAL r_channel_in_3 	: 	STD_LOGIC_VECTOR( 7 DOWNTO 0 ) := (others => '0');
	SIGNAL r_channel_in_4 	: 	STD_LOGIC_VECTOR( 7 DOWNTO 0 ) := (others => '0');
	SIGNAL r_channel_in_5 	: 	STD_LOGIC_VECTOR( 7 DOWNTO 0 ) := (others => '0');
	SIGNAL r_channel_in_6 	: 	STD_LOGIC_VECTOR( 7 DOWNTO 0 ) := (others => '0');
	SIGNAL r_channel_in_7 	: 	STD_LOGIC_VECTOR( 7 DOWNTO 0 ) := (others => '0');
	SIGNAL r_channel_in_8 	: 	STD_LOGIC_VECTOR( 7 DOWNTO 0 ) := (others => '0');
	SIGNAL r_mode_data 		:	STD_LOGIC_VECTOR( 3 DOWNTO 0 ) := (others => '0');
	SIGNAL r_data_out 		:	STD_LOGIC_VECTOR( 7 DOWNTO 0 ) := x"80";

-- logic signals
	TYPE machine IS (idle, initialise, summing, waiting, averaging, delivering);
	SIGNAL state : machine;

BEGIN
	r_channel_in_1 	<= CHANNEL_IN_1 WHEN r_sum_en = '1' ELSE x"80";
	r_channel_in_2 	<= CHANNEL_IN_2 WHEN r_sum_en = '1' ELSE x"80";
	r_channel_in_3 	<= CHANNEL_IN_3 WHEN r_sum_en = '1' ELSE x"80";
	r_channel_in_4 	<= CHANNEL_IN_4 WHEN r_sum_en = '1' ELSE x"80";
	r_channel_in_5 	<= CHANNEL_IN_5 WHEN r_sum_en = '1' ELSE x"80";
	r_channel_in_6 	<= CHANNEL_IN_6 WHEN r_sum_en = '1' ELSE x"80";
	r_channel_in_7 	<= CHANNEL_IN_7 WHEN r_sum_en = '1' ELSE x"80";
	r_channel_in_8 	<= CHANNEL_IN_8 WHEN r_sum_en = '1' ELSE x"80";
	r_sum_en		<= SUM_EN;
	r_mode_data		<= MODE_DATA;
	r_sum_valid		<= SUM_VALID;
	DATA_OUT 		<= r_data_out;
	SUM_READY 		<= r_sum_ready;

	PROCESS (CLK_IN, RESET) IS
		VARIABLE average : STD_LOGIC_VECTOR(11 DOWNTO 0) := (others => '0');
		VARIABLE hold_channel_1 : STD_LOGIC_VECTOR(11 DOWNTO 0) := (others => '0');
		VARIABLE hold_channel_2 : STD_LOGIC_VECTOR(11 DOWNTO 0) := (others => '0');
		VARIABLE hold_channel_3 : STD_LOGIC_VECTOR(11 DOWNTO 0) := (others => '0');
		VARIABLE hold_channel_4 : STD_LOGIC_VECTOR(11 DOWNTO 0) := (others => '0');
		VARIABLE hold_channel_5 : STD_LOGIC_VECTOR(11 DOWNTO 0) := (others => '0');
		VARIABLE hold_channel_6 : STD_LOGIC_VECTOR(11 DOWNTO 0) := (others => '0');
		VARIABLE hold_channel_7 : STD_LOGIC_VECTOR(11 DOWNTO 0) := (others => '0');
		VARIABLE hold_channel_8 : STD_LOGIC_VECTOR(11 DOWNTO 0) := (others => '0');
	BEGIN
		IF RESET = '1' THEN
			r_sum_ready		<= '0';
			r_data_out 		<= x"80";
			hold_channel_1 := (others => '0');
			hold_channel_2 := (others => '0');
			hold_channel_3 := (others => '0');
			hold_channel_4 := (others => '0');
			hold_channel_5 := (others => '0');
			hold_channel_6 := (others => '0');
			hold_channel_7 := (others => '0');
			hold_channel_8 := (others => '0');

		ELSIF rising_edge(CLK_IN) THEN
			CASE state IS
				WHEN idle =>
					r_sum_en_edge <= r_sum_en;
					IF r_sum_en = '1' AND r_sum_en_edge = '0' THEN
						state <= initialise;
					ELSE state <= idle; END IF;
					r_sum_ready <= '0';
					r_sum_ready		<= '0';
					r_data_out 		<= x"80";
					hold_channel_1 := x"080";
					hold_channel_2 := x"080";
					hold_channel_3 := x"080";
					hold_channel_4 := x"080";
					hold_channel_5 := x"080";
					hold_channel_6 := x"080";
					hold_channel_7 := x"080";
					hold_channel_8 := x"080";
				WHEN initialise =>

					IF r_sum_valid = '1' THEN
						state <= summing;
						hold_channel_1(7 DOWNTO 0) := r_channel_in_1;
						hold_channel_2(7 DOWNTO 0) := r_channel_in_2;
						hold_channel_3(7 DOWNTO 0) := r_channel_in_3;
						hold_channel_4(7 DOWNTO 0) := r_channel_in_4;
						hold_channel_5(7 DOWNTO 0) := r_channel_in_5;
						hold_channel_6(7 DOWNTO 0) := r_channel_in_6;
						hold_channel_7(7 DOWNTO 0) := r_channel_in_7;
						hold_channel_8(7 DOWNTO 0) := r_channel_in_8;
					ELSE
						state <= initialise;
					END IF;
					r_sum_ready <= '0';
				WHEN summing =>
					CASE r_mode_data IS
						WHEN x"0" => average := hold_channel_1 + hold_channel_2 + hold_channel_3 + hold_channel_4 + hold_channel_5 + hold_channel_6 + hold_channel_7 + hold_channel_8 ;
						WHEN x"1" => average := hold_channel_1;
						WHEN x"2" => average := hold_channel_2;
						WHEN x"3" => average := hold_channel_3;
						WHEN x"4" => average := hold_channel_4;
						WHEN x"5" => average := hold_channel_5;
						WHEN x"6" => average := hold_channel_6;
						WHEN x"7" => average := hold_channel_7;
						WHEN x"8" => average := hold_channel_8;
						WHEN others => null;
					END CASE;
					state <= waiting;
					r_sum_ready <= '0';
				WHEN waiting =>
					state <= averaging;
					r_sum_ready <= '0';
				WHEN averaging =>
					CASE r_mode_data IS
						WHEN x"0" =>	r_data_out <= average (10 DOWNTO 3);
						WHEN others =>	r_data_out <= average (7 DOWNTO 0);
					END CASE;
					r_sum_ready <= '0';
					state <= delivering;
				WHEN delivering =>
					r_sum_ready <= '1';
					IF r_sum_en = '1' THEN
						state <= initialise;
					ELSE state <= idle; END IF;
				WHEN others =>
					state <= idle;
			END CASE;

		END IF;

	END PROCESS;
END ARCHITECTURE;

0 个答案:

没有答案