eFEX firmware  1.7.3
ATLAS l1-calo - electron and tau feature extraction firmware for eFEX boards

Back to eFEX documentation
ipbus_spi32.vhd
Go to the documentation of this file.
1 
6 
7 
8 library IEEE;
9 use IEEE.std_logic_1164.all;
10 use IEEE.std_logic_arith.all;
11 use IEEE.std_logic_unsigned.all;
12 library ipbus_lib;
13 use ipbus_lib.ipbus.all;
14 use work.spi.all;
15 use ipbus_lib.ipbus_reg_types.all;
17 entity ipbus_spi32 is
18  generic(
19  BYTE_SPI: boolean := FALSE;
20  -- SPI i/o granularity. Default is 32bits for PLL. Set TRUE for FLASH.
21  ADDR_WIDTH: natural
22  -- = Width of whole interface. Includes control reg, input and output RAM.
23  );
24 port (
26  ipbus_clk: in std_logic;
28  reset: in std_logic;
30  ipb_in: in ipb_wbus;
32  ipb_out: out ipb_rbus;
34  spi_in : in spi_mi;
36  spi_out : out spi_mo;
38  selreg : out std_logic_vector(1 downto 0)
39  );
40 
41 attribute keep_hierarchy : string;
42 attribute keep_hierarchy of ipbus_spi32 : entity is "yes";
43 
44 end ipbus_spi32 ;
46 
47 architecture rtl of ipbus_spi32 is
48 
49 
50 signal ram_ptr : std_logic_vector(ADDR_WIDTH - 3 downto 0);-- An index for both in and out ram
51 signal ram_write: std_logic;
52 
53 signal outgoing_data, incoming_data: std_logic_vector(31 downto 0);
54 
55 constant DIV_BITS: natural := 2;
56 
57 signal spi_clk: std_logic := '0';
58 signal clk_en: std_logic := '0';
59 
60 constant NSLV: positive := 4;
61 signal ipbw: ipb_wbus_array(NSLV-1 downto 0);
62 signal ipbr, ipbr_d: ipb_rbus_array(NSLV-1 downto 0);
63 
64 signal spi_ctrl: ipb_reg_v(3 downto 0);
65 signal spi_stat: ipb_reg_v(0 downto 0);
66 
67 
68 signal transfer_count : std_logic_vector( ADDR_WIDTH downto 0);
69  -- = number of bytes if BYTE_SPI=TRUE else = number of 32-bit words
70 
71 signal do_spi,run_spi,busy : std_logic;
72 
73 
74 --attribute PRESERVE_SIGNAL : boolean;
75 --attribute PRESERVE_SIGNAL of spi_clk: signal is true;
76 
77 begin
78 
79 block_decode: entity ipbus_lib.ipbus_fabric_branch
80  generic map(
81  NSLV => NSLV,
82  DECODE_BASE => ADDR_WIDTH -2
83  )
84  port map(
85  ipb_in => ipb_in,
86  ipb_out => ipb_out,
87  ipb_to_slaves => ipbw,
88  ipb_from_slaves => ipbr
89  );
90 
91 clock_div: process(reset, ipbus_clk)
92  variable div : std_logic_vector(DIV_BITS downto 1);
93  begin
94  if reset = '1' then
95  div:=(others => '0');
96  elsif rising_edge(ipbus_clk) then
97  spi_clk <= div(DIV_BITS);
98  div:=div+1;
99  end if;
100  end process;
101 
102 
103 spi_control: entity ipbus_lib.ipbus_ctrlreg_v
104  generic map(
105  N_CTRL => 4,
106  N_STAT => 1
107  )
108  port map(
109  clk => ipbus_clk,
110  reset => reset,
111  ipbus_in => ipbw(0),
112  ipbus_out => ipbr(0),
113  d => spi_stat,
114  q => spi_ctrl
115  );
116 
117  selreg <= spi_ctrl(0)(1 downto 0); -- base address + 0
118  transfer_count <= spi_ctrl(2)((ADDR_WIDTH ) downto 0); -- 2
119  do_spi <= spi_ctrl(3)(0); -- 3
120 
121  spi_stat(0) <= X"0000000" & "000" & busy; -- 4
122 
123 
124 -- arbitration register with key, lock and watchdog timer
125 arbitration: entity work.ipbus_watchdog
126  generic map(
127  TIMER_WIDTH => 20
128  )
129  port map(
130  ipbus_clk => ipbus_clk,
131  reset => reset,
132  ipbus_in => ipbw(1),
133  ipbus_out => ipbr(1)
134  );
135 
136 
137 -- dpram shares address space with control, arbitration and the other dpram, hence the '-2' width
138 spi_dpram_out: entity work.ipbus_dpram_flash -- to SPI
139  generic map(
140  ADDR_WIDTH => ADDR_WIDTH -2
141  )
142  port map(
143  clk => ipbus_clk,
144  rst => reset,
145  ipb_in => ipbw(2),
146  ipb_out => ipbr(2),
147  rclk => spi_clk,
148  we => '0',--ram_write,
149  d => (others => '0'),--incoming_data,
150  q => outgoing_data,
151  addr => ram_ptr--pointer_addr
152  );
153 
154 spi_dpram_in: entity work.ipbus_dpram_flash -- from SPI
155  generic map(
156  ADDR_WIDTH => ADDR_WIDTH -2
157  )
158  port map(
159  clk => ipbus_clk,
160  rst => reset,
161  ipb_in => ipbw(3),
162  ipb_out => ipbr(3),
163  rclk => spi_clk,
164  we => ram_write,
165  d => incoming_data,
166  q => open,--outgoing_data,
167  addr => ram_ptr--pointer_addr
168  );
169 
170 synch: entity work.command_sync
171  port map (
172  ipb_clk => ipbus_clk,
173  out_clk => spi_clk,
174  reset => reset,
175  req => do_spi, -- on 0 to 1 transition
176  ack => busy,
177  kick => run_spi -- active until busy arrives
178  );
179 
180 spi_engine: entity work.spi32_8_control
181  generic map(
182  ADDR_WIDTH => ADDR_WIDTH -1,
183  BYTE_SPI => BYTE_SPI
184  )
185  port map (
186  spi_clk => spi_clk,
187  reset => reset,
188  outgoing_data => outgoing_data,
189  incoming_data => incoming_data,
190  run_spi => run_spi,
191  busy => busy,
192  transfer_count => transfer_count,
193  ram_ptr => ram_ptr,
194  ram_write => ram_write,-- grab data returning from slave
195  cs_n => spi_out.le,
196  clk_en => clk_en,
197  mosi => spi_out.mosi,
198  miso => spi_in.miso
199  );
200 
201 -- A clean version of clko <= clk_en and spi_clk;
202 gen_clock: ENTITY work.clock_pulse
203  PORT map(
204  CLK_I => spi_clk ,
205  RESET => reset,
206  Enable => clk_en,
207  pulse => spi_out.clk
208  );
209 
210 -- incoming block located directly after outgoing block. ram_write used as pointer msb
211 -- pointer_addr <= ram_write & ram_ptr;
212 
213 end rtl;
214 
clcock pulse
Definition: clock_pulse.vhd:12
out pulse std_logic
pulse created from the enable siganl
Definition: clock_pulse.vhd:22
in Enable std_logic
enable
Definition: clock_pulse.vhd:19
in RESET std_logic
reset
Definition: clock_pulse.vhd:17
in CLK_I std_logic
clock in
Definition: clock_pulse.vhd:15
commond synchronisation
in reset std_logic
reset
in ack std_logic
ack
in req std_logic
positive edge sensitive
in out_clk std_logic
derived from ipb_clk and slower
out kick std_logic := '0'
kick downstream state machine
in ipb_clk std_logic
IPBus clock of 31.25MHz.
ipbus dpram flash
in clk std_logic
write clock
in addr std_logic_vector( ADDR_WIDTH- 1 downto 0)
address
out ipb_out ipb_rbus
IPBus output bus going from slaves to master.
in rclk std_logic
read clock
in we std_logic := '0'
write enable
in ipb_in ipb_wbus
IPBus input bus going from master to slaves.
in rst std_logic
reset
in d std_logic_vector( 31 downto 0) :=( others => '0')
data in
out q std_logic_vector( 31 downto 0)
data out
ipbus_spi32
Definition: ipbus_spi32.vhd:47
ipbus_spi32
Definition: ipbus_spi32.vhd:17
in reset std_logic
reset
Definition: ipbus_spi32.vhd:28
in spi_in spi_mi
spi input signals
Definition: ipbus_spi32.vhd:34
out selreg std_logic_vector( 1 downto 0)
select output
Definition: ipbus_spi32.vhd:39
out ipb_out ipb_rbus
IPBus output bus going from slaves to master.
Definition: ipbus_spi32.vhd:32
out spi_out spi_mo
spi output signals
Definition: ipbus_spi32.vhd:36
in ipb_in ipb_wbus
IPBus input bus going from master to slaves.
Definition: ipbus_spi32.vhd:30
in ipbus_clk std_logic
ipbus clk of 31.25MHz
Definition: ipbus_spi32.vhd:26
ipbus watchdog
in ipbus_clk STD_LOGIC
IPBus clock of 31.25MHz.
out ipbus_out ipb_rbus
IPBus output bus going from slaves to master.
in reset STD_LOGIC
reset
in ipbus_in ipb_wbus
IPBus input bus going from master to slaves.
icontroller for SPI interface PLL chips of FTM /eFEX
in reset std_logic
reset
out cs_n std_logic := '1'
chip select of the spi flssh
out incoming_data std_logic_vector( 31 downto 0)
data from the spi flash
out busy std_logic := '0'
busy
in outgoing_data std_logic_vector( 31 downto 0)
data going to the spi flash
in run_spi std_logic
run spi controller
in transfer_count std_logic_vector( ADDR_WIDTH+ 1 downto 0)
data transfer count
out clk_en std_logic := '0'
clock enable
out mosi std_logic := '0'
mosi to spi flash
in miso std_logic := '0'
miso from spi flash
out ram_write std_logic := '0'
write enable of the ram
in spi_clk std_logic
spi clock
out ram_ptr std_logic_vector( ADDR_WIDTH- 2 downto 0)
ram pointer