-
Notifications
You must be signed in to change notification settings - Fork 3
/
mixer2.vhd
143 lines (128 loc) · 3.45 KB
/
mixer2.vhd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 00:03:11 08/06/2014
-- Design Name:
-- Module Name: mixer2 - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity mixer2 is Port (
clk : in STD_LOGIC;
rst : in STD_LOGIC;
A_in: in signed(21 downto 0);
A_valid: in std_logic;
A_mute: in std_logic;
B_in: in signed(21 downto 0);
B_valid: in std_logic;
B_mute: in std_logic;
mix_out: out signed(21 downto 0);
mix_valid: out std_logic
); end mixer2;
architecture Behavioral of mixer2 is
type state_type is (state_idle, state_a, state_b, state_limit);
type reg_type is record
state: state_type;
accumulator: signed(22 downto 0);
mix: signed(21 downto 0);
valid: std_logic;
end record;
constant reg_reset: reg_type := (
state => state_idle,
accumulator => to_signed(0, 23),
mix => to_signed(0, 22),
valid => '0'
);
constant accumulator_high: signed(22 downto 0) := to_signed(2097151, 23); -- +2^21-1
constant mix_high: signed(21 downto 0) := to_signed(2097151, 22);
constant accumulator_low: signed(22 downto 0) := to_signed(-2097152, 23); -- -2^21
constant mix_low: signed(21 downto 0) := to_signed(-2097152, 22);
signal reg: reg_type := reg_reset;
signal ci_next: reg_type;
begin
COMB: process(reg, rst, A_in, A_valid, B_in, B_valid, A_mute, B_mute)
variable ci: reg_type;
variable A_mask: signed(22 downto 0);
variable B_mask: signed(22 downto 0);
begin
ci := reg;
-- self-clearing
ci.valid := '0';
if(A_mute = '1') then
A_mask := to_signed(0, 23);
else
A_mask := signed(A_in(21) & A_in);
end if;
if(B_mute = '1') then
B_mask := to_signed(0, 23);
else
B_mask := signed(B_in(21) & B_in);
end if;
if(rst = '1') then
ci := reg_reset;
else
case reg.state is
when state_idle =>
if(A_valid = '1' and B_valid = '1') then
ci.accumulator := A_mask + B_mask;
ci.state := state_limit;
elsif(A_valid = '1' and B_valid = '0') then
ci.accumulator := A_mask;
ci.state := state_b;
elsif(A_valid = '0' and B_valid = '1') then
ci.accumulator := B_mask;
ci.state := state_a;
end if;
when state_a =>
if(A_valid = '1') then
ci.accumulator := reg.accumulator + A_mask;
ci.state := state_limit;
end if;
when state_b =>
if(B_valid = '1') then
ci.accumulator := reg.accumulator + B_mask;
ci.state := state_limit;
end if;
when state_limit =>
-- check accumulator and clamp to a 22-bit value in mix
if(reg.accumulator > accumulator_high) then
ci.mix := mix_high;
elsif(reg.accumulator < accumulator_low) then
ci.mix := mix_low;
else
ci.mix := signed(reg.accumulator(22) & reg.accumulator(20 downto 0));
end if;
ci.valid := '1';
ci.state := state_idle;
when others => null;
end case;
end if;
ci_next <= ci;
end process COMB;
SEQ: process(clk, ci_next)
begin
if(rising_edge(clk)) then
reg <= ci_next;
end if;
end process SEQ;
-- output
mix_out <= reg.mix;
mix_valid <= reg.valid;
end Behavioral;