and 6.1.
-- This VHDL code describes the Crossbar interconnect network -- and shared memory organization with
-- only one interface, on processor side.
-- Equivalent Block diagram for module 'top' is shown in Figure 7.1 -- Equivalent Block diagram for module 'main' is shown in Figure 6.1 library IEEE ; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; entity top is port (clk: in std_logic ; rst: in std_logic ; scnr: in std_logic_vector(2 downto 0) ; pid: in std_logic_vector(2 downto 0) ; data: out std_logic_vector(3 downto 0) ; addr: out std_logic_vector(3 downto 0) ); end top ;
architecture test_top of top is component main is
port (ctrl: in std_logic_vector(3 downto 0) ; qdep: in std_logic_vector(15 downto 0) ; addr_bus: in std_logic_vector(15 downto 0) ; data_in : in std_logic_vector(15 downto 0) ; rw: in std_logic_vector(3 downto 0) ; clk: in std_logic ;
rst: in std_logic ;
flag: inout std_logic_vector(3 downto 0) ; data_out: out std_logic_vector(15 downto 0) ); end component main ;
signal ctrl: std_logic_vector(3 downto 0) ; signal flag: std_logic_vector(3 downto 0) ;
signal qdep: std_logic_vector(15 downto 0) ; signal addr_bus: std_logic_vector(15 downto 0) ; signal data_in: std_logic_vector(15 downto 0) ; signal data_out: std_logic_vector(15 downto 0) ; signal rw: std_logic_vector(3 downto 0) ; begin
stim_gen: process (scnr) is begin
-- This is equivalent to Stimulus generator in the figure 7.1 -- All these scenarios are discussed in Chapter 6
case scnr (2 downto 0) is when "000" =>
-- all processors write to memory locations in different memory blocks data_in <= x"4321" ; addr_bus <= x"FB73" ; qdep <= x"1234" ; ctrl <= x"F" ; rw <= x"F" ; when "001" =>
-- all processors read from memory locations in different memory blocks -- in the reverse order
data_in <= x"26FE" ; addr_bus <= x"37BF" ; qdep <= x"1234" ; ctrl <= x"F" ; rw <= x"0" ; when "010" =>
-- processors 2 (write) and 3 (read) to different memory locations in the same memory block
-- processor 2 gets priority as its qdepth is greater
-- processors 0 (write) and 1 (read) to different memory locations in the same memory block
-- processor 1 gets priority as its processor id is greater data_in <= x"AAAA" ; addr_bus <= x"CD56" ; qdep <= x"EFFF" ; ctrl <= x"F" ; rw <= x"5" ; when "011" =>
-- processors 2 (write) and 3 (read) to different memory locations in the same memory block
-- processor 3 gets priority as its processor id is greater
-- processors 0 (write) and 1 (read) to different memory locations in the same memory block
-- processor 0 gets priority as its qdepth is greater data_in <= x"5555" ; addr_bus <= x"DC65" ; qdep <= x"4434" ; ctrl <= x"F" ; rw <= x"5" ; when "100" =>
data_in <= x"9999" ; -- processors 2 (write) and 3 (write) to same memory location addr_bus <= x"3399" ; -- processor 2 gets priority as its qdepth is greater
qdep <= x"4EE4" ; -- processors 0 (read) and 1 (read) from same memory location ctrl <= x"F" ; -- processor 1 gets priority as its qdepth is greater
rw <= x"C" ;
when "101" => -- processors 0 (write), 1 (read), 2 (read) and 3 (read) to different memory locations in the same memory block
data_in <= x"EEEE" ; -- processor 0 gets priority as its qdepth is greater addr_bus <= x"7654" ;
qdep <= x"5556" ; ctrl <= x"F" ; rw <= x"1" ;
when "110" => -- processors 1 (read), 2 (read) and 3 (read) to same memory location (proc 0 is idle)
data_in <= x"CCCC" ; -- processor 3 gets priority as its processor id is greater addr_bus <= x"6666" ;
qdep <= x"5555" ; ctrl <= x"E" ; rw <= x"0" ;
when others => -- all processors in idle state data_in <= x"FFFF" ; -- flag is ‘0000’ addr_bus <= x"EEAE" ; qdep <= x"0011" ; ctrl <= x"0" ; rw <= x"0" ; end case ;
INST: main port map (clk => clk, rst => rst, data_in => data_in, qdep => qdep, addr_bus => addr_bus,
rw => rw, ctrl => ctrl, flag => flag, data_out => data_out );
-- This is equivalent to 'display' block in figure 7.1 disply: process (ctrl,scnr,pid) is
begin
case pid (2 downto 0) is when "000" =>
data <= qdep(3 downto 0) ; addr(0) <= ctrl(0) ; addr(1) <= rw(0) ; addr(2) <= flag(0) ; addr(3) <= flag(0) ; when "001" => if (rw(0) = '0') then
data <= data_out(3 downto 0) ; else
data <= data_in(3 downto 0) ; end if ;
addr <= addr_bus(3 downto 0) ; when "010" =>
data <= qdep(7 downto 4) ; addr(0) <= ctrl(1) ; addr(1) <= rw(1) ; addr(2) <= flag(1) ; addr(3) <= flag(1) ; when "011" => if (rw(1) = '0') then
data <= data_out(7 downto 4) ; else
data <= data_in(7 downto 4) ; end if ;
addr <= addr_bus(7 downto 4) ; when "100" =>
data <= qdep(11 downto 8) ; addr(0) <= ctrl(2) ;
addr(1) <= rw(2) ; addr(2) <= flag(2) ;
addr(3) <= flag(2) ; when "101" => if (rw(2) = '0') then
data <= data_out(11 downto 8) ; else
data <= data_in(11 downto 8) ; end if ;
addr <= addr_bus(11 downto 8) ; when "110" =>
data <= qdep(15 downto 12) ; addr(0) <= ctrl(3) ; addr(1) <= rw(3) ; addr(2) <= flag(3) ; addr(3) <= flag(3) ; when others => if (rw(3) = '0') then
data <= data_out(15 downto 12) ; else
data <= data_in(15 downto 12) ; end if ;
addr <= addr_bus(15 downto 12) ; end case ;
end process disply ;
end architecture test_top ;
-- The main interconnect module library IEEE;
use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; entity main is
port (ctrl: in std_logic_vector(3 downto 0) ; qdep: in std_logic_vector(15 downto 0) ; addr_bus: in std_logic_vector(15 downto 0) ; data_in: in std_logic_vector(15 downto 0) ; rw: in std_logic_vector(3 downto 0) ; clk: in std_logic ;
rst: in std_logic ;
data_out: out std_logic_vector(15 downto 0) ); end main ;
architecture main_arch of main is
type qd is array (3 downto 0) of std_logic_vector(3 downto 0) ;
type data_array is array (3 downto 0) of std_logic_vector(3 downto 0) ; type addr_array is array (3 downto 0) of std_logic_vector(3 downto 0) ; type mb is array (3 downto 0) of std_logic_vector(1 downto 0) ;
type mem_array is array (15 downto 0) of std_logic_vector(3 downto 0) ;
-- This function does the priority logic for all the memory blocks -- This is schemactically equivalent to Figures 4.5 and 4.6 in the report -- This can work for any number of processors and memory blocks -- by changing 'i' and 'j' values
function flg (qdep, addr_bus, ctrl:std_logic_vector ) return std_logic_vector is
variable qdvar: std_logic_vector (3 downto 0) ; variable flag: std_logic_vector(3 downto 0) ; variable qdv : std_logic_vector(3 downto 0) ; variable gnt : std_logic ; variable a: integer ; variable b: integer ; variable memaddr : mb ; variable qd_arr : qd ; begin
qd_arr(0) := qdep(3 downto 0) ; qd_arr(1) := qdep(7 downto 4) ; qd_arr(2) := qdep(11 downto 8) ; qd_arr(3) := qdep(15 downto 12) ; memaddr(0) := addr_bus(3 downto 2) ; memaddr(1) := addr_bus(7 downto 6) ; memaddr(2) := addr_bus(11 downto 10) ; memaddr(3) := addr_bus(15 downto 14) ; L1: for i in 0 to 3 loop
L2: for j in 0 to 3 loop
if (ctrl(j) = '0') then flag(j) := '0' ;
qdv(j) := '0' ;
elsif (memaddr(j) = i) then qdv(j) := '1' ; else qdv(j) := '0' ; end if ; end loop L2 ; qdvar := "0000" ; gnt := '0' ; L3: for k in 0 to 3 loop if qdv(k) = '1' then
if qdvar <= qd_arr(k) then qdvar := qd_arr(k) ; a := k ; gnt := '1' ; else flag(k) := '0' ; end if; end if ; end loop L3 ; if (gnt = '1') then flag(a) := '1' ; end if ; end loop L1 ; return (flag) ; end flg;
signal memory: mem_array ; begin
P1 : process(ctrl, clk, qdep, addr_bus, rst, data_in) is begin
if (rst = '1') then flag <= "0000" ; else
-- Memory transaction
-- The conditional statements make sure that the connection is established -- before memory transaction
-- Equivalent to Figures 4.4 and 4.1 after the completion of priority logic operation. -- This routine is to be repeated for each addition of processor
if (clk 'event and clk = '0') then if (flag(0) = '1') then
if (rw(0) = '1') then
memory(conv_integer(addr_bus(3 downto 0))) <= data_in(3 downto 0) ; data_out(3 downto 0) <= (others => 'Z') ;
else
data_out(3 downto 0) <= memory(conv_integer(addr_bus(3 downto 0))) ; end if ;
end if ;
if (flag(1) = '1') then if (rw(1) = '1') then
memory(conv_integer(addr_bus(7 downto 4))) <= data_in(7 downto 4) ; data_out(7 downto 4) <= (others => 'Z') ;
else
data_out(7 downto 4) <= memory(conv_integer(addr_bus(7 downto 4))) ; end if ;
end if ;
if (flag(2) = '1') then if (rw(2) = '1') then
memory(conv_integer(addr_bus(11 downto 8))) <= data_in(11 downto 8) ; data_out(11 downto 8) <= (others => 'Z') ;
else
data_out(11 downto 8) <= memory(conv_integer(addr_bus(11 downto 8))) ; end if ;
end if ;
if (flag(3) = '1') then if (rw(3) = '1') then
memory(conv_integer(addr_bus(15 downto 12))) <= data_in(15 downto 12) ; data_out(15 downto 12) <= (others => 'Z') ;
else
; end if ; end if ; end if; end if; end process P1 ; end main_arch ;