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 9

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 9 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_o   : out  std_logic_vector(7 downto 0); --bus data
80
         usb_bd     : in   std_logic_vector(7 downto 0) --bus data
81
    );
82
end usb2mem;
83
 
84
 
85
architecture RTL of usb2mem is
86
 
87
 
88
 
89
 
90
  type state_type is (RESETs,RXCMD0s,RXCMD1s,DECODEs,INTERNs,VCIRDs,VCIWRs,TXCMD0s,TXCMD1s,STS_WAITs);
91
  signal CS : state_type;
92
 
93
  signal data_reg_i : std_logic_vector(15 downto 0);
94
  signal data_reg_o : std_logic_vector(15 downto 0);
95
  signal data_oe    : std_logic;  -- rx fifo empty (data redy if low)
96
  signal usb_wr_d   : std_logic;  -- internal readable output state for write
97
  signal addr_reg: std_logic_vector(23 downto 0);
98
 
99
  --State machine
100
  signal cmd_cnt   : std_logic_vector(15 downto 0);
101
  signal state_cnt : std_logic_vector(3 downto 0);
102
  --shyncro to USB
103
  signal usb_txe_nd  :    std_logic;  -- tx fifo empty (redy for new data if low)
104
  signal usb_rxf_nd  :    std_logic;  -- rx fifo empty (data redy if low)
105
  --signal internal_cmd  :    std_logic;  -- rx fifo empty (data redy if low)
106
 
107
  signal read_mode   : std_logic;
108
  --signal write_mode  : std_logic;
109
  signal write_count : std_logic;
110
  signal first_word : std_logic;
111
  signal mem_busy_nd : std_logic;
112
 
113
 
114
 
115
begin
116
 
117
usb_wr <= usb_wr_d;
118
 
119
-- this goes to byte buffer for that reason send LSB first and MSB second
120
usb_bd_o <=data_reg_o(7 downto 0)when data_oe='1' and CS=TXCMD0s and usb_mode_en='1' else --LSB byte first
121
                          data_reg_o(15 downto 8) when data_oe='1' and CS=TXCMD1s and usb_mode_en='1' else
122
                          (others=>'0');
123
 
124
 
125
process (clk25,reset_n)  --enable the scanning while in reset (simulation will be incorrect)
126
begin  -- process
127
  if reset_n='0' then
128
        CS <= RESETs;
129
        usb_rd_n <= '1';
130
        usb_wr_d <= '0';
131
        usb_txe_nd <= '1';
132
        usb_rxf_nd <= '1';
133
        data_oe <='0';
134
        state_cnt <=(others=>'0'); --init command counter
135
        mem_do <= (others=>'0');
136
        mem_addr <= (others=>'0');
137
        addr_reg <= (others=>'0');
138
        mem_val <= '0';
139
        mem_wr <='0';
140
        mem_cmd <='0';
141
        cmd_cnt <= (others=>'0');
142
        read_mode <='0';
143
        write_count <='0';
144
        first_word <='0';
145
        mem_idle <='1'; --set idle
146
        mem_busy_nd <='1';
147
        usb_buf_en <='1'; -- default mode (USB prog disabled, buffer with HiZ outputs)
148
        dev_present_n <='0'; --indicate that device is present on LPC bus for thincans
149
  elsif clk25'event and clk25 = '1' then    -- rising clock edge
150
        usb_txe_nd <= usb_txe_n; --syncronize
151
        usb_rxf_nd <= usb_rxf_n; --syncronize
152
        mem_busy_nd <=mem_busy_n; --syncronize
153
        case CS is
154
        when RESETs =>
155
                        if usb_rxf_nd='0' and usb_mode_en='1' and mem_busy_nd='1' then
156
                                state_cnt <=(others=>'0'); --init command counter
157
                                data_oe <='0'; --we will read command in
158
                                --mem_idle <='0'; --set busy untill return here
159
                                CS <= RXCMD0s;
160
                        end if;
161
                when RXCMD0s =>
162
                        if state_cnt="0000" then
163
                                usb_rd_n <='0'; -- set read low
164
                                state_cnt <= state_cnt + 1;-- must be min 50ns long (two cycles)
165
                        elsif state_cnt="0001" then
166
                                state_cnt <= state_cnt + 1;-- one wait cycle
167
                        elsif state_cnt="0010" then
168
                                state_cnt <= state_cnt + 1;-- now is ok
169
                                data_reg_i(15 downto 8) <= usb_bd; --get data form bus MSByte must come first
170
                        elsif state_cnt="0011" then
171
                                usb_rd_n <='1'; -- set read back to high
172
                                state_cnt <= state_cnt + 1;-- start wait        
173
                        elsif state_cnt="0100" then
174
                                state_cnt <= state_cnt + 1;-- wait      (the usb_rxf_n toggles after each read and next data is not ready)
175
                        elsif state_cnt="0101" then
176
                                state_cnt <= state_cnt + 1;-- wait      
177
                        elsif state_cnt="0110" then
178
                                state_cnt <= state_cnt + 1;-- now is ok prob.                                                                                                           
179
                        else
180
                                if usb_rxf_nd='0' then   --wait untill next byte is available
181
                                        state_cnt <=(others=>'0'); --init command counter
182
                                        CS <= RXCMD1s;
183
                                end if;
184
                        end if;
185
                when RXCMD1s =>
186
                        if state_cnt="0000" then
187
                                usb_rd_n <='0'; -- set read low
188
                                state_cnt <= state_cnt + 1;-- must be min 50ns long (two cycles)
189
                        elsif state_cnt="0001" then
190
                                state_cnt <= state_cnt + 1;-- one wait cycle
191
                        elsif state_cnt="0010" then
192
                                state_cnt <= state_cnt + 1;-- now is ok
193
                                data_reg_i(7 downto 0) <= usb_bd; --get data form bus LSByte must come last
194
                        elsif state_cnt="0011" then
195
                                state_cnt <= state_cnt + 1;-- now is ok
196
                                usb_rd_n <='1'; -- set read back to high        
197
                        elsif state_cnt="0100" then
198
                                state_cnt <= state_cnt + 1;-- wait (the usb_rxf_n toggles after each read and next data is not ready)
199
                        elsif state_cnt="0101" then
200
                                state_cnt <= state_cnt + 1;-- wait
201
                        elsif state_cnt="0110" then
202
                                state_cnt <= state_cnt + 1;-- now is ok prob.                                                                                           
203
                        else
204
                                state_cnt <=(others=>'0'); --init command counter
205
                                CS <= INTERNs;
206
                        end if;
207
                when INTERNs =>
208
                if      cmd_cnt=x"0000" then
209
                        if data_reg_i(7 downto 0)=x"A0" then
210
                                addr_reg(7 downto 0)<= data_reg_i(15 downto 8);
211
                                CS <= RESETs; --go back to resets
212
                        elsif data_reg_i(7 downto 0)=x"A1" then
213
                                addr_reg(15 downto 8)<= data_reg_i(15 downto 8);
214
                                CS <= RESETs; --go back to resets
215
                        elsif data_reg_i(7 downto 0)=x"A2" then
216
                                addr_reg(23 downto 16)<= data_reg_i(15 downto 8);
217
                                CS <= RESETs; --go back to resets
218
                        elsif data_reg_i(7 downto 0)=x"3F" then
219
                                CS <= RESETs; --go back to resets               --NOP command           
220
                        elsif data_reg_i(7 downto 0)=x"C5" then
221
                                if (data_reg_i(15 downto 8))=x"00" then
222
                                        data_reg_o <=x"3210";
223
                                elsif(data_reg_i(15 downto 8))=x"01" then
224
                                        data_reg_o <=dongle_ver;
225
                                elsif(data_reg_i(15 downto 8))=x"02" then
226
                                        data_reg_o <=pcb_ver;
227
                                elsif(data_reg_i(15 downto 8))=x"03" then
228
                                        data_reg_o <="0000000000000"&mode;
229
                                elsif(data_reg_i(15 downto 8))=x"C1" then       --release flash to LPC interface
230
                                        data_reg_o <=x"C1C5";
231
                                        mem_idle <='1'; --set idle
232
                                elsif(data_reg_i(15 downto 8))=x"C2" then       --force USB prog mode
233
                                        usb_buf_en <='0';
234
                                        data_reg_o <=x"C2C5";
235
                                elsif(data_reg_i(15 downto 8))=x"C3" then       --fake dongle disconnect
236
                                        data_reg_o <=x"C3C5";
237
                                        dev_present_n <='0';
238
                                elsif(data_reg_i(15 downto 8))=x"C4" then       --fake dongle connect
239
                                        data_reg_o <=x"C4C5";
240
                                        dev_present_n <='1';
241
                                elsif(data_reg_i(15 downto 8))=x"C5" then       --fake dongle connect
242
                                        data_reg_o <=x"C5C5";
243
                                        mem_idle <='0';  --lock LPC out from memory interface
244
                                elsif(data_reg_i(15 downto 8))=x"C6" then       --fake dongle connect
245
                                        data_reg_o <=x"C6C5";
246
                                        mem_idle <='1';  --unlock memory interface                                      
247
                                else
248
                                        data_reg_o <=x"3210";  --always return even on unknown commands
249
                                end if;
250
                                CS <= TXCMD0s;
251
                        elsif data_reg_i(7 downto 0)=x"CD" then
252
                                if (data_reg_i(15 downto 8))=x"00" then --64K word read coming
253
                                        cmd_cnt <= (others=>'1'); --64K word count
254
                                else
255
                                        cmd_cnt <= x"00"&data_reg_i(15 downto 8) - 1; -- -1 as one read will be done right now (cmd_cnt words)
256
                                end if;
257
                                CS <= VCIRDs; --go perform a read
258
                                read_mode <='1';
259
                        elsif data_reg_i(7 downto 0)=x"E8" then
260
                            --write_mode <='1';
261
                                write_count <='0';
262
                                first_word <='0';
263
                                cmd_cnt <= x"00"&data_reg_i(15 downto 8) + 1;  --+2 for direct count write +1
264
                                data_reg_i(15 downto 8)<=(others=>'0');
265
                                CS <= VCIWRs; --go perform a write
266
                        elsif data_reg_i(7 downto 0)=x"E9" then
267
                                write_count <='1';  --no initial command write
268
                                first_word <='0';
269
                                if (data_reg_i(15 downto 8))=x"00" then --64K word write coming
270
                                        cmd_cnt <= (others=>'1'); --64K word count
271
                                else
272
                                        cmd_cnt <= x"00"&data_reg_i(15 downto 8);
273
                                end if;
274
                                data_reg_i(15 downto 8)<=(others=>'0');
275
                                CS <= RESETs;    --PSRAM does not need command                  
276
                        else
277
                                CS <= VCIWRs;
278
                        end if;
279
                else
280
                        if cmd_cnt>x"0000" then
281
                                cmd_cnt<= cmd_cnt - 1;
282
                                if write_count='0' then
283
                                        write_count<='1';
284
                                elsif write_count='1' and  first_word ='0' then
285
                                        first_word <='1';
286
                                elsif write_count='1' and  first_word ='1' then
287
                                        addr_reg <= addr_reg + 1; --autoincrement address in in block mode
288
                                end if;
289
                                --if cmd_cnt>x"02" then --so not to increase too many times on write buffer
290
                                --      addr_reg <= addr_reg + 1; --autoincrement address in in block mode
291
                                --end if;
292
                        end if;
293
                        CS <= VCIWRs;
294
                end if;
295
                when VCIRDs =>          --flash read
296
                        mem_wr <='0';                    --this is VCI write_not_read
297
                        mem_cmd <='0';
298
                        mem_addr <= addr_reg(22 downto 0)&'0'; --translate byte address to word address
299
                        mem_val <= '1';
300
                        if mem_ack='1' then
301
                                data_reg_o <= mem_di;
302
                                mem_wr <='0';                    --this is VCI write_not_read
303
                                mem_cmd <='0';
304
                                mem_val <= '0';
305
                                CS <= TXCMD0s;
306
                        end if;
307
                when VCIWRs =>          --flash write
308
                        mem_addr <= addr_reg(22 downto 0)&'0'; --translate byte address to word address
309
                        if mode(2)='1' then
310
                                --this HW swap removes the need to swap bytes in python for PSRAM region
311
                                mem_do <= data_reg_i(7 downto 0)&data_reg_i(15 downto 8); --SWAP data for PSRAM region
312
                        else
313
                                mem_do <= data_reg_i;   --USB data in will go to mem_out
314
                        end if;
315
                        mem_wr <='1';                   --this is VCI write_not_read
316
                        mem_cmd <='1';
317
                        mem_val <= '1';
318
                        if mem_ack='1' then
319
                                mem_do <= (others=>'Z');
320
                                mem_wr <='0';                    --this is VCI write_not_read
321
                                mem_cmd <='0';
322
                                mem_val <= '0';
323
                                --if write_mode='0' then
324
 
325
                                        if cmd_cnt=x"0000" then --if flash command and not data
326
                                                state_cnt <=(others=>'0'); --init command counter
327
                                                CS <= STS_WAITs;
328
                                        else
329
                                                CS <= RESETs;
330
                                        end if;
331
                                --else  --else if was 0xE8 must read and return XSR
332
                                --      write_mode <='0'; --XSR return will no follow clear this bit
333
                                --      CS <= VCIRDs;
334
                                --end if;
335
                        end if;
336
                when TXCMD0s =>  --transmit over USB what ever is in data_reg_o MSB first
337
 
338
                                if state_cnt="0000" then
339
                                        if usb_txe_nd='0' then
340
                                                usb_wr_d<='1'; -- data is mux'ed by state and data_oe in the beginning of arch
341
                                                state_cnt <= state_cnt + 1;-- now is ok
342
                                        end if;
343
                                elsif state_cnt="0010" then
344
                                    data_oe<='1'; --this is to put data on bus befora falling edge of wr (max 20ns before)
345
                                        state_cnt <= state_cnt + 1;-- now is ok
346
                                elsif state_cnt="0011" then
347
                                    usb_wr_d<='0'; --falling edge performs write  must be high for atleast 50ns
348
                                        state_cnt <= state_cnt + 1;-- now is ok
349
                                elsif state_cnt="0100" then
350
                                        state_cnt <= state_cnt + 1;-- now is ok         
351
                                        data_oe<='0';
352
                                elsif state_cnt="0111" then       --must stay low at least 50ns
353
                                        CS <= TXCMD1s;
354
                                        state_cnt <= (others=>'0');
355
                                else
356
                                        state_cnt <= state_cnt + 1;-- if intermediate cnt then count
357
                                end if;
358
 
359
                when TXCMD1s =>
360
 
361
                                if state_cnt="0000" then
362
                                    if usb_txe_nd='0' then
363
                                                usb_wr_d<='1'; -- data is mux'ed by state and data_oe in the beginning of arch
364
                                                state_cnt <= state_cnt + 1;-- now is ok
365
                                        end if;
366
                                elsif state_cnt="0010" then
367
                                    data_oe<='1'; --this is to put data on bus befora falling edge of wr (max 20ns before)
368
                                        state_cnt <= state_cnt + 1;-- now is ok
369
                                elsif state_cnt="0011" then
370
                                    usb_wr_d<='0'; --falling edge performs write  must be high for atleast 50ns
371
                                        state_cnt <= state_cnt + 1;-- now is ok
372
                                elsif state_cnt="0100" then
373
                                        state_cnt <= state_cnt + 1;-- now is ok         
374
                                        data_oe<='0';
375
                                elsif state_cnt="0111" then       --must stay low at least 50ns
376
                                        if read_mode='0' then
377
                                                CS <= RESETs;
378
                                        elsif cmd_cnt="0000" then --last word sent
379
                                                addr_reg <= addr_reg + 1; --autoincrement address in read mode
380
                                                read_mode <='0';
381
                                                CS <= RESETs;
382
                                        else
383
                                                cmd_cnt<= cmd_cnt - 1;
384
                                                addr_reg <= addr_reg + 1; --autoincrement address in read mode
385
                                                CS <= VCIRDs;   --more data to be read
386
                                        end if;
387
                                        state_cnt <= (others=>'0');
388
                                else
389
                                        state_cnt <= state_cnt + 1;-- if intermediate cnt then count
390
                                end if;
391
                when STS_WAITs =>
392
                                if mem_busy_nd='0' or mode(2)='1' then  --go to RESETs if PSRAM mode is selected
393
                                        CS <= RESETs; --now it's ok to go here
394
                                else
395
                                        state_cnt <= state_cnt + 1;
396
                                        if state_cnt="1111" then
397
                                                --sts cant take longer than 500 ns to go low
398
                                                CS <= RESETs; --time out go to resets anyway
399
                                        end if;
400
                                end if;
401
        when others => null;
402
        end case;
403
  end if;
404
end process;
405
 
406
 
407
 
408
end RTL;
409
 

powered by: WebSVN 2.1.0

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