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

Subversion Repositories simpcon

[/] [simpcon/] [trunk/] [vhdl/] [sc_lego.vhd] - Blame information for rev 29

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 18 martin
--
2 29 martin
--
3
--  This file is a part of JOP, the Java Optimized Processor
4
--
5
--  Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
6
--
7
--  This program is free software: you can redistribute it and/or modify
8
--  it under the terms of the GNU General Public License as published by
9
--  the Free Software Foundation, either version 3 of the License, or
10
--  (at your option) any later version.
11
--
12
--  This program is distributed in the hope that it will be useful,
13
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
--  GNU General Public License for more details.
16
--
17
--  You should have received a copy of the GNU General Public License
18
--  along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
--
20
 
21
 
22
--
23 20 martin
--      sc_lego.vhd
24 18 martin
--
25 20 martin
--      Motor and sensor interface for LEGO MindStorms
26
--      
27
--      Original author: Martin Schoeberl       martin@jopdesign.com
28
--      Author: Peter Hilber                    peter.hilber@student.tuwien.ac.at
29 18 martin
--
30 20 martin
--      address map:
31
--              see read and write processes
32 18 martin
--
33
--
34 20 martin
--      2005-12-22      adapted for SimpCon interface
35
--      2007-03-13      extended for Lego PCB
36 18 martin
--
37 20 martin
--      todo:
38 18 martin
--
39
--
40
 
41 20 martin
 
42 18 martin
--
43 20 martin
--      lego io
44 18 martin
--
45
 
46
library ieee;
47
use ieee.std_logic_1164.all;
48
use ieee.numeric_std.all;
49 20 martin
use work.lego_pld_pack.all;
50
use work.lego_pack.all;
51 18 martin
 
52 20 martin
entity sc_lego is
53
    generic (addr_bits : integer;
54
             clk_freq : integer);
55 18 martin
 
56 20 martin
    port (
57
        clk             : in std_logic;
58
        reset   : in std_logic;
59 18 martin
 
60 20 martin
        -- SimpCon interface
61 18 martin
 
62 20 martin
        address         : in std_logic_vector(addr_bits-1 downto 0);
63
        wr_data         : in std_logic_vector(31 downto 0);
64
        rd, wr          : in std_logic;
65
        rd_data         : out std_logic_vector(31 downto 0);
66
        rdy_cnt         : out unsigned(1 downto 0);
67
 
68
                -- speaker
69
 
70
                speaker : out std_logic;
71
 
72
        -- motor stuff
73 18 martin
 
74 20 martin
        m0en : out std_logic;
75
        m0dir : out std_logic;
76
        m0break : out std_logic;
77
        m0dia : in std_logic;
78
        m0doa : out std_logic;
79
        m0dib : in std_logic;
80
        m0dob : out std_logic;
81 18 martin
 
82 20 martin
        m1en : out std_logic;
83
        m1dir : out std_logic;
84
        m1break : out std_logic;
85
        m1dia : in std_logic;
86
        m1doa : out std_logic;
87
        m1dib : in std_logic;
88
        m1dob : out std_logic;
89 18 martin
 
90 20 martin
        m2en : out std_logic;
91
        m2dir : out std_logic;
92
        m2break : out std_logic;
93 18 martin
 
94 20 martin
        -- sensor stuff
95
 
96
        s0di : in std_logic;
97
        s0do : out std_logic;
98
        s0pi : out std_logic;
99
        s1di : in std_logic;
100
        s1do : out std_logic;
101
        s1pi : out std_logic;
102
        s2di : in std_logic;
103
        s2do : out std_logic;
104
        s2pi : out std_logic;
105 18 martin
 
106 20 martin
        mic1do : out std_logic;
107
        mic1 : in std_logic;
108
 
109 18 martin
 
110 20 martin
                -- pld
111
                pld_strobe              : out std_logic;
112
                pld_data                : inout std_logic;
113
                pld_clk                 : out std_logic
114 18 martin
 
115 20 martin
        );
116
end sc_lego;
117 18 martin
 
118 20 martin
architecture rtl of sc_lego is
119
    -- settings for components
120
    constant adc_width               : integer := 9;
121 18 martin
 
122 20 martin
    -- settings for motor
123
    constant motor_dout_width : integer := 9;
124
    constant duty_cycle_width        : integer := 14;
125
 
126
    constant ld_ratio_measure_to_pwm : integer := 4;   -- ld(bit width time/bit width time spent measuring)
127
    constant clkint_prescaler_width  : integer := 18;
128
    constant counter_width           : integer := clkint_prescaler_width + ld_ratio_measure_to_pwm + 1;
129
    constant clksd_prescaler_width   : integer := clkint_prescaler_width - motor_dout_width;
130 18 martin
 
131 20 martin
 
132
        constant audio_input_width : integer := 8;
133 18 martin
 
134
 
135 20 martin
        -- pld  
136
 
137
    signal pld_out_pins : FORWARDED_PINS;
138
    signal pld_in_pins  : FORWARDED_PINS;
139 18 martin
 
140 20 martin
        -- signals
141
 
142
        signal sensor0_dout: std_logic_vector(adc_width-1 downto 0);
143
        signal sensor1_dout: std_logic_vector(adc_width-1 downto 0);
144
        signal sensor2_dout: std_logic_vector(adc_width-1 downto 0);
145 18 martin
 
146 20 martin
        -- motors
147
 
148
    signal motor0_state:                lego_motor_state;
149
    signal motor0_duty_cycle:   unsigned(duty_cycle_width-1 downto 0);
150
    signal motor0_measure:      std_logic;
151 18 martin
 
152 20 martin
        signal motor0_dout1:    std_logic_vector(motor_dout_width-1 downto 0);
153
        signal motor0_dout2:    std_logic_vector(motor_dout_width-1 downto 0);
154
 
155
        signal motor1_state:            lego_motor_state;
156
    signal motor1_duty_cycle:   unsigned(duty_cycle_width-1 downto 0);
157
    signal motor1_measure:      std_logic;
158 18 martin
 
159 20 martin
        signal motor1_dout1:    std_logic_vector(motor_dout_width-1 downto 0);
160
        signal motor1_dout2:    std_logic_vector(motor_dout_width-1 downto 0);
161
 
162
        signal motor2_state:            lego_motor_state;
163
    signal motor2_duty_cycle:   unsigned(duty_cycle_width-1 downto 0);
164
    signal motor2_measure:      std_logic;
165 18 martin
 
166 20 martin
        signal motor1_buf_bemf:         std_logic_vector(motor_dout_width*2-1 downto 0);
167 18 martin
 
168 20 martin
        -- microphone
169 18 martin
 
170 20 martin
        signal micro_dout:                      std_logic_vector(adc_width-1 downto 0);
171
 
172
        signal cmp_micro_counter: unsigned(clkint_prescaler_width-1 downto 0);
173
        signal cmp_micro_clksd: std_logic;
174
        signal cmp_micro_clkint: std_logic;
175
 
176
        -- speaker
177
 
178
        signal audio_input:                     std_logic_vector(audio_input_width-1 downto 0);
179 18 martin
begin
180
 
181 20 martin
    rdy_cnt <= "00";    -- no wait states
182 18 martin
 
183
--
184
--      The registered MUX is all we need for a SimpCon read.
185
--      The read data is stored in registered rd_data.
186
--
187 20 martin
    read: process(clk, reset)
188
    begin
189 18 martin
 
190 20 martin
        if (reset='1') then
191
            rd_data <= (others => '0');
192
        elsif rising_edge(clk) then
193 18 martin
 
194 20 martin
            if rd='1' then
195
                                rd_data <= (others => '0');
196
                -- that's our very simple address decoder
197
                case address(3 downto 0) is
198
                                        -- sensors
199
                                        when "0000" =>
200
                                                rd_data(adc_width*3-1 downto 0) <= sensor2_dout & sensor1_dout & sensor0_dout;
201
                                        -- microphone
202
                                        when "0001" =>
203
                                                rd_data(adc_width-1 downto 0) <= micro_dout;
204
                                        -- motor 0 back-emf
205
                                        when "0010" =>
206
                                                rd_data(motor_dout_width*2-1 downto 0) <= motor0_dout2 & motor0_dout1;
207
                                        -- motor 1 back-emf
208
                                        when "0011" =>
209
                                                rd_data(motor_dout_width*2-1 downto 0) <= motor1_dout2 & motor1_dout1;
210
                                        -- buttons
211
                                        when "0100" =>
212
                                                rd_data(3 downto 0) <= pld_in_pins(btn3) & pld_in_pins(btn2) & pld_in_pins(btn1) & pld_in_pins(btn0);
213
                                        -- digital inputs
214
                                        when "0101" =>
215
                                                rd_data(2 downto 0) <= pld_in_pins(i2) & pld_in_pins(i1) & pld_in_pins(i0);
216
                                        -- for future use
217
                                        when "0110" =>
218
                                                rd_data(9 downto 0) <= pld_in_pins(unused9) & pld_in_pins(unused8) & pld_in_pins(unused7) &
219
                                                                                                pld_in_pins(unused6) & pld_in_pins(unused5) & pld_in_pins(unused4) &
220
                                                                                                pld_in_pins(unused3) & pld_in_pins(unused2) & pld_in_pins(unused1) &
221
                                                                                                pld_in_pins(unused0);
222
                                        -- pld raw input
223
                                        when "0111" =>
224
                                                rd_data(20 downto 0) <= pld_in_pins;
225
                                        -- motor 0 back-emf
226
                                        when "1000" =>
227
                                                rd_data(motor_dout_width*2-1 downto 0) <= motor0_dout2 & motor0_dout1;
228
                                                motor1_buf_bemf <= motor1_dout2 & motor1_dout1;
229
                                        -- motor 1 back-emf
230
                                        when "1001" =>
231
                                                rd_data(motor_dout_width*2-1 downto 0) <= motor1_buf_bemf;
232
                        when others =>
233
                end case;
234
            end if;
235
        end if;
236 18 martin
 
237 20 martin
    end process;
238 18 martin
 
239
 
240
--
241
--      SimpCon write is very simple
242
--
243 20 martin
    write: process(clk, reset)
244 18 martin
 
245 20 martin
    begin
246 18 martin
 
247 20 martin
        if (reset='1') then
248
                        pld_out_pins <= (others => '0');
249 18 martin
 
250 20 martin
            motor0_state      <= LEGO_MOTOR_STATE_OFF;
251
            motor0_duty_cycle <= (others => '0');
252
            motor0_measure    <= '0';
253 18 martin
 
254 20 martin
            motor1_state      <= LEGO_MOTOR_STATE_OFF;
255
            motor1_duty_cycle <= (others => '0');
256
            motor1_measure    <= '0';
257 18 martin
 
258 20 martin
            motor2_state      <= LEGO_MOTOR_STATE_OFF;
259
            motor2_duty_cycle <= (others => '0');
260
                        motor2_measure    <= '0';
261 18 martin
 
262 20 martin
        elsif rising_edge(clk) then
263 18 martin
 
264 20 martin
            if wr='1' then
265 18 martin
 
266 20 martin
                                case address(2 downto 0) is
267
                                    -- leds
268
                                        when "000" =>
269
                                                pld_out_pins(led0) <= wr_data(0);
270
                                                pld_out_pins(led1) <= wr_data(1);
271
                                                pld_out_pins(led2) <= wr_data(2);
272
                                                pld_out_pins(led3) <= wr_data(3);
273
                                        -- motor 0
274
                                        when "001" =>
275
                                                motor0_state <= lego_motor_state(wr_data(lego_motor_state'high downto 0));
276
                                                motor0_duty_cycle <= unsigned(wr_data(lego_motor_state'high+1+(duty_cycle_width-1) downto lego_motor_state'high+1));
277
                                                motor0_measure <= wr_data((duty_cycle_width-1)+lego_motor_state'high+2);
278
                                        -- motor 1
279
                                        when "010" =>
280
                                                motor1_state <= lego_motor_state(wr_data(lego_motor_state'high downto 0));
281
                                                motor1_duty_cycle <= unsigned(wr_data(lego_motor_state'high+1+(duty_cycle_width-1) downto lego_motor_state'high+1));
282
                                                motor1_measure <= wr_data((duty_cycle_width-1)+lego_motor_state'high+2);
283
                                        -- motor 2
284
                                        when "011" =>
285
                                                motor2_state <= lego_motor_state(wr_data(lego_motor_state'high downto 0));
286
                                                motor2_duty_cycle <= unsigned(wr_data(lego_motor_state'high+1+(duty_cycle_width-1) downto lego_motor_state'high+1));
287
                                                -- no actual back-emf measurement available
288
                                                motor2_measure <= wr_data((duty_cycle_width-1)+lego_motor_state'high+2);
289
                                        -- for future use
290
                                        when "110" =>
291
                                                pld_out_pins(unused9) <= wr_data(9);
292
                                                pld_out_pins(unused8) <= wr_data(8);
293
                                                pld_out_pins(unused7) <= wr_data(7);
294
                                                pld_out_pins(unused6) <= wr_data(6);
295
                                                pld_out_pins(unused5) <= wr_data(5);
296
                                                pld_out_pins(unused4) <= wr_data(4);
297
                                                pld_out_pins(unused3) <= wr_data(3);
298
                                                pld_out_pins(unused2) <= wr_data(2);
299
                                                pld_out_pins(unused1) <= wr_data(1);
300
                                                pld_out_pins(unused0) <= wr_data(0);
301
                                                pld_out_pins(10 downto 4) <= "0000000";
302
                                        when "111" =>
303
                                                audio_input <= wr_data(audio_input_width-1 downto 0);
304
                                        when others =>
305
                                                null;
306
                                end case;
307
            end if;
308 18 martin
 
309 20 martin
        end if;
310 18 martin
 
311 20 martin
    end process;
312
 
313
 
314
    cmp_pld_interface: entity work.pld_interface
315
        port map(
316
            clk => clk,
317
            reset => reset,
318
            out_pins => pld_out_pins,
319
            in_pins => pld_in_pins,
320
            pld_strobe => pld_strobe,
321
            pld_clk => pld_clk,
322
            data => pld_data);
323
 
324
        cmp_sensor0: entity work.lesens generic map (
325
        clk_freq => clk_freq
326
        )
327 18 martin
                port map(
328
                        clk => clk,
329 20 martin
                reset => reset,
330
                        dout => sensor0_dout,
331
                        sp => s0pi,
332
                sdi => s0di,
333
                        sdo => s0do);
334 18 martin
 
335 20 martin
        cmp_sensor1: entity work.lesens generic map (
336
        clk_freq => clk_freq
337
        )
338
                port map(
339
                        clk => clk,
340
                reset => reset,
341
                        dout => sensor1_dout,
342
                        sp => s1pi,
343
                sdi => s1di,
344
                        sdo => s1do);
345
 
346
        cmp_sensor2: entity work.lesens generic map (
347
        clk_freq => clk_freq
348
        )
349
                port map(
350
                        clk => clk,
351
                reset => reset,
352
                        dout => sensor2_dout,
353
                        sp => s2pi,
354
                sdi => s2di,
355
                        sdo => s2do);
356
 
357
        cmp_motor0: entity work.lego_motor
358
        generic map (
359
            duty_cycle_width        => duty_cycle_width,
360
            counter_width           => counter_width,
361
            ld_ratio_measure_to_pwm => ld_ratio_measure_to_pwm,
362
            clksd_prescaler_width   => clksd_prescaler_width,
363
            clkint_prescaler_width  => clkint_prescaler_width,
364
            dout_width              => motor_dout_width)
365
        port map (
366
            clk                     => clk,
367
            reset                   => reset,
368
            state                   => motor0_state,
369
            duty_cycle              => motor0_duty_cycle,
370
            measure                 => motor0_measure,
371
            dout_1                  => motor0_dout1,
372
            dout_2                                      => motor0_dout2,
373
            men                     => m0en,
374
                        mdir                                    => m0dir,
375
                        mbreak                                  => m0break,
376
            mdia                    => m0dia,
377
            mdoa                    => m0doa,
378
            mdib                    => m0dib,
379
            mdob                    => m0dob);
380 18 martin
 
381 20 martin
        cmp_motor1: entity work.lego_motor
382
        generic map (
383
            duty_cycle_width        => duty_cycle_width,
384
            counter_width           => counter_width,
385
            ld_ratio_measure_to_pwm => ld_ratio_measure_to_pwm,
386
            clksd_prescaler_width   => clksd_prescaler_width,
387
            clkint_prescaler_width  => clkint_prescaler_width,
388
            dout_width              => motor_dout_width)
389
        port map (
390
            clk                     => clk,
391
            reset                   => reset,
392
            state                   => motor1_state,
393
            duty_cycle              => motor1_duty_cycle,
394
            measure                 => motor1_measure,
395
            dout_1                  => motor1_dout1,
396
            dout_2                                      => motor1_dout2,
397
            men                     => m1en,
398
                        mdir                                    => m1dir,
399
                        mbreak                                  => m1break,
400
            mdia                    => m1dia,
401
            mdoa                    => m1doa,
402
            mdib                    => m1dib,
403
            mdob                    => m1dob);
404 18 martin
 
405 20 martin
        -- no back-emf measurement available for this motor due to lack of pins :(
406
        cmp_motor2: entity work.lego_motor
407
        generic map (
408
            duty_cycle_width        => duty_cycle_width,
409
            counter_width           => counter_width,
410
            ld_ratio_measure_to_pwm => ld_ratio_measure_to_pwm,
411
            clksd_prescaler_width   => clksd_prescaler_width,
412
            clkint_prescaler_width  => clkint_prescaler_width,
413
            dout_width              => motor_dout_width)
414
        port map (
415
            clk                     => clk,
416
            reset                   => reset,
417
            state                   => motor2_state,
418
            duty_cycle              => motor2_duty_cycle,
419
            measure                 => motor2_measure,
420
            --dout_1                => motor2_dout1,
421
            --dout_2                            => motor2_dout2,
422
            men                     => m2en,
423
                        mdir                                    => m2dir,
424
                        mbreak                                  => m2break,
425
            mdia                        => '0',
426
            --mdoa                  => m2doa,
427
            mdib                        => '0'
428
            --mdob                  => m2dob
429
                        );
430
 
431
        -- XXX
432
        cmp_micro_count: process(clk, reset)
433
        begin
434
        if reset = '1' then
435
                cmp_micro_counter <= (others => '0');
436
        elsif rising_edge(clk) then
437
                cmp_micro_counter <= cmp_micro_counter + 1;
438
        end if;
439
        end process;
440
 
441
        cmp_micro_clksd <= '1' when (cmp_micro_counter(clksd_prescaler_width-1 downto 0) = 0) else '0';
442
        cmp_micro_clkint <= '1' when (cmp_micro_counter(clkint_prescaler_width-1 downto 0) = 0) else '0';
443
 
444
        cmp_micro: entity work.sigma_delta
445
    generic map (
446
      dout_width => adc_width)
447
    port map (
448
      clk    => clk,
449
      reset  => reset,
450
      clksd  => cmp_micro_clksd,
451
      clkint => cmp_micro_clkint,
452
      dout   => micro_dout,
453
      sdi    => mic1,
454
      sdo    => mic1do);
455
 
456
        cmp_audio: entity work.audio
457
        generic map (
458
                input_width => audio_input_width)
459
        port map (
460
                clk => clk,
461
                reset => reset,
462
                input => audio_input,
463
                output => speaker);
464
 
465 18 martin
end rtl;

powered by: WebSVN 2.1.0

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