OpenCores
URL https://opencores.org/ocsvn/log_anal/log_anal/trunk

Subversion Repositories log_anal

[/] [log_anal/] [tags/] [v1_0/] [rtl/] [log_anal.vhd] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jamro
-- logic analyser (LA) for FPGAs
2
-- ver 1.0
3
-- Author: Ernest Jamro
4
 
5
--//////////////////////////////////////////////////////////////////////
6
--//// Copyright (C) 2001 Authors and OPENCORES.ORG                 ////
7
--////                                                              ////
8
--//// This source file may be used and distributed without         ////
9
--/// restriction provided that this copyright statement is not    ////
10
--//// removed from the file and that any derivative work contains  ////
11
--//// the original copyright notice and the associated disclaimer. ////
12
--////                                                              ////
13
--//// This source file is free software; you can redistribute it   ////
14
--//// and/or modify it under the terms of the GNU Lesser General   ////
15
--//// Public License as published by the Free Software Foundation; ////
16
--//// either version 2.1 of the License, or (at your option) any   ////
17
--//// later version.                                               ////
18
--////                                                              ////
19
--//// This source is distributed in the hope that it will be       ////
20
--//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
21
--//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
22
--//// PURPOSE. See the GNU Lesser General Public License for more  ////
23
--//// details.                                                     ////
24
--////                                                              ////
25
--//// You should have received a copy of the GNU Lesser General    ////
26
--//// Public License along with this source; if not, download it   ////
27
--//// from <http://www.opencores.org/lgpl.shtml>                   ////
28
 
29
 
30
------------------------------------------------------------------------------------
31
------------------------------------------------------------------------------------
32
-- logic analyser (LA) - probes signals states every rising clk, before/after the triger sequence
33
 
34
library IEEE;
35
use IEEE.std_logic_1164.all;
36
use IEEE.std_logic_unsigned.all;
37
 
38
 
39
entity log_anal is
40
  generic(data_width: integer:= 16; -- width of the data that are analysed (must be power of 2)
41
      mem_adr_width: integer:= 9; -- internal memory address width
42
          adr_width: integer:= 11; -- adr_I address width
43
      trig_width: integer:= 8; -- width of the triger logic
44
          two_clocks: integer:= 0); -- two seperate clocks for control interface and logic analyser
45
  -- the following rules must!!! be satysfied for generic:
46
  -- data_width= 8, 16 or  32
47
  -- adr_width= mem_adr_width + 1 + log2(data_width/8); 4<=mem_adr_width<=16
48
  -- mem_adr_width<=16
49
  -- trig_width<= 32
50
  -- two_clocks= 0 (only wb_clk_I clock is used) 1- f_clk= k*f_wb_clk_I, 2- two asynchronous clocks
51
 
52
  -- mem_adr_width optimal selection for 4kb BRAM (Virtex): 
53
  --  mem_adr_width<= 9 then number of BRAM block used= data_width/8
54
 
55
  port (arst: in std_logic; -- global asynchronous set reset signal (mainly for simulation purposes)
56
          -- interface for logic analyser 
57
          clk: in std_logic; -- seperate clock for logic analyzer (the same as wb_clk_I when two_clocks= 0)
58
          data: in std_logic_vector(data_width-1 downto 0); -- data that are analysied
59
          ce_data: in std_logic; -- clock enable -- should be used if data are recorded e.g. every second la_clk
60
      trig: in std_logic_vector(trig_width-1 downto 0); -- triger bus (can be different that data bus
61
          ce_trig: in std_logic; -- clock enable for triger bus
62
          -- control WISHBOBE slave interface - interface for setting logic analyser options and transfering analysed data to computer
63
      wb_clk_I: in STD_LOGIC; -- clock (common for every logic every logic analyser signals) - common for loagic analyser and WISHBONE control interface
64
          wb_adr_I: in std_logic_vector(adr_width-1 downto 0); -- address bus (one bit wider than mem_adr_width)
65
          wb_dat_I: in std_logic_vector(7 downto 0);
66
          wb_dat_O: out std_logic_vector(7 downto 0);
67
          wb_stb_I, wb_we_I: in std_logic;
68
          -- wb_cyc_I: in std_logic; -- signal is ignored
69
          -- wb_rst_I: in std_logic; -- the WISHBONE interface need not be reseted
70
          wb_ack_O: buffer std_logic);
71
end log_anal;
72
 
73
architecture LA of log_anal is
74
 -- TECHNOLOGY DEPENDENT MEMORY
75
 component la_mem
76
  generic ( data_width: integer:= 8; -- width of the data (la interface)
77
    mem_adr_width: integer:= 9; -- width of the address (address width cannot be greater than max_address width (for data_width=1)
78
        c_adr_width: integer:= 9; -- control interface address width = adr_width + log2(data_width/8)
79
        two_clocks: integer:= 0 -- one or two seperate clocks are used
80
        );
81
  port (arst: in std_logic; -- asynchronous reset (mainly for simulation purposes
82
    -- first port interface (for control and data read)
83
        c_clk: in std_logic; -- clock
84
        c_do: out std_logic_vector(7 downto 0); -- control interface signals
85
        c_adr: in std_logic_vector(c_adr_width-1 downto 0);
86
    -- second port for logic analyser data write
87
        la_clk: in std_logic; -- clock (ignored when two_clocks=0)
88
        la_we: in std_logic; -- write enable
89
    la_di: in std_logic_vector(data_width-1 downto 0);
90
        la_adr: in std_logic_vector(mem_adr_width-1 downto 0));
91
  end component;
92
 
93
  component la_trigger
94
        generic (trig_width: integer); -- width of the trig data 1<=trig_width<=32
95
        port (clk, arst: in std_logic;
96
        -- LA interface
97
        trig_data: in std_logic_vector(trig_width-1 downto 0); -- data that are alasysed for triger
98
        trig_now: out std_logic; -- triger data is now presented on the trig_data bus
99
        -- Control interface (to set and read triger values)
100
        wr: in std_logic; -- when 1 writes din to triger configuration registers
101
        adr: in std_logic_vector(3 downto 0);
102
        dout: out std_logic_vector(7 downto 0);
103
        din: in std_logic_vector(7 downto 0) );
104
  end component;
105
 
106
  signal ackR: std_logic; -- ack_O for (mainly for memory access)
107
  signal data_q: std_logic_vector(data_width-1 downto 0); -- flip-flop to allow better routing of the data bus (the LA less influences Place&Route program)
108
  signal trig_q: std_logic_vector(trig_width-1 downto 0); -- similar like data_q but for triger
109
  signal ce_data_q: std_logic; -- flip-flop for clock enable signal
110
  -- control signals
111
  signal run: std_logic; -- LA is now acquiring new data (after triger has been found)
112
  signal status_reg: std_logic_vector(7 downto 0); -- status register that will be read 
113
  signal trig_now: std_logic; -- proper triger is now presented at the trig input
114
  signal trig_wr: std_logic; -- write to the triger configuration register
115
  signal trig_datR: std_logic_vector(7 downto 0); -- read data form configuration register
116
  signal wr_trig_counter: std_logic; -- a write to trig counter is done by the control interface
117
  signal mem_we: std_logic; -- memory write enable
118
  -- signals read/written by control interace
119
  signal wb_reg_wr, wb_reg_wr_q: std_logic; -- wishbone writes to an internal control register (clock sinchronisation is considered)
120
  signal reg_do, reg_do_q: std_logic_vector(7 downto 0); -- internal registers data out (according to the wb_adr_I
121
  signal mem_do: std_logic_vector(7 downto 0); -- memory output data
122
  signal counter: std_logic_vector(mem_adr_width-1 downto 0); -- counter which runs continuosly untill the LA finishes data acquisition
123
  -- this counter point to the current data write possition, should be read to show the start (end) point for data reading
124
  signal counter_rd: std_logic_vector(15 downto 0); -- like counter but MSBs are fill with zeros
125
  signal trig_counter: std_logic_vector(mem_adr_width downto 0); -- counter which shows how much 
126
  -- data is still to be acquired, "10000..0"- full, "00..0"-empty
127
  -- this counter can be written to point the triger position: "100..0" - do not triger
128
  -- "011..1"- triger at the end, "00..0"- triger at the beginning, "0100..0"- triger at the half, "0XXXXX" - somewhere between
129
  signal trig_counter_down: std_logic_vector(mem_adr_width downto 0); -- this counter checkes that
130
    -- the proper number of data before the triger have been already recorded
131
    -- this counter is especially importent when triger is at the end of the recorded data
132
        -- therefore the data before the triger has to be written just before the triger (not a random data from the previous record)
133
  type sel_type is (s_mem_data, s_status_reg, s_counter, s_triger, s_none); -- which device is selected
134
  signal sel_dev: sel_type;
135
begin
136
-----------------------------------------------------------
137
-- clock synchronisation region
138
        -- la_clk and stb_i_q selection
139
  clk_g0: if two_clocks=0 generate
140
          reg_do_q<= reg_do;
141
          wb_reg_wr<= wb_we_i and wb_stb_i;
142
          wb_ack_O<= wb_stb_i and ackR;
143
    end generate;
144
 
145
  clk_g1: if two_clocks>0 generate
146
          -- wb_reg_wr flip-flop
147
          process(clk, arst) begin
148
                if arst='1' then wb_reg_wr<= '0';
149
                elsif clk'event and clk='1' then
150
                  if wb_we_i='1' and -- write
151
                         ackR='1' and -- wait for one whole wb_clk_I cycle
152
                         wb_reg_wr='0' and wb_reg_wr_q='0' then-- wb_reg_wr is active only for one clk cycle
153
                            wb_reg_wr<= '1';
154
                  else
155
                            wb_reg_wr<= '0';
156
                  end if;
157
                end if;
158
          end process;
159
 
160
          -- wb_reg_wr_q flip-flop
161
          process(clk, arst, ackR) begin
162
                if arst='1' or ackR='0' then -- ackR='0' if stb_i=0 or in the previous wb_clk a data transfer took place
163
                        wb_reg_wr_q<= '0';
164
                elsif clk'event and clk='1' then
165
                   if wb_reg_wr='1' then
166
                         wb_reg_wr_q<= '1'; -- wait for asynchronous reset
167
                   end if;
168
                end if;
169
          end process;
170
          -- reg_do_q flip-flops
171
          process(wb_clk_I, arst) begin
172
                 if arst='1' then reg_do_q<="00000000";
173
                 elsif wb_clk_i='1' and wb_clk_i'event then
174
                         reg_do_q<= reg_do;
175
                 end if;
176
          end process;
177
 
178
 
179
        wb_ack_O<= wb_stb_i and ackR when wb_we_i='0'   -- for control register read and memory read
180
          else wb_stb_i and wb_reg_wr_q; -- for control register write
181
 
182
  end generate; -- two_clocks>1
183
 
184
--------------------------------------------------------------
185
-- logic analyzer data region 
186
  -- data flip-flops
187
  process(arst, clk) begin
188
        if arst='1' then data_q<= (others=>'0');
189
        elsif clk'event and clk='1' then
190
          data_q<= data;
191
        end if;
192
  end process;
193
  -- triger flip-flops
194
  process(arst, clk) begin
195
        if arst='1' then trig_q<= (others=> '0');
196
        elsif clk'event and clk='1' then
197
          if ce_trig='1' then
198
                trig_q<= trig;
199
          end if;
200
        end if;
201
  end process;
202
  -- clock enable for data
203
  process(arst, clk) begin
204
        if arst='1' then ce_data_q<= '0';
205
        elsif clk'event and clk='1' then
206
                ce_data_q<= ce_data;
207
        end if;
208
  end process;
209
  -- counter (increased every clk when analysed data are writen to memory)
210
  process(arst, clk) begin
211
        if arst='1' then counter<= (others=>'0');
212
        elsif clk'event and clk='1' then
213
          if trig_counter(mem_adr_width)='0' and ce_data_q='1' then -- when data acquisition has not been finished
214
                 counter<= counter + 1;
215
          end if;
216
        end if;
217
  end process;
218
 
219
  -- trig_counter (shows how many analysed data are still to be recorded) recording stops if the counter is overflowed
220
  process(arst, clk) begin
221
        if arst='1' then trig_counter<= (others=>'0');
222
        elsif clk'event and clk='1' then
223
      if wr_trig_counter='1' then
224
                  if mem_adr_width>=6 then
225
                    trig_counter(mem_adr_width downto mem_adr_width-6)<= wb_dat_i(6 downto 0); -- write only 7 MSBs of the trig_counter 
226
                    trig_counter(mem_adr_width-7 downto 0)<= (others=> '0');
227
                  else
228
                        trig_counter<= wb_dat_i(6 downto 6-mem_adr_width);
229
                  end if;
230
          elsif run='1' and ce_data_q='1' then -- acquisition is not finished
231
                  trig_counter<= trig_counter + 1;
232
          end if;
233
        end if;
234
  end process;
235
  -- trig counter down - triger is enable when a proper number of data before triger has been recorded
236
  process(arst, clk) begin
237
        if arst='1' then trig_counter_down<= (others=>'0');
238
        elsif clk'event and clk='1' then
239
          if wr_trig_counter='1' then
240
                  if mem_adr_width>=6 then
241
                    trig_counter_down(mem_adr_width downto mem_adr_width-6)<= wb_dat_i(6 downto 0); -- write only 7 MSBs of the trig_counter 
242
                    trig_counter_down(mem_adr_width-7 downto 0)<= (others=> '0');
243
                  else --mem_adr_width< 6
244
                        trig_counter_down<= wb_dat_i(6 downto 6-mem_adr_width);
245
                  end if;
246
          elsif trig_counter_down(mem_adr_width)='0' and ce_data_q='1' then -- not enought data has been written to the memory before the triger
247
                  trig_counter_down<= trig_counter_down - 1;
248
          end if;
249
        end if;
250
  end process;
251
  -- run logic
252
  process(arst, clk) begin
253
        if arst='1' then run<='0';
254
        elsif clk'event and clk='1' then
255
          if wr_trig_counter='1' then
256
                  run<= wb_dat_i(7); -- remember that if datW(7)=1 then datW(6 downto 0) should be "00..0"
257
          elsif trig_counter(mem_adr_width)='1' then
258
                  run<= '0'; -- whole memory have been written
259
          elsif trig_now='1' and trig_counter_down(mem_adr_width)='1' then -- activate run only if proper number of data has been recorded before the triger
260
                  run<= '1';
261
          end if;
262
        end if;
263
  end process;
264
  wr_trig_counter<= '1' when sel_dev = s_status_reg and wb_reg_wr='1' else '0';
265
 
266
 
267
  ----- triger logic
268
  trigger: la_trigger
269
        generic map (trig_width=>trig_width)
270
        port map (clk=>clk, arst=> arst, trig_data=> trig_q, trig_now=> trig_now,
271
        -- Control interface (to set and read triger values)
272
        wr=> trig_wr, adr=> wb_adr_I(3 downto 0), dout=> trig_datR, din=> wb_dat_I);
273
 
274
  trig_wr<= '1' when wb_reg_wr='1' and sel_dev=s_triger else '0';
275
 
276
 
277
  -- addrss space
278
  -- 0-1FF - main LA memory (for a single BRAM 4kb)
279
  -- 200 control registers based address
280
  -- 200 - status (b7=run, b6= finish, b5-b0 - triger start, 111111- at the end, 000001- at the beginning
281
  -- 204 - stop counter - points where the last recorded data is in the LA main memory
282
  -- 208-20B - trigger value (0- triger when 0, 1- triger when the trig data is 1)
283
  -- 20C-20F - trigger consider (0- do not care about the input (X), 1- consider the input bit)
284
 
285
  sel_dev<= s_mem_data when wb_adr_I(adr_width-1)='0' else -- data memory
286
      s_triger when wb_adr_I(3)='1' else
287
          s_counter when wb_adr_I(2 downto 1)= "10" else
288
      s_status_reg when wb_adr_I(2 downto 0)= "000" else
289
          s_none;
290
 
291
 
292
  mem_we<= ce_data_q and not trig_counter(mem_adr_width); -- when valid data and not whole buffer written
293
  -- memory block
294
  mem:  la_mem
295
  generic map (data_width=> data_width, mem_adr_width=> mem_adr_width,
296
      c_adr_width=> adr_width-1, two_clocks=> two_clocks)
297
        port map (arst=> arst, c_clk=> wb_clk_I, c_do=> mem_do,
298
           c_adr=> wb_adr_I(adr_width-2 downto 0),
299
      -- second port for logic analyser data write
300
          la_clk=> clk, la_we=> mem_we, la_di=> data_q, la_adr=> counter);
301
 
302
  -- read registers
303
  counter_rd(mem_adr_width-1 downto 0)<= counter;
304
  gc15: if mem_adr_width<=15 generate -- fill MSB of counter width 0s
305
          counter_rd(15 downto mem_adr_width)<= (others=> '0');
306
  end generate;
307
  -- status register
308
  gs8: if mem_adr_width>=6 generate
309
    status_reg<= run & trig_counter(mem_adr_width downto mem_adr_width-6);
310
  end generate;
311
  gs7: if mem_adr_width<= 5 generate
312
        status_reg(7 downto 6-mem_adr_width)<= run & trig_counter;
313
        status_reg(5-mem_adr_width downto 0)<= (others=>'0');
314
  end generate;
315
 
316
  -- data out multiplexer
317
  wb_dat_o<= mem_do when sel_dev=s_mem_data else -- memory is clocked by wb_clk_I so need not additional register
318
          reg_do_q; -- reg_out is registered only when two_clocks=1
319
 
320
  reg_do<= trig_datR when sel_dev= s_triger else
321
        counter_rd(15 downto 8) when sel_dev= s_counter and wb_adr_I(0)='1' else
322
        counter_rd(7 downto 0) when sel_dev= s_counter and wb_adr_I(0)='0' else
323
        status_reg when sel_dev = s_status_reg else
324
        "00000000";
325
 
326
  -- ackR logic (ack_O for reading)      BRAM needs 2 clock cycles for reading
327
  process(arst, wb_clk_I) begin
328
        if arst='1' then ackR<= '0';
329
        elsif wb_clk_I'event and wb_clk_I='1' then
330
          ackR<= not wb_ack_O and wb_stb_I; -- strobe is active (valid address) and not data transfer
331
        end if;
332
  end process;
333
 
334
-- check generic values:
335
        assert data_width=32 or data_width=16 or data_width=8
336
          report "Error in log_anal: data_width must be: 8, 16 or 32"
337
                severity failure;
338
        assert mem_adr_width<=16 and mem_adr_width>=4
339
           report "Error in log_anal: mem_adr_width must not be in range 4 to 16"
340
                severity failure;
341
        assert (adr_width = mem_adr_width+1 and data_width=8) or
342
           (adr_width = mem_adr_width+2 and data_width=16) or
343
           (adr_width = mem_adr_width+3 and data_width=32)
344
           report "Error in log_anal: c_adr_width should be: adr_width + 1 + log2(data_width/8)"
345
           severity failure;
346
        assert trig_width<=32
347
          report "Error in log_anal: trig_width must not be greater than 32"
348
          severity failure;
349
end LA;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.