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

Subversion Repositories astron_mm

[/] [astron_mm/] [trunk/] [common_reg_r_w_dc.vhd] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 danv
-------------------------------------------------------------------------------
2
--
3 3 danv
-- Copyright 2020
4 2 danv
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
5
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
6 3 danv
-- 
7
-- Licensed under the Apache License, Version 2.0 (the "License");
8
-- you may not use this file except in compliance with the License.
9
-- You may obtain a copy of the License at
10
-- 
11
--     http://www.apache.org/licenses/LICENSE-2.0
12
-- 
13
-- Unless required by applicable law or agreed to in writing, software
14
-- distributed under the License is distributed on an "AS IS" BASIS,
15
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
-- See the License for the specific language governing permissions and
17
-- limitations under the License.
18 2 danv
--
19
-------------------------------------------------------------------------------
20
 
21
-- Purpose: Provide dual clock domain crossing to common_reg_r_w.vhd
22
-- Description:
23
-- . Write vector to out_reg
24
-- . Read vector from in_reg or readback from out_reg
25
--
26
--   31             24 23             16 15              8 7               0  wi
27
--  |-----------------|-----------------|-----------------|-----------------|
28
--  |                              data[31:0]                               |  0
29
--  |-----------------------------------------------------------------------|
30
--  |                              data[63:32]                              |  1
31
--  |-----------------------------------------------------------------------|
32
--
33
-- . g_readback
34
--   When g_readback is TRUE then the written data is read back from the st_clk
35
--   domain directly into the mm_clk domain, so without ST --> MM clock domain
36
--   crossing logic. This is allowed because the read back value is stable. 
37
--   For readback the out_reg needs to be connected to in_reg, independent of
38
--   the g_readback setting, because the readback value is read back from the
39
--   st_clk domain. In this way the readback value also reveals that the 
40
--   written value is indeed available in the st_clk domain (ie. this shows 
41
--   that the st_clk is active). If g_cross_clock_domain=FALSE, then g_readback
42
--   is don't care.
43
--   In fact g_readback could better be called g_st_readback. An alternative
44
--   g_mm_readback could define direct read back in the MM clock domain and
45
--   would allow leaving the in_reg not connected.
46
 
47 4 danv
LIBRARY IEEE, common_pkg_lib, common_components_lib, astron_ram_lib;
48 2 danv
USE IEEE.STD_LOGIC_1164.ALL;
49
USE common_pkg_lib.common_pkg.ALL;
50 4 danv
USE astron_ram_lib.common_ram_pkg.ALL;
51 2 danv
 
52
ENTITY common_reg_r_w_dc IS
53
  GENERIC (
54
    g_cross_clock_domain : BOOLEAN := TRUE;  -- use FALSE when mm_clk and st_clk are the same, else use TRUE to cross the clock domain
55
    g_in_new_latency     : NATURAL := 0;  -- >= 0
56
    g_readback           : BOOLEAN := FALSE;  -- must use FALSE for write/read or read only register when g_cross_clock_domain=TRUE
57
    --g_readback           : BOOLEAN := TRUE;   -- can use TRUE for write and readback register
58
    g_reg                : t_c_mem := c_mem_reg;
59
    g_init_reg           : STD_LOGIC_VECTOR(c_mem_reg_init_w-1 DOWNTO 0) := (OTHERS => '0')
60
  );
61
  PORT (
62
    -- Clocks and reset
63
    mm_rst      : IN  STD_LOGIC;   -- reset synchronous with mm_clk
64
    mm_clk      : IN  STD_LOGIC;   -- memory-mapped bus clock
65
    st_rst      : IN  STD_LOGIC;   -- reset synchronous with st_clk
66
    st_clk      : IN  STD_LOGIC;   -- other clock domain clock
67
 
68
    -- Memory Mapped Slave in mm_clk domain
69
    sla_in      : IN  t_mem_mosi;  -- actual ranges defined by g_reg
70
    sla_out     : OUT t_mem_miso;  -- actual ranges defined by g_reg
71
 
72
    -- MM registers in st_clk domain
73
    reg_wr_arr  : OUT STD_LOGIC_VECTOR(            g_reg.nof_dat-1 DOWNTO 0);
74
    reg_rd_arr  : OUT STD_LOGIC_VECTOR(            g_reg.nof_dat-1 DOWNTO 0);
75
    in_new      : IN  STD_LOGIC := '1';
76
    in_reg      : IN  STD_LOGIC_VECTOR(g_reg.dat_w*g_reg.nof_dat-1 DOWNTO 0);
77
    out_reg     : OUT STD_LOGIC_VECTOR(g_reg.dat_w*g_reg.nof_dat-1 DOWNTO 0);
78
    out_new     : OUT STD_LOGIC    -- Pulses '1' when new data has been written. 
79
  );
80
END common_reg_r_w_dc;
81
 
82
 
83
ARCHITECTURE str OF common_reg_r_w_dc IS
84
 
85
  -- Registers in mm_clk domain
86
  SIGNAL vector_wr_arr   : STD_LOGIC_VECTOR(            g_reg.nof_dat-1 DOWNTO 0);
87
  SIGNAL vector_rd_arr   : STD_LOGIC_VECTOR(            g_reg.nof_dat-1 DOWNTO 0);
88
  SIGNAL out_vector      : STD_LOGIC_VECTOR(g_reg.dat_w*g_reg.nof_dat-1 DOWNTO 0);
89
  SIGNAL in_vector       : STD_LOGIC_VECTOR(g_reg.dat_w*g_reg.nof_dat-1 DOWNTO 0);
90
 
91
  -- Initialize output to avoid Warning: (vsim-8684) No drivers exist on out port *, and its initial value is not used
92
  SIGNAL i_sla_out       : t_mem_miso := c_mem_miso_rst;
93
 
94
  SIGNAL reg_wr_arr_i    : STD_LOGIC_VECTOR(            g_reg.nof_dat-1 DOWNTO 0);
95
  SIGNAL wr_pulse        : STD_LOGIC;
96
  SIGNAL toggle          : STD_LOGIC;
97
  SIGNAL out_new_i       : STD_LOGIC;
98
 
99
BEGIN
100
 
101
  ------------------------------------------------------------------------------
102
  -- MM register access in the mm_clk domain
103
  ------------------------------------------------------------------------------
104
 
105
  sla_out <= i_sla_out;
106
 
107
  u_reg : ENTITY work.common_reg_r_w
108
  GENERIC MAP (
109
    g_reg      => g_reg,
110
    g_init_reg => g_init_reg
111
  )
112
  PORT MAP (
113
    rst         => mm_rst,
114
    clk         => mm_clk,
115
    -- control side
116
    wr_en       => sla_in.wr,
117
    wr_adr      => sla_in.address(g_reg.adr_w-1 DOWNTO 0),
118
    wr_dat      => sla_in.wrdata(g_reg.dat_w-1 DOWNTO 0),
119
    rd_en       => sla_in.rd,
120
    rd_adr      => sla_in.address(g_reg.adr_w-1 DOWNTO 0),
121
    rd_dat      => i_sla_out.rddata(g_reg.dat_w-1 DOWNTO 0),
122
    rd_val      => i_sla_out.rdval,
123
    -- data side
124
    reg_wr_arr  => vector_wr_arr,
125
    reg_rd_arr  => vector_rd_arr,
126
    out_reg     => out_vector,
127
    in_reg      => in_vector
128
  );
129
 
130
 
131
  ------------------------------------------------------------------------------
132
  -- Transfer register value between mm_clk and st_clk domain.
133
  -- If the function of the register ensures that the value will not be used
134
  -- immediately when it was set, then the transfer between the clock domains
135
  -- can be done by wires only. Otherwise if the change in register value can
136
  -- have an immediate effect then the bit or word value needs to be transfered
137
  -- using:
138
  --
139
  -- . common_async            --> for single-bit level signal
140
  -- . common_spulse           --> for single-bit pulse signal
141
  -- . common_reg_cross_domain --> for a multi-bit (a word) signal
142
  --
143
  -- Typically always use a crossing component for the single bit signals (to
144
  -- be on the save side) and only use a crossing component for the word
145
  -- signals if it is necessary (to avoid using more logic than necessary).
146
  ------------------------------------------------------------------------------
147
 
148
  no_cross : IF g_cross_clock_domain = FALSE GENERATE
149
    in_vector   <= in_reg;
150
    out_reg     <= out_vector;
151
    reg_wr_arr  <= vector_wr_arr;
152
    reg_rd_arr  <= vector_rd_arr;
153
    out_new     <= vector_wr_arr(0);
154
  END GENERATE;  -- no_cross
155
 
156
  gen_cross : IF g_cross_clock_domain = TRUE GENERATE
157
 
158
    gen_rdback : IF g_readback=TRUE GENERATE
159
      in_vector <= in_reg;
160
    END GENERATE;
161
 
162
    gen_rd : IF g_readback=FALSE GENERATE
163
      u_in_vector : ENTITY work.common_reg_cross_domain
164
      GENERIC MAP (
165
        g_in_new_latency => g_in_new_latency
166
      )
167
      PORT MAP (
168
        in_rst      => st_rst,
169
        in_clk      => st_clk,
170
        in_new      => in_new,
171
        in_dat      => in_reg,
172
        in_done     => OPEN,
173
        out_rst     => mm_rst,
174
        out_clk     => mm_clk,
175
        out_dat     => in_vector,
176
        out_new     => OPEN
177
      );
178
    END GENERATE;
179
 
180
    u_out_reg : ENTITY work.common_reg_cross_domain
181
    GENERIC MAP(
182
      g_out_dat_init => g_init_reg
183
    )
184
    PORT MAP (
185
      in_rst      => mm_rst,
186
      in_clk      => mm_clk,
187
      in_dat      => out_vector,
188
      in_done     => OPEN,
189
      out_rst     => st_rst,
190
      out_clk     => st_clk,
191
      out_dat     => out_reg,
192
      out_new     => out_new_i
193
    );
194
 
195
    u_toggle : ENTITY common_components_lib.common_switch
196
    GENERIC MAP (
197
      g_rst_level    => '0',
198
      g_priority_lo  => FALSE,
199
      g_or_high      => FALSE,
200
      g_and_low      => FALSE
201
    )
202
    PORT MAP (
203
      rst         => st_rst,
204
      clk         => st_clk,
205
      switch_high => wr_pulse,
206
      switch_low  => out_new_i,
207
      out_level   => toggle
208
    );
209
 
210
    wr_pulse   <= '0' WHEN vector_or(reg_wr_arr_i)='0' ELSE '1';
211
    out_new    <= out_new_i AND toggle;
212
    reg_wr_arr <= reg_wr_arr_i;
213
 
214
    gen_access_evt : FOR I IN 0 TO g_reg.nof_dat-1 GENERATE
215
      u_reg_wr_arr : ENTITY common_components_lib.common_spulse
216
      PORT MAP (
217
        in_rst    => mm_rst,
218
        in_clk    => mm_clk,
219
        in_pulse  => vector_wr_arr(I),
220
        in_busy   => OPEN,
221
        out_rst   => st_rst,
222
        out_clk   => st_clk,
223
        out_pulse => reg_wr_arr_i(I)
224
      );
225
 
226
      u_reg_rd_arr : ENTITY common_components_lib.common_spulse
227
      PORT MAP (
228
        in_rst    => mm_rst,
229
        in_clk    => mm_clk,
230
        in_pulse  => vector_rd_arr(I),
231
        in_busy   => OPEN,
232
        out_rst   => st_rst,
233
        out_clk   => st_clk,
234
        out_pulse => reg_rd_arr(I)
235
      );
236
    END GENERATE;
237
 
238
  END GENERATE;  -- gen_cross
239
 
240
END str;

powered by: WebSVN 2.1.0

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