-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathgc_arbitrated_mux.vhd
145 lines (117 loc) · 4.41 KB
/
gc_arbitrated_mux.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
143
-------------------------------------------------------------------------------
-- Title : Multiplexer with round-robin arbitration
-- Project : General Cores Collection library
-------------------------------------------------------------------------------
-- File : gc_arbitrated_mux.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN
-- Created : 2011-08-24
-- Last update: 2020-09-18
-- Platform : FPGA-generic
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: An N-channel time-division multiplexer with round robin
-- arbitration.
-------------------------------------------------------------------------------
--
-- Copyright (c) 2011 CERN / BE-CO-HT
--
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 0.51 (the "License") (which enables you, at your option,
-- to treat this file as licensed under the Apache License 2.0); you may not
-- use this file except in compliance with the License. You may obtain a copy
-- of the License at http://solderpad.org/licenses/SHL-0.51.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2011-08-24 1.0 twlostow Created
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
entity gc_arbitrated_mux is
generic (
-- number of arbitrated inputs
g_num_inputs : integer;
-- data width
g_width : integer);
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
-- data (all inputs joined together)
d_i : in std_logic_vector(g_num_inputs * g_width-1 downto 0);
-- 1: data word on input N is valid. Can be asserted only if corresponding
-- d_req_o(N) == 1
d_valid_i : in std_logic_vector(g_num_inputs-1 downto 0);
-- 1: input N is ready to accept next data word
d_req_o : out std_logic_vector(g_num_inputs-1 downto 0);
-- Mux output
q_o : out std_logic_vector(g_width-1 downto 0);
-- 1: q_o contains valid data word
q_valid_o : out std_logic;
-- Index of the input, to which came the currently outputted data word.
q_input_id_o : out std_logic_vector(f_log2_ceil(g_num_inputs)-1 downto 0)
);
end gc_arbitrated_mux;
architecture rtl of gc_arbitrated_mux is
function f_onehot_decode
(x : std_logic_vector) return integer is
begin
for i in 0 to x'length-1 loop
if(x(i) = '1') then
return i;
end if;
end loop; -- i
return 0;
end f_onehot_decode;
type t_data_array is array(0 to g_num_inputs-1) of std_logic_vector(g_width-1 downto 0);
signal req_masked, req, grant : std_logic_vector(g_num_inputs-1 downto 0);
signal dregs : t_data_array;
begin -- rtl
gen_inputs : for i in 0 to g_num_inputs-1 generate
p_input_reg : process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
req(i) <= '0';
else
if(grant(i) = '1') then
req(i) <= '0';
elsif(d_valid_i(i) = '1') then
dregs(i) <= d_i(g_width * (i+1) - 1 downto g_width * i);
req(i) <= '1';
end if;
end if;
end if;
end process;
d_req_o(i) <= not req(i);
end generate gen_inputs;
req_masked <= req and not grant;
p_arbitrate : process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
q_valid_o <= '0';
grant <= (others => '0');
else
f_rr_arbitrate(req_masked , grant, grant);
if(unsigned(grant) /= 0) then
q_o <= dregs(f_onehot_decode(grant));
q_input_id_o <= std_logic_vector(to_unsigned(f_onehot_decode(grant), f_log2_ceil(g_num_inputs)));
q_valid_o <= '1';
else
q_o <= (others => 'X');
q_input_id_o <= (others => 'X');
q_valid_o <= '0';
end if;
end if;
end if;
end process;
end rtl;