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

Subversion Repositories artec_dongle_ii_fpga

[/] [artec_dongle_ii_fpga/] [trunk/] [src/] [usb/] [usb2mem.vhd] - Blame information for rev 6

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 nuubik
--COMMAND STRUCTURE OF SERAL USB PROTOCOL
2
 
3
-- MSBYTE   LSBYTE
4
 
5
-- DATA     CODE
6
 
7
--Dongle internal command codes
8
-- 0x00     0xC5                --Get Status data is don't care (must return) 0x3210 (3 is the MSNibble)
9
-- 0x01     0xC5        --Get Dongle version code
10
-- 0x02     0xC5        --PCB version code
11
-- 0x03     0xC5        --Get Mode switch setting
12
 
13
-- 0xC1     0xC5        --Release memeory interface to LPC
14
-- 0xC2     0xC5        --Put the device in USB programming mode (pulldown buf_en)
15
-- 0xC3     0xC5        --Force the dongle to indicate it's disconnected
16
-- 0xC4     0xC5        --Force the dongle to indicate it's connected
17
 
18
-- 0xC5     0xC5        --Force the dongle to lock memory interface
19
-- 0xC6     0xC5        --Force the dongle to unlock memory interface
20
 
21
-- 0x--     0xC5                --Get Status data is don't care (must return) 0x3210 (3 is the MSNibble)
22
 
23
 
24
-- 0xNN     0xCD        --Get Data from flash (performs read from current address) NN count of words auto increment address
25
-- 0xAA     0xA0                --Addr LSByte write
26
-- 0xAA     0xA1        --Addr Byte write
27
-- 0xAA     0xA2                --Addr MSByte write
28
-- 0x--     0x3F                --NOP
29
 
30
--Flash operations codes
31
-- 0xNN     0xE8        --Write to buffer returns extended satus NN is word count for USB machine
32
-- 0x--     0xD0                        -- 0xD0 is flash confirm command
33
 
34
--PSRAM operations codes
35
-- 0xNN     0xE9        --Write to buffer returns extended satus NN is word count for USB machine
36
-- 0xDD     0xDD        --N+1 times data expected 0xF + 1 is the maximum
37
 
38
 
39
--write flash buffer sequence
40
--      ???                                     -- set address if needed               
41
-- 0xNN     0xE8        --Write to buffer returns extended satus NN is word count for USB machine
42
-- 0x--     0xNN                        --0xNN is word count for flash ges directly to flash and is wordCount - 1
43
-- 0xDD     0xDD        --N+1 times data expected 0xF + 1 is the maximum
44
--      ...
45
-- 0x--     0xD0                        -- 0xD0 is flash confirm command
46
 
47
 
48
 
49
library IEEE;
50
use IEEE.std_logic_1164.all;
51
use IEEE.std_logic_unsigned.all;
52
use IEEE.std_logic_arith.all;
53
 
54
entity usb2mem is
55
  port (
56
    clk25     : in  std_logic;
57
    reset_n   : in  std_logic;
58
        dongle_ver: in std_logic_vector(15 downto 0);
59
        pcb_ver   : in std_logic_vector(15 downto 0);
60
        mode       : in    std_logic_vector(2 downto 0);  --sel upper addr bits
61
        usb_buf_en : out  std_logic;
62
        dev_present_n : out  std_logic;
63
    -- mem Bus
64
        mem_busy_n: in std_logic;
65
        mem_idle  : out std_logic; -- '1' if controller is idle (flash is safe for LPC reads)
66
    mem_addr  : out std_logic_vector(23 downto 0);
67
    mem_do    : out std_logic_vector(15 downto 0);
68
    mem_di    : in std_logic_vector(15 downto 0);
69
    mem_wr    : out std_logic;
70
    mem_val   : out std_logic;
71
    mem_ack   : in  std_logic;
72
    mem_cmd   : out std_logic;
73
    -- USB port
74
        usb_mode_en: in   std_logic;  -- enable this block 
75
    usb_rd_n   : out  std_logic;  -- enables out data if low (next byte detected by edge / in usb chip)
76
    usb_wr     : out  std_logic;  -- write performed on edge \ of signal
77
    usb_txe_n  : in   std_logic;  -- tx fifo empty (redy for new data if low)
78
    usb_rxf_n  : in   std_logic;  -- rx fifo empty (data redy if low)
79
    usb_bd     : inout  std_logic_vector(7 downto 0) --bus data
80
    );
81
end usb2mem;
82
 
83
 
84
architecture RTL of usb2mem is
85
 
86
 
87
 
88
 
89
  type state_type is (RESETs,RXCMD0s,RXCMD1s,DECODEs,INTERNs,VCIRDs,VCIWRs,TXCMD0s,TXCMD1s,STS_WAITs);
90
  signal CS : state_type;
91
 
92
  signal data_reg_i : std_logic_vector(15 downto 0);
93
  signal data_reg_o : std_logic_vector(15 downto 0);
94
  signal data_oe    : std_logic;  -- rx fifo empty (data redy if low)
95
  signal usb_wr_d   : std_logic;  -- internal readable output state for write
96
  signal addr_reg: std_logic_vector(23 downto 0);
97
 
98
  --State machine
99
  signal cmd_cnt   : std_logic_vector(15 downto 0);
100
  signal state_cnt : std_logic_vector(3 downto 0);
101
  --shyncro to USB
102
  signal usb_txe_nd  :    std_logic;  -- tx fifo empty (redy for new data if low)
103
  signal usb_rxf_nd  :    std_logic;  -- rx fifo empty (data redy if low)
104
  signal internal_cmd  :    std_logic;  -- rx fifo empty (data redy if low)
105
 
106
  signal read_mode   : std_logic;
107
  signal write_mode  : std_logic;
108
  signal write_count : std_logic;
109
  signal first_word : std_logic;
110
  signal mem_busy_nd : std_logic;
111
 
112
 
113
 
114
begin
115
 
116
--define internal command codes
117
internal_cmd <='1' when data_reg_i(7 downto 0) = x"C5" else
118
                                        '1' when data_reg_i(7 downto 0) = x"CD" else
119
                                        '1' when data_reg_i(7 downto 0) = x"A0" else
120
                                        '1' when data_reg_i(7 downto 0) = x"A1" else
121
                                        '1' when data_reg_i(7 downto 0) = x"A2" else
122
                                        '1' when data_reg_i(7 downto 0) = x"3F" else
123
                                        --These are spechial attention Flash commands
124
                                        '1' when data_reg_i(7 downto 0) = x"E8" else
125
                                        '1' when data_reg_i(7 downto 0) = x"E9" else
126
                                        '0';
127
 
128
 
129
usb_wr <= usb_wr_d when usb_mode_en='1' else
130
                  'Z';
131
 
132
 
133
-- this goes to byte buffer for that reason send LSB first and MSB second
134
usb_bd <=data_reg_o(7 downto 0)when data_oe='1' and CS=TXCMD0s and usb_mode_en='1' else --LSB byte first
135
                        data_reg_o(15 downto 8) when data_oe='1' and CS=TXCMD1s and usb_mode_en='1' else --MSB byte second
136
                        (others=>'Z');
137
 
138
 
139
process (clk25,reset_n)  --enable the scanning while in reset (simulation will be incorrect)
140
begin  -- process
141
  if reset_n='0' then
142
        CS <= RESETs;
143
        usb_rd_n <= '1';
144
        usb_wr_d <= '0';
145
        usb_txe_nd <= '1';
146
        usb_rxf_nd <= '1';
147
        data_oe <='0';
148
        state_cnt <=(others=>'0'); --init command counter
149
        mem_do <= (others=>'Z');
150
        mem_addr <= (others=>'Z');
151
        addr_reg <= (others=>'0');
152
        mem_val <= '0';
153
        mem_wr <='0';
154
        mem_cmd <='0';
155
        cmd_cnt <= (others=>'0');
156
        read_mode <='0';
157
        write_mode <='0';
158
        write_count <='0';
159
        first_word <='0';
160
        mem_idle <='1'; --set idle
161
        mem_busy_nd <='1';
162
        usb_buf_en <='1'; -- default mode (USB prog disabled, buffer with HiZ outputs)
163
        dev_present_n <='0'; --indicate that device is present on LPC bus for thincans
164
  elsif clk25'event and clk25 = '1' then    -- rising clock edge
165
        usb_txe_nd <= usb_txe_n; --syncronize
166
        usb_rxf_nd <= usb_rxf_n; --syncronize
167
        mem_busy_nd <=mem_busy_n; --syncronize
168
        case CS is
169
        when RESETs =>
170
                        if usb_rxf_nd='0' and usb_mode_en='1' and mem_busy_nd='1' then
171
                                state_cnt <=(others=>'0'); --init command counter
172
                                data_oe <='0'; --we will read command in
173
                                --mem_idle <='0'; --set busy untill return here
174
                                CS <= RXCMD0s;
175
                        end if;
176
                when RXCMD0s =>
177
                        if state_cnt="0000" then
178
                                usb_rd_n <='0'; -- set read low
179
                                state_cnt <= state_cnt + 1;-- must be min 50ns long (two cycles)
180
                        elsif state_cnt="0001" then
181
                                state_cnt <= state_cnt + 1;-- one wait cycle
182
                        elsif state_cnt="0010" then
183
                                state_cnt <= state_cnt + 1;-- now is ok
184
                                data_reg_i(15 downto 8) <= usb_bd; --get data form bus MSByte must come first
185
                        elsif state_cnt="0011" then
186
                                usb_rd_n <='1'; -- set read back to high
187
                                state_cnt <= state_cnt + 1;-- start wait        
188
                        elsif state_cnt="0100" then
189
                                state_cnt <= state_cnt + 1;-- wait      (the usb_rxf_n toggles after each read and next data is not ready)
190
                        elsif state_cnt="0101" then
191
                                state_cnt <= state_cnt + 1;-- wait      
192
                        elsif state_cnt="0110" then
193
                                state_cnt <= state_cnt + 1;-- now is ok prob.                                                                                                           
194
                        else
195
                                if usb_rxf_nd='0' then   --wait untill next byte is available
196
                                        state_cnt <=(others=>'0'); --init command counter
197
                                        CS <= RXCMD1s;
198
                                end if;
199
                        end if;
200
                when RXCMD1s =>
201
                        if state_cnt="0000" then
202
                                usb_rd_n <='0'; -- set read low
203
                                state_cnt <= state_cnt + 1;-- must be min 50ns long (two cycles)
204
                        elsif state_cnt="0001" then
205
                                state_cnt <= state_cnt + 1;-- one wait cycle
206
                        elsif state_cnt="0010" then
207
                                state_cnt <= state_cnt + 1;-- now is ok
208
                                data_reg_i(7 downto 0) <= usb_bd; --get data form bus LSByte must come last
209
                        elsif state_cnt="0011" then
210
                                state_cnt <= state_cnt + 1;-- now is ok
211
                                usb_rd_n <='1'; -- set read back to high        
212
                        elsif state_cnt="0100" then
213
                                state_cnt <= state_cnt + 1;-- wait (the usb_rxf_n toggles after each read and next data is not ready)
214
                        elsif state_cnt="0101" then
215
                                state_cnt <= state_cnt + 1;-- wait
216
                        elsif state_cnt="0110" then
217
                                state_cnt <= state_cnt + 1;-- now is ok prob.                                                                                           
218
                        else
219
                                state_cnt <=(others=>'0'); --init command counter
220
                                CS <= INTERNs;
221
                        end if;
222
                when INTERNs =>
223
                if      cmd_cnt=x"0000" then
224
                        if data_reg_i(7 downto 0)=x"A0" then
225
                                addr_reg(7 downto 0)<= data_reg_i(15 downto 8);
226
                                CS <= RESETs; --go back to resets
227
                        elsif data_reg_i(7 downto 0)=x"A1" then
228
                                addr_reg(15 downto 8)<= data_reg_i(15 downto 8);
229
                                CS <= RESETs; --go back to resets
230
                        elsif data_reg_i(7 downto 0)=x"A2" then
231
                                addr_reg(23 downto 16)<= data_reg_i(15 downto 8);
232
                                CS <= RESETs; --go back to resets
233
                        elsif data_reg_i(7 downto 0)=x"3F" then
234
                                CS <= RESETs; --go back to resets               --NOP command           
235
                        elsif data_reg_i(7 downto 0)=x"C5" then
236
                                if (data_reg_i(15 downto 8))=x"00" then
237
                                        data_reg_o <=x"3210";
238
                                elsif(data_reg_i(15 downto 8))=x"01" then
239
                                        data_reg_o <=dongle_ver;
240
                                elsif(data_reg_i(15 downto 8))=x"02" then
241
                                        data_reg_o <=pcb_ver;
242
                                elsif(data_reg_i(15 downto 8))=x"03" then
243
                                        data_reg_o <="0000000000000"&mode;
244
                                elsif(data_reg_i(15 downto 8))=x"C1" then       --release flash to LPC interface
245
                                        data_reg_o <=x"C1C5";
246
                                        mem_idle <='1'; --set idle
247
                                elsif(data_reg_i(15 downto 8))=x"C2" then       --force USB prog mode
248
                                        usb_buf_en <='0';
249
                                        data_reg_o <=x"C2C5";
250
                                elsif(data_reg_i(15 downto 8))=x"C3" then       --fake dongle disconnect
251
                                        data_reg_o <=x"C3C5";
252
                                        dev_present_n <='0';
253
                                elsif(data_reg_i(15 downto 8))=x"C4" then       --fake dongle connect
254
                                        data_reg_o <=x"C4C5";
255
                                        dev_present_n <='1';
256
                                elsif(data_reg_i(15 downto 8))=x"C5" then       --fake dongle connect
257
                                        data_reg_o <=x"C5C5";
258
                                        mem_idle <='0';  --lock LPC out from memory interface
259
                                elsif(data_reg_i(15 downto 8))=x"C6" then       --fake dongle connect
260
                                        data_reg_o <=x"C6C5";
261
                                        mem_idle <='1';  --unlock memory interface                                      
262
                                else
263
                                        data_reg_o <=x"3210";  --always return even on unknown commands
264
                                end if;
265
                                CS <= TXCMD0s;
266
                        elsif data_reg_i(7 downto 0)=x"CD" then
267
                                if (data_reg_i(15 downto 8))=x"00" then --64K word read coming
268
                                        cmd_cnt <= (others=>'1'); --64K word count
269
                                else
270
                                        cmd_cnt <= x"00"&data_reg_i(15 downto 8) - 1; -- -1 as one read will be done right now (cmd_cnt words)
271
                                end if;
272
                                CS <= VCIRDs; --go perform a read
273
                                read_mode <='1';
274
                        elsif data_reg_i(7 downto 0)=x"E8" then
275
                            --write_mode <='1';
276
                                write_count <='0';
277
                                first_word <='0';
278
                                cmd_cnt <= x"00"&data_reg_i(15 downto 8) + 1;  --+2 for direct count write +1
279
                                data_reg_i(15 downto 8)<=(others=>'0');
280
                                CS <= VCIWRs; --go perform a write
281
                        elsif data_reg_i(7 downto 0)=x"E9" then
282
                                write_count <='1';  --no initial command write
283
                                first_word <='0';
284
                                if (data_reg_i(15 downto 8))=x"00" then --64K word write coming
285
                                        cmd_cnt <= (others=>'1'); --64K word count
286
                                else
287
                                        cmd_cnt <= x"00"&data_reg_i(15 downto 8);
288
                                end if;
289
                                data_reg_i(15 downto 8)<=(others=>'0');
290
                                CS <= RESETs;    --PSRAM does not need command                  
291
                        else
292
                                CS <= VCIWRs;
293
                        end if;
294
                else
295
                        if cmd_cnt>x"0000" then
296
                                cmd_cnt<= cmd_cnt - 1;
297
                                if write_count='0' then
298
                                        write_count<='1';
299
                                elsif write_count='1' and  first_word ='0' then
300
                                        first_word <='1';
301
                                elsif write_count='1' and  first_word ='1' then
302
                                        addr_reg <= addr_reg + 1; --autoincrement address in in block mode
303
                                end if;
304
                                --if cmd_cnt>x"02" then --so not to increase too many times on write buffer
305
                                --      addr_reg <= addr_reg + 1; --autoincrement address in in block mode
306
                                --end if;
307
                        end if;
308
                        CS <= VCIWRs;
309
                end if;
310
                when VCIRDs =>          --flash read
311
                        mem_wr <='0';                    --this is VCI write_not_read
312
                        mem_cmd <='0';
313
                        mem_addr <= addr_reg(22 downto 0)&'0'; --translate byte address to word address
314
                        mem_val <= '1';
315
                        if mem_ack='1' then
316
                                data_reg_o <= mem_di;
317
                                mem_wr <='0';                    --this is VCI write_not_read
318
                                mem_cmd <='0';
319
                                mem_val <= '0';
320
                                CS <= TXCMD0s;
321
                        end if;
322
                when VCIWRs =>          --flash write
323
                        mem_addr <= addr_reg(22 downto 0)&'0'; --translate byte address to word address
324
                        if mode(2)='1' then
325
                                --this HW swap removes the need to swap bytes in python for PSRAM region
326
                                mem_do <= data_reg_i(7 downto 0)&data_reg_i(15 downto 8); --SWAP data for PSRAM region
327
                        else
328
                                mem_do <= data_reg_i;   --USB data in will go to mem_out
329
                        end if;
330
                        mem_wr <='1';                   --this is VCI write_not_read
331
                        mem_cmd <='1';
332
                        mem_val <= '1';
333
                        if mem_ack='1' then
334
                                mem_do <= (others=>'Z');
335
                                mem_wr <='0';                    --this is VCI write_not_read
336
                                mem_cmd <='0';
337
                                mem_val <= '0';
338
                                --if write_mode='0' then
339
 
340
                                        if cmd_cnt=x"0000" then --if flash command and not data
341
                                                state_cnt <=(others=>'0'); --init command counter
342
                                                CS <= STS_WAITs;
343
                                        else
344
                                                CS <= RESETs;
345
                                        end if;
346
                                --else  --else if was 0xE8 must read and return XSR
347
                                --      write_mode <='0'; --XSR return will no follow clear this bit
348
                                --      CS <= VCIRDs;
349
                                --end if;
350
                        end if;
351
                when TXCMD0s =>  --transmit over USB what ever is in data_reg_o MSB first
352
 
353
                                if state_cnt="0000" then
354
                                        if usb_txe_nd='0' then
355
                                                usb_wr_d<='1'; -- data is mux'ed by state and data_oe in the beginning of arch
356
                                                state_cnt <= state_cnt + 1;-- now is ok
357
                                        end if;
358
                                elsif state_cnt="0010" then
359
                                    data_oe<='1'; --this is to put data on bus befora falling edge of wr (max 20ns before)
360
                                        state_cnt <= state_cnt + 1;-- now is ok
361
                                elsif state_cnt="0011" then
362
                                    usb_wr_d<='0'; --falling edge performs write  must be high for atleast 50ns
363
                                        state_cnt <= state_cnt + 1;-- now is ok
364
                                elsif state_cnt="0100" then
365
                                        state_cnt <= state_cnt + 1;-- now is ok         
366
                                        data_oe<='0';
367
                                elsif state_cnt="0111" then       --must stay low at least 50ns
368
                                        CS <= TXCMD1s;
369
                                        state_cnt <= (others=>'0');
370
                                else
371
                                        state_cnt <= state_cnt + 1;-- if intermediate cnt then count
372
                                end if;
373
 
374
                when TXCMD1s =>
375
 
376
                                if state_cnt="0000" then
377
                                    if usb_txe_nd='0' then
378
                                                usb_wr_d<='1'; -- data is mux'ed by state and data_oe in the beginning of arch
379
                                                state_cnt <= state_cnt + 1;-- now is ok
380
                                        end if;
381
                                elsif state_cnt="0010" then
382
                                    data_oe<='1'; --this is to put data on bus befora falling edge of wr (max 20ns before)
383
                                        state_cnt <= state_cnt + 1;-- now is ok
384
                                elsif state_cnt="0011" then
385
                                    usb_wr_d<='0'; --falling edge performs write  must be high for atleast 50ns
386
                                        state_cnt <= state_cnt + 1;-- now is ok
387
                                elsif state_cnt="0100" then
388
                                        state_cnt <= state_cnt + 1;-- now is ok         
389
                                        data_oe<='0';
390
                                elsif state_cnt="0111" then       --must stay low at least 50ns
391
                                        if read_mode='0' then
392
                                                CS <= RESETs;
393
                                        elsif cmd_cnt="0000" then --last word sent
394
                                                addr_reg <= addr_reg + 1; --autoincrement address in read mode
395
                                                read_mode <='0';
396
                                                CS <= RESETs;
397
                                        else
398
                                                cmd_cnt<= cmd_cnt - 1;
399
                                                addr_reg <= addr_reg + 1; --autoincrement address in read mode
400
                                                CS <= VCIRDs;   --more data to be read
401
                                        end if;
402
                                        state_cnt <= (others=>'0');
403
                                else
404
                                        state_cnt <= state_cnt + 1;-- if intermediate cnt then count
405
                                end if;
406
                when STS_WAITs =>
407
                                if mem_busy_nd='0' or mode(2)='1' then  --go to RESETs if PSRAM mode is selected
408
                                        CS <= RESETs; --now it's ok to go here
409
                                else
410
                                        state_cnt <= state_cnt + 1;
411
                                        if state_cnt="1111" then
412
                                                --sts cant take longer than 500 ns to go low
413
                                                CS <= RESETs; --time out go to resets anyway
414
                                        end if;
415
                                end if;
416
        when others => null;
417
        end case;
418
  end if;
419
end process;
420
 
421
 
422
 
423
end RTL;
424
 

powered by: WebSVN 2.1.0

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