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

Subversion Repositories ccsds_rxtxsoc

[/] [ccsds_rxtxsoc/] [trunk/] [ccsds_tx_framer.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 zguig52
-------------------------------
2
---- Project: EurySPACE CCSDS RX/TX with wishbone interface
3
---- Design Name: ccsds_tx_framer
4
---- Version: 1.0.0
5
---- Description:
6
---- Implementation of standard CCSDS 132.0-B-2
7
-------------------------------
8
---- Author(s):
9
---- Guillaume REMBERT
10
-------------------------------
11
---- Licence:
12
---- MIT
13
-------------------------------
14
---- Changes list:
15
---- 2016/02/27: initial release
16
---- 2016/10/20: rework
17
---- 2016/10/24: multiple footers generation to ensure higher speed than input max data rate (CCSDS_TX_FRAMER_DATA_BUS_SIZE*CLK_FREQ bits/sec)
18
---- 2016/10/31: ressources optimization
19
---- 2016/11/03: add only idle data insertion
20
-------------------------------
21
--TODO: trailer as option
22
--HEADER (6 up to 70 bytes) / before data / f(idle)
23
--TRANSFER FRAME DATA FIELD => Variable
24
--TRAILER (2 up to 6 bytes) / after data / f(data, header)
25
 
26
-- libraries used
27
library ieee;
28
use ieee.std_logic_1164.all;
29
 
30
--=============================================================================
31
-- Entity declaration for ccsds_tx / unitary tx framer inputs and outputs
32
--=============================================================================
33
entity ccsds_tx_framer is
34
  generic(
35
    constant CCSDS_TX_FRAMER_DATA_BUS_SIZE: integer; -- in bits
36
    constant CCSDS_TX_FRAMER_DATA_LENGTH: integer; -- in Bytes
37
    constant CCSDS_TX_FRAMER_FOOTER_LENGTH: integer; -- in Bytes
38
    constant CCSDS_TX_FRAMER_HEADER_LENGTH: integer; -- in Bytes
39
    constant CCSDS_TX_FRAMER_PARALLELISM_MAX_RATIO: integer := 16 -- activated max framer parallelism speed ratio / 1 = full speed / 2 = wishbone bus non-pipelined write max speed / ... / CCSDS_TX_FRAMER_DATA_BUS_SIZE = external serial data
40
  );
41
  port(
42
    -- inputs
43
    clk_i: in std_logic;
44
    dat_i: in std_logic_vector(CCSDS_TX_FRAMER_DATA_BUS_SIZE-1 downto 0);
45
    dat_val_i: in std_logic;
46
    rst_i: in std_logic;
47
    -- outputs
48
    dat_o: out std_logic_vector((CCSDS_TX_FRAMER_HEADER_LENGTH+CCSDS_TX_FRAMER_FOOTER_LENGTH+CCSDS_TX_FRAMER_DATA_LENGTH)*8-1 downto 0);
49
    dat_nxt_o: out std_logic;
50
    dat_val_o: out std_logic;
51
    idl_o: out std_logic
52
  );
53
end ccsds_tx_framer;
54
 
55
--=============================================================================
56
-- architecture declaration / internal components and connections
57
--=============================================================================
58
architecture structure of ccsds_tx_framer is
59
  component ccsds_tx_header is
60
    generic(
61
      constant CCSDS_TX_HEADER_LENGTH: integer
62
    );
63
    port(
64
      clk_i: in std_logic;
65
      idl_i: in std_logic;
66
      nxt_i: in std_logic;
67
      rst_i: in std_logic;
68
      dat_o: out std_logic_vector(CCSDS_TX_HEADER_LENGTH*8-1 downto 0);
69
      dat_val_o: out std_logic
70
    );
71
  end component;
72
  component ccsds_tx_footer is
73
    generic(
74
      constant CCSDS_TX_FOOTER_DATA_LENGTH : integer;
75
      constant CCSDS_TX_FOOTER_LENGTH: integer
76
    );
77
    port(
78
      clk_i: in std_logic;
79
      rst_i: in std_logic;
80
      nxt_i: in std_logic;
81
      bus_o: out std_logic;
82
      dat_i: in std_logic_vector(CCSDS_TX_FOOTER_DATA_LENGTH*8-1 downto 0);
83
      dat_o: out std_logic_vector((CCSDS_TX_FOOTER_LENGTH+CCSDS_TX_FOOTER_DATA_LENGTH)*8-1 downto 0);
84
      dat_val_o: out std_logic
85
    );
86
  end component;
87
 
88
-- internal constants
89
  constant CCSDS_TX_FRAMER_FOOTER_NUMBER : integer := CCSDS_TX_FRAMER_DATA_BUS_SIZE*((CCSDS_TX_FRAMER_HEADER_LENGTH+CCSDS_TX_FRAMER_DATA_LENGTH+CCSDS_TX_FRAMER_FOOTER_LENGTH)*8+1)/(CCSDS_TX_FRAMER_DATA_LENGTH*8*CCSDS_TX_FRAMER_PARALLELISM_MAX_RATIO)+1; -- 8*(HEAD+DATA+FOOT+1) clks / crc ; BUS bits / parallelism * clk ; DATA*8 bits / footer
90
  constant CCSDS_TX_FRAMER_OID_PATTERN: std_logic_vector(CCSDS_TX_FRAMER_DATA_LENGTH*8-1 downto 0) := (others => '1'); -- Only Idle Data Pattern transmitted (jam payload for frame stuffing)
91
 
92
-- internal variable signals 
93
  type frame_array is array (CCSDS_TX_FRAMER_FOOTER_NUMBER-1 downto 0) of std_logic_vector((CCSDS_TX_FRAMER_FOOTER_LENGTH+CCSDS_TX_FRAMER_DATA_LENGTH+CCSDS_TX_FRAMER_HEADER_LENGTH)*8-1 downto 0);
94
  signal wire_header_data: std_logic_vector(CCSDS_TX_FRAMER_HEADER_LENGTH*8-1 downto 0);
95
  signal wire_footer_data_o: frame_array;
96
  signal wire_header_data_valid: std_logic;
97
  signal wire_footer_data_valid: std_logic_vector(CCSDS_TX_FRAMER_FOOTER_NUMBER-1 downto 0);
98
  signal wire_header_next: std_logic := '0';
99
  signal wire_header_idle: std_logic := '0';
100
  signal wire_footer_next: std_logic_vector(CCSDS_TX_FRAMER_FOOTER_NUMBER-1 downto 0) := (others => '0');
101
  signal wire_footer_busy: std_logic_vector(CCSDS_TX_FRAMER_FOOTER_NUMBER-1 downto 0);
102
 
103
  signal reg_next_frame: std_logic_vector(CCSDS_TX_FRAMER_DATA_LENGTH*8-CCSDS_TX_FRAMER_DATA_BUS_SIZE-1 downto 0);
104
  signal reg_current_frame: std_logic_vector((CCSDS_TX_FRAMER_DATA_LENGTH)*8-1 downto 0);
105
  signal reg_processing_frame: std_logic_vector((CCSDS_TX_FRAMER_DATA_LENGTH+CCSDS_TX_FRAMER_HEADER_LENGTH)*8-1 downto 0);
106
  signal next_processing_frame_pointer : integer range 0 to CCSDS_TX_FRAMER_FOOTER_NUMBER-1 := 0;
107
 
108
-- components instanciation and mapping
109
  begin
110
  tx_header_0: ccsds_tx_header
111
    generic map(
112
      CCSDS_TX_HEADER_LENGTH => CCSDS_TX_FRAMER_HEADER_LENGTH
113
    )
114
    port map(
115
      clk_i => clk_i,
116
      idl_i => wire_header_idle,
117
      nxt_i => wire_header_next,
118
      rst_i => rst_i,
119
      dat_o => wire_header_data,
120
      dat_val_o => wire_header_data_valid
121
    );
122
 
123
  FOOTERGEN:
124
    for i in 0 to CCSDS_TX_FRAMER_FOOTER_NUMBER-1 generate
125
      tx_footer_x : ccsds_tx_footer
126
      generic map(
127
        CCSDS_TX_FOOTER_DATA_LENGTH => CCSDS_TX_FRAMER_DATA_LENGTH+CCSDS_TX_FRAMER_HEADER_LENGTH,
128
        CCSDS_TX_FOOTER_LENGTH => CCSDS_TX_FRAMER_FOOTER_LENGTH
129
      )
130
      port map(
131
        clk_i => clk_i,
132
        rst_i => rst_i,
133
        nxt_i => wire_footer_next(i),
134
        bus_o => wire_footer_busy(i),
135
        dat_i => reg_processing_frame,
136
        dat_o => wire_footer_data_o(i),
137
        dat_val_o => wire_footer_data_valid(i)
138
      );
139
    end generate FOOTERGEN;
140
 
141
-- presynthesis checks
142
    CHKFRAMERP0 : if ((CCSDS_TX_FRAMER_DATA_LENGTH*8) mod CCSDS_TX_FRAMER_DATA_BUS_SIZE /= 0) generate
143
      process
144
      begin
145
        report "ERROR: FRAMER DATA LENGTH SHOULD BE A MULTIPLE OF FRAMER DATA BUS SIZE" severity failure;
146
        wait;
147
      end process;
148
    end generate CHKFRAMERP0;
149
    CHKFRAMERP1 : if ((CCSDS_TX_FRAMER_DATA_LENGTH) = 0) generate
150
      process
151
      begin
152
        report "ERROR: FRAMER DATA LENGTH CANNOT BE 0" severity failure;
153
        wait;
154
      end process;
155
    end generate CHKFRAMERP1;
156
    CHKFRAMERP2 : if ((CCSDS_TX_FRAMER_PARALLELISM_MAX_RATIO) = 0) generate
157
      process
158
      begin
159
        report "ERROR: PARALLELISM MAX RATIO CANNOT BE 0" severity failure;
160
        wait;
161
      end process;
162
    end generate CHKFRAMERP2;
163
 
164
-- internal processing
165
 
166
    --=============================================================================
167
    -- Begin of frameroutputp
168
    -- Generate valid frame output on footer data_valid signal
169
    --=============================================================================
170
    -- read: rst_i, wire_footer_data, wire_footer_data_valid
171
    -- write: dat_o, dat_val_o
172
    -- r/w: next_valid_frame_pointer
173
    FRAMEROUTPUTP: process (clk_i)
174
    variable next_valid_frame_pointer : integer range 0 to CCSDS_TX_FRAMER_FOOTER_NUMBER-1 := 0;
175
    begin
176
      -- on each clock rising edge
177
      if rising_edge(clk_i) then
178
        -- reset signal received
179
        if (rst_i = '1') then
180
          next_valid_frame_pointer := 0;
181
          dat_o <= (others => '0');
182
          dat_val_o <= '0';
183
        -- generating valid frames output
184
        else
185
          dat_o <= wire_footer_data_o(next_valid_frame_pointer);
186
          if (wire_footer_data_valid(next_valid_frame_pointer) = '1') then
187
            dat_val_o <= '1';
188
            if (next_valid_frame_pointer < (CCSDS_TX_FRAMER_FOOTER_NUMBER-1)) then
189
              next_valid_frame_pointer := (next_valid_frame_pointer + 1);
190
            else
191
              next_valid_frame_pointer := 0;
192
            end if;
193
          else
194
            dat_o <= (others => '0');
195
            dat_val_o <= '0';
196
          end if;
197
        end if;
198
      end if;
199
    end process;
200
    --=============================================================================
201
    -- Begin of framerprocessp
202
    -- Start footer computation on valid header signal
203
    --=============================================================================
204
    -- read: wire_header_data, wire_header_data_valid
205
    -- write: next_processing_frame_pointer, reg_processing_frame, wire_footer_next
206
    -- r/w: 
207
    FRAMERPROCESSP: process (clk_i)
208
    variable reg_next_processing_frame: std_logic_vector((CCSDS_TX_FRAMER_DATA_LENGTH)*8-1 downto 0);
209
    begin
210
      -- on each clock rising edge
211
      if rising_edge(clk_i) then
212
        -- reset signal received
213
        if (rst_i = '1') then
214
          next_processing_frame_pointer <= 0;
215
          wire_footer_next <= (others => '0');
216
        else
217
          if(wire_header_data_valid = '1') then
218
            reg_processing_frame((CCSDS_TX_FRAMER_DATA_LENGTH+CCSDS_TX_FRAMER_HEADER_LENGTH)*8-1 downto CCSDS_TX_FRAMER_DATA_LENGTH*8) <= wire_header_data;
219
            -- idle data to be used
220
            if (wire_header_data(10 downto 0) = "11111111110") then
221
              reg_processing_frame(CCSDS_TX_FRAMER_DATA_LENGTH*8-1 downto 0) <= CCSDS_TX_FRAMER_OID_PATTERN;
222
              reg_next_processing_frame := reg_current_frame;
223
            -- current data to be used
224
            else
225
              -- continuous data flow header is one clk in advance
226
              if (CCSDS_TX_FRAMER_DATA_LENGTH*8 = CCSDS_TX_FRAMER_DATA_BUS_SIZE) and (CCSDS_TX_FRAMER_PARALLELISM_MAX_RATIO = 1) then
227
                reg_processing_frame(CCSDS_TX_FRAMER_DATA_LENGTH*8-1 downto 0) <= reg_next_processing_frame;
228
                reg_next_processing_frame := reg_current_frame;
229
              -- header is synchronous with data
230
              else
231
                reg_processing_frame(CCSDS_TX_FRAMER_DATA_LENGTH*8-1 downto 0) <= reg_current_frame;
232
              end if;
233
            end if;
234
            wire_footer_next(next_processing_frame_pointer) <= '1';
235
            if (next_processing_frame_pointer = CCSDS_TX_FRAMER_FOOTER_NUMBER-1) then
236
              next_processing_frame_pointer <= 0;
237
            else
238
              next_processing_frame_pointer <= (next_processing_frame_pointer + 1);
239
            end if;
240
          end if;
241
          if (next_processing_frame_pointer = 0) then
242
            wire_footer_next(CCSDS_TX_FRAMER_FOOTER_NUMBER-1) <= '0';
243
          else
244
            wire_footer_next(next_processing_frame_pointer-1) <= '0';
245
          end if;
246
        end if;
247
      end if;
248
    end process;
249
    --=============================================================================
250
    -- Begin of framergeneratep
251
    -- Generate next_frame, start next header generation
252
    --=============================================================================
253
    -- read: dat_val_i, rst_i
254
    -- write: wire_header_next, reg_current_frame, reg_next_frame, dat_nxt_o, idl_o
255
    -- r/w: 
256
    FRAMERGENERATEP: process (clk_i)
257
    variable next_frame_write_pos: integer range 0 to (CCSDS_TX_FRAMER_DATA_LENGTH*8/CCSDS_TX_FRAMER_DATA_BUS_SIZE)-1 := (CCSDS_TX_FRAMER_DATA_LENGTH*8/CCSDS_TX_FRAMER_DATA_BUS_SIZE)-1;
258
    variable frame_output_counter: integer range 0 to (CCSDS_TX_FRAMER_DATA_LENGTH*CCSDS_TX_FRAMER_PARALLELISM_MAX_RATIO*8/CCSDS_TX_FRAMER_DATA_BUS_SIZE)-1 := 0;
259
    variable current_frame_ready: std_logic := '0';
260
    begin
261
      -- on each clock rising edge
262
      if rising_edge(clk_i) then
263
        -- reset signal received
264
        if (rst_i = '1') then
265
          current_frame_ready := '0';
266
          wire_header_next <= '0';
267
          next_frame_write_pos := (CCSDS_TX_FRAMER_DATA_LENGTH*8/CCSDS_TX_FRAMER_DATA_BUS_SIZE)-1;
268
          frame_output_counter := 0;
269
          idl_o <= '0';
270
          dat_nxt_o <= '0';
271
        else
272
          -- valid data is presented
273
          if (dat_val_i = '1') then
274
            -- next frame is full
275
            if (next_frame_write_pos = 0) then
276
              reg_current_frame(CCSDS_TX_FRAMER_DATA_BUS_SIZE-1 downto 0) <= dat_i;
277
              reg_current_frame(CCSDS_TX_FRAMER_DATA_LENGTH*8-1 downto CCSDS_TX_FRAMER_DATA_BUS_SIZE) <= reg_next_frame;
278
              -- time to start frame computation
279
              if (frame_output_counter = 0) then
280
                -- CRC is ready to compute
281
                if (wire_footer_busy(next_processing_frame_pointer) = '0') then
282
                  frame_output_counter := (CCSDS_TX_FRAMER_DATA_LENGTH*8*CCSDS_TX_FRAMER_PARALLELISM_MAX_RATIO/CCSDS_TX_FRAMER_DATA_BUS_SIZE)-1;
283
                  wire_header_next <= '1';
284
                  wire_header_idle <= '0';
285
                  idl_o <= '0';
286
                -- source data rate overflow / stop buffer output
287
                else
288
                  dat_nxt_o <= '0';
289
                end if;
290
              else
291
                frame_output_counter := frame_output_counter - 1;
292
                -- signal a frame ready for computation
293
                if (current_frame_ready = '0') then
294
                  wire_header_next <= '0';
295
                  current_frame_ready := '1';
296
                -- source data rate overflow
297
                else
298
                  dat_nxt_o <= '0';
299
                end if;
300
              end if;
301
              next_frame_write_pos := CCSDS_TX_FRAMER_DATA_LENGTH*8/CCSDS_TX_FRAMER_DATA_BUS_SIZE-1;
302
            else
303
              -- filling next frame
304
              reg_next_frame(next_frame_write_pos*CCSDS_TX_FRAMER_DATA_BUS_SIZE-1 downto (next_frame_write_pos-1)*CCSDS_TX_FRAMER_DATA_BUS_SIZE) <= dat_i;
305
              next_frame_write_pos := next_frame_write_pos-1;
306
              -- time to start frame computation
307
              if (frame_output_counter = 0) then
308
                -- CRC is ready to compute
309
                if (wire_footer_busy(next_processing_frame_pointer) = '0') then
310
                  dat_nxt_o <= '1';
311
                  frame_output_counter := (CCSDS_TX_FRAMER_DATA_LENGTH*CCSDS_TX_FRAMER_PARALLELISM_MAX_RATIO*8/CCSDS_TX_FRAMER_DATA_BUS_SIZE)-1;
312
                  -- no frame is ready / inserting idle data
313
                  if (current_frame_ready = '0') then
314
                    wire_header_next <= '1';
315
                    wire_header_idle <= '1';
316
                    idl_o <= '1';
317
                  -- a frame is ready
318
                  else
319
                    wire_header_next <= '1';
320
                    wire_header_idle <= '0';
321
                    current_frame_ready := '0';
322
                    idl_o <= '0';
323
                  end if;
324
                else
325
                  dat_nxt_o <= '0';
326
                end if;
327
              else
328
                -- stop data before overflow
329
                if (next_frame_write_pos = 1) and (current_frame_ready = '1') then
330
                  dat_nxt_o <= '0';
331
                end if;
332
                frame_output_counter := frame_output_counter - 1;
333
                wire_header_next <= '0';
334
              end if;
335
            end if;
336
          -- no valid data
337
          else
338
            -- time to start frame computation
339
            if (frame_output_counter = 0) then
340
              -- CRC is ready to compute
341
              if (wire_footer_busy(next_processing_frame_pointer) = '0') then
342
                dat_nxt_o <= '1';
343
                frame_output_counter := (CCSDS_TX_FRAMER_DATA_LENGTH*CCSDS_TX_FRAMER_PARALLELISM_MAX_RATIO*8/CCSDS_TX_FRAMER_DATA_BUS_SIZE)-1;
344
                if (current_frame_ready = '0') then
345
                  wire_header_next <= '1';
346
                  wire_header_idle <= '1';
347
                  idl_o <= '1';
348
                else
349
                  wire_header_next <= '1';
350
                  wire_header_idle <= '0';
351
                  current_frame_ready := '0';
352
                  idl_o <= '0';
353
                end if;
354
              end if;
355
            else
356
              wire_header_next <= '0';
357
              frame_output_counter := frame_output_counter - 1;
358
            end if;
359
          end if;
360
        end if;
361
      end if;
362
    end process;
363
end structure;

powered by: WebSVN 2.1.0

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