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

Subversion Repositories simpcon

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 19 to Rev 20
    Reverse comparison

Rev 19 → Rev 20

/trunk/vhdl/scio_min.vhd
37,7 → 37,7
use work.jop_config.all;
 
entity scio is
 
generic (cpu_id : integer := 0);
port (
clk : in std_logic;
reset : in std_logic;
54,6 → 54,11
irq_in : out irq_in_type;
exc_req : in exception_type;
 
-- CMP
 
sync_out : in sync_out_type := NO_SYNC;
sync_in : out sync_in_type;
-- serial interface
 
txd : out std_logic;
76,7 → 81,7
 
architecture rtl of scio is
 
constant SLAVE_CNT : integer := 2;
constant SLAVE_CNT : integer := 3;
-- SLAVE_CNT <= 2**DECODE_BITS
-- take care of USB address 0x20!
constant DECODE_BITS : integer := 2;
112,6 → 117,10
sc_io_in.rd_data <= sc_dout(sel_reg);
sc_io_in.rdy_cnt <= sc_rdy_cnt(sel_reg);
 
-- default for unused USB device
sc_dout(2) <= (others => '0');
sc_rdy_cnt(2) <= (others => '0');
 
--
-- Connect SLAVE_CNT simple test slaves
--
136,9 → 145,10
end if;
end process;
cmp_cnt: entity work.sc_cnt generic map (
cmp_sys: entity work.sc_sys generic map (
addr_bits => SLAVE_ADDR_BITS,
clk_freq => clk_freq
clk_freq => clk_freq,
cpu_id => cpu_id
)
port map(
clk => clk,
154,6 → 164,9
irq_in => irq_in,
exc_req => exc_req,
sync_out => sync_out,
sync_in => sync_in,
wd => wd
);
 
/trunk/vhdl/sc_pack.vhd
33,10 → 33,13
rd : std_logic;
wr : std_logic;
end record;
 
type sc_in_type is record
rd_data : std_logic_vector(31 downto 0);
rdy_cnt : unsigned(RDY_CNT_SIZE-1 downto 0);
end record;
 
type sc_io_out_array_type is array (integer range <>) of sc_io_out_type;
type sc_in_array_type is array (integer range <>) of sc_in_type;
end sc_pack;
/trunk/vhdl/sc_cnt.vhd
200,9 → 200,17
irq_in.exc_int <= '0';
 
if exc_req.spov='1' then
exc_type(0) <= '1';
exc_type(2 downto 0) <= EXC_SPOV;
irq_in.exc_int <= '1';
end if;
if exc_req.np='1' then
exc_type(2 downto 0) <= EXC_NP;
irq_in.exc_int <= '1';
end if;
if exc_req.ab='1' then
exc_type(2 downto 0) <= EXC_AB;
irq_in.exc_int <= '1';
end if;
 
if wr='1' then
case address(2 downto 0) is
/trunk/vhdl/sc_lego.vhd
1,304 → 1,444
--
-- sc_lego.vhd
-- sc_lego.vhd
--
-- Motor and sensor interface for LEGO MindStorms
--
-- Author: Martin Schoeberl martin@jopdesign.com
-- Motor and sensor interface for LEGO MindStorms
--
-- Original author: Martin Schoeberl martin@jopdesign.com
-- Author: Peter Hilber peter.hilber@student.tuwien.ac.at
--
-- address map:
-- address map:
-- see read and write processes
--
-- 0 motor output, sensor input
-- 1 not used
-- 2 not used
-- 3 not used
--
-- 2005-12-22 adapted for SimpCon interface
-- 2005-12-22 adapted for SimpCon interface
-- 2007-03-13 extended for Lego PCB
--
-- todo:
-- todo:
--
--
 
 
--
-- lesens
-- lego io
--
-- sigma delta AD converter and power switch
-- for the LEGO sensor.
--
 
 
-- TODO: write a general sigma delta ADC
-- But this one is special as the senso gets powered!
--
 
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.lego_pld_pack.all;
use work.lego_pack.all;
 
entity lesens is
entity sc_lego is
generic (addr_bits : integer;
clk_freq : integer);
 
generic (clk_freq : integer);
port (
clk : in std_logic;
reset : in std_logic;
port (
clk : in std_logic;
reset : in std_logic;
 
dout : out std_logic_vector(8 downto 0);
-- SimpCon interface
 
sp : out std_logic;
sdi : in std_logic;
sdo : out std_logic
);
end lesens ;
address : in std_logic_vector(addr_bits-1 downto 0);
wr_data : in std_logic_vector(31 downto 0);
rd, wr : in std_logic;
rd_data : out std_logic_vector(31 downto 0);
rdy_cnt : out unsigned(1 downto 0);
-- speaker
speaker : out std_logic;
-- motor stuff
 
architecture rtl of lesens is
m0en : out std_logic;
m0dir : out std_logic;
m0break : out std_logic;
m0dia : in std_logic;
m0doa : out std_logic;
m0dib : in std_logic;
m0dob : out std_logic;
 
signal clkint : unsigned(8 downto 0); -- 9 bit ADC
signal val : unsigned(8 downto 0);
m1en : out std_logic;
m1dir : out std_logic;
m1break : out std_logic;
m1dia : in std_logic;
m1doa : out std_logic;
m1dib : in std_logic;
m1dob : out std_logic;
 
signal rx_d : std_logic;
signal serdata : std_logic;
m2en : out std_logic;
m2dir : out std_logic;
m2break : out std_logic;
 
signal spike : std_logic_vector(2 downto 0); -- sync in, filter
-- sensor stuff
s0di : in std_logic;
s0do : out std_logic;
s0pi : out std_logic;
s1di : in std_logic;
s1do : out std_logic;
s1pi : out std_logic;
s2di : in std_logic;
s2do : out std_logic;
s2pi : out std_logic;
 
signal pow_cnt : unsigned(2 downto 0);
mic1do : out std_logic;
mic1 : in std_logic;
 
signal clksd : std_logic;
signal prescale : unsigned(7 downto 0);
constant sd_clk_cnt : integer := ((clk_freq+1000000)/2000000)-1;
-- pld
pld_strobe : out std_logic;
pld_data : inout std_logic;
pld_clk : out std_logic
 
begin
);
end sc_lego;
 
architecture rtl of sc_lego is
-- settings for components
constant adc_width : integer := 9;
 
--
-- power switch for sensor
--
process(pow_cnt)
-- settings for motor
constant motor_dout_width : integer := 9;
constant duty_cycle_width : integer := 14;
constant ld_ratio_measure_to_pwm : integer := 4; -- ld(bit width time/bit width time spent measuring)
constant clkint_prescaler_width : integer := 18;
constant counter_width : integer := clkint_prescaler_width + ld_ratio_measure_to_pwm + 1;
constant clksd_prescaler_width : integer := clkint_prescaler_width - motor_dout_width;
 
begin
sp <= '1';
if pow_cnt=0 or pow_cnt=1 then
sp <= '0';
end if;
end process;
constant audio_input_width : integer := 8;
 
sdo <= serdata;
 
--
-- prescaler (2 MHz clock)
--
process(clk, reset)
-- pld
signal pld_out_pins : FORWARDED_PINS;
signal pld_in_pins : FORWARDED_PINS;
 
begin
if (reset='1') then
prescale <= (others => '0');
clksd <= '0';
elsif rising_edge(clk) then
clksd <= '0';
prescale <= prescale + 1;
if prescale = sd_clk_cnt then
prescale <= (others => '0');
clksd <= '1';
end if;
end if;
-- signals
signal sensor0_dout: std_logic_vector(adc_width-1 downto 0);
signal sensor1_dout: std_logic_vector(adc_width-1 downto 0);
signal sensor2_dout: std_logic_vector(adc_width-1 downto 0);
 
end process;
-- motors
signal motor0_state: lego_motor_state;
signal motor0_duty_cycle: unsigned(duty_cycle_width-1 downto 0);
signal motor0_measure: std_logic;
 
--
-- sigma delta converter
--
process(clk, reset)
signal motor0_dout1: std_logic_vector(motor_dout_width-1 downto 0);
signal motor0_dout2: std_logic_vector(motor_dout_width-1 downto 0);
signal motor1_state: lego_motor_state;
signal motor1_duty_cycle: unsigned(duty_cycle_width-1 downto 0);
signal motor1_measure: std_logic;
 
begin
if (reset='1') then
spike <= "000";
dout <= (others => '0');
val <= (others => '0');
clkint <= (others => '0');
serdata <= '0';
pow_cnt <= (others => '0');
signal motor1_dout1: std_logic_vector(motor_dout_width-1 downto 0);
signal motor1_dout2: std_logic_vector(motor_dout_width-1 downto 0);
signal motor2_state: lego_motor_state;
signal motor2_duty_cycle: unsigned(duty_cycle_width-1 downto 0);
signal motor2_measure: std_logic;
 
elsif rising_edge(clk) then
signal motor1_buf_bemf: std_logic_vector(motor_dout_width*2-1 downto 0);
 
if clksd='1' then
-- microphone
 
--
-- delay
--
spike(0) <= sdi;
spike(2 downto 1) <= spike(1 downto 0);
serdata <= rx_d; -- no inverter, using an invert. comperator
 
--
-- integrate
--
 
if serdata='0' then -- 'invert' value
val <= val+1;
end if;
 
if clkint=0 then -- 256 us
if pow_cnt=1 then
dout <= std_logic_vector(val);
end if;
val <= (others => '0');
pow_cnt <= pow_cnt + 1;
end if;
 
clkint <= clkint+1; -- free running counter
 
end if;
 
end if;
 
end process;
 
 
--
-- filter input
--
with spike select
rx_d <= '0' when "000",
'0' when "001",
'0' when "010",
'1' when "011",
'0' when "100",
'1' when "101",
'1' when "110",
'1' when "111",
'X' when others;
end rtl;
 
 
--
-- lego io
--
 
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity sc_lego is
generic (addr_bits : integer;
clk_freq : integer);
 
port (
clk : in std_logic;
reset : in std_logic;
 
-- SimpCon interface
 
address : in std_logic_vector(addr_bits-1 downto 0);
wr_data : in std_logic_vector(31 downto 0);
rd, wr : in std_logic;
rd_data : out std_logic_vector(31 downto 0);
rdy_cnt : out unsigned(1 downto 0);
 
-- motor stuff
 
ma_en : out std_logic;
ma_l1 : out std_logic;
ma_l2 : out std_logic;
ma_l1_sdi : in std_logic;
ma_l1_sdo : out std_logic;
ma_l2_sdi : in std_logic;
ma_l2_sdo : out std_logic;
 
mb_en : out std_logic;
mb_l1 : out std_logic;
mb_l2 : out std_logic;
 
-- sensor stuff
 
s1_pow : out std_logic;
s1_sdi : in std_logic;
s1_sdo : out std_logic
 
);
end sc_lego;
 
architecture rtl of sc_lego is
 
signal m_out : std_logic_vector(5 downto 0);
signal sensor : std_logic_vector(8 downto 0);
 
signal xyz : std_logic_vector(31 downto 0);
 
signal micro_dout: std_logic_vector(adc_width-1 downto 0);
signal cmp_micro_counter: unsigned(clkint_prescaler_width-1 downto 0);
signal cmp_micro_clksd: std_logic;
signal cmp_micro_clkint: std_logic;
-- speaker
signal audio_input: std_logic_vector(audio_input_width-1 downto 0);
begin
 
rdy_cnt <= "00"; -- no wait states
rdy_cnt <= "00"; -- no wait states
 
--
-- The registered MUX is all we need for a SimpCon read.
-- The read data is stored in registered rd_data.
--
process(clk, reset)
begin
read: process(clk, reset)
begin
 
if (reset='1') then
rd_data <= (others => '0');
elsif rising_edge(clk) then
if (reset='1') then
rd_data <= (others => '0');
elsif rising_edge(clk) then
 
if rd='1' then
-- that's our very simple address decoder
if address(0)='0' then
rd_data(8 downto 0) <= sensor;
rd_data(31 downto 9) <= (others => '0');
else
rd_data <= xyz;
end if;
end if;
end if;
if rd='1' then
rd_data <= (others => '0');
-- that's our very simple address decoder
case address(3 downto 0) is
-- sensors
when "0000" =>
rd_data(adc_width*3-1 downto 0) <= sensor2_dout & sensor1_dout & sensor0_dout;
-- microphone
when "0001" =>
rd_data(adc_width-1 downto 0) <= micro_dout;
-- motor 0 back-emf
when "0010" =>
rd_data(motor_dout_width*2-1 downto 0) <= motor0_dout2 & motor0_dout1;
-- motor 1 back-emf
when "0011" =>
rd_data(motor_dout_width*2-1 downto 0) <= motor1_dout2 & motor1_dout1;
-- buttons
when "0100" =>
rd_data(3 downto 0) <= pld_in_pins(btn3) & pld_in_pins(btn2) & pld_in_pins(btn1) & pld_in_pins(btn0);
-- digital inputs
when "0101" =>
rd_data(2 downto 0) <= pld_in_pins(i2) & pld_in_pins(i1) & pld_in_pins(i0);
-- for future use
when "0110" =>
rd_data(9 downto 0) <= pld_in_pins(unused9) & pld_in_pins(unused8) & pld_in_pins(unused7) &
pld_in_pins(unused6) & pld_in_pins(unused5) & pld_in_pins(unused4) &
pld_in_pins(unused3) & pld_in_pins(unused2) & pld_in_pins(unused1) &
pld_in_pins(unused0);
-- pld raw input
when "0111" =>
rd_data(20 downto 0) <= pld_in_pins;
-- motor 0 back-emf
when "1000" =>
rd_data(motor_dout_width*2-1 downto 0) <= motor0_dout2 & motor0_dout1;
motor1_buf_bemf <= motor1_dout2 & motor1_dout1;
-- motor 1 back-emf
when "1001" =>
rd_data(motor_dout_width*2-1 downto 0) <= motor1_buf_bemf;
when others =>
end case;
end if;
end if;
 
end process;
end process;
 
 
--
-- SimpCon write is very simple
--
process(clk, reset)
write: process(clk, reset)
 
begin
begin
 
if (reset='1') then
xyz <= (others => '0');
if (reset='1') then
pld_out_pins <= (others => '0');
 
m_out <= (others => '0');
motor0_state <= LEGO_MOTOR_STATE_OFF;
motor0_duty_cycle <= (others => '0');
motor0_measure <= '0';
 
elsif rising_edge(clk) then
motor1_state <= LEGO_MOTOR_STATE_OFF;
motor1_duty_cycle <= (others => '0');
motor1_measure <= '0';
 
if wr='1' then
xyz <= wr_data;
m_out <= wr_data(5 downto 0);
end if;
motor2_state <= LEGO_MOTOR_STATE_OFF;
motor2_duty_cycle <= (others => '0');
motor2_measure <= '0';
 
end if;
elsif rising_edge(clk) then
 
end process;
if wr='1' then
 
-- simple motor out
mb_en <= m_out(5);
mb_l1 <= m_out(4);
mb_l2 <= m_out(3);
ma_en <= m_out(2);
ma_l1 <= m_out(1);
ma_l2 <= m_out(0);
case address(2 downto 0) is
-- leds
when "000" =>
pld_out_pins(led0) <= wr_data(0);
pld_out_pins(led1) <= wr_data(1);
pld_out_pins(led2) <= wr_data(2);
pld_out_pins(led3) <= wr_data(3);
-- motor 0
when "001" =>
motor0_state <= lego_motor_state(wr_data(lego_motor_state'high downto 0));
motor0_duty_cycle <= unsigned(wr_data(lego_motor_state'high+1+(duty_cycle_width-1) downto lego_motor_state'high+1));
motor0_measure <= wr_data((duty_cycle_width-1)+lego_motor_state'high+2);
-- motor 1
when "010" =>
motor1_state <= lego_motor_state(wr_data(lego_motor_state'high downto 0));
motor1_duty_cycle <= unsigned(wr_data(lego_motor_state'high+1+(duty_cycle_width-1) downto lego_motor_state'high+1));
motor1_measure <= wr_data((duty_cycle_width-1)+lego_motor_state'high+2);
-- motor 2
when "011" =>
motor2_state <= lego_motor_state(wr_data(lego_motor_state'high downto 0));
motor2_duty_cycle <= unsigned(wr_data(lego_motor_state'high+1+(duty_cycle_width-1) downto lego_motor_state'high+1));
-- no actual back-emf measurement available
motor2_measure <= wr_data((duty_cycle_width-1)+lego_motor_state'high+2);
-- for future use
when "110" =>
pld_out_pins(unused9) <= wr_data(9);
pld_out_pins(unused8) <= wr_data(8);
pld_out_pins(unused7) <= wr_data(7);
pld_out_pins(unused6) <= wr_data(6);
pld_out_pins(unused5) <= wr_data(5);
pld_out_pins(unused4) <= wr_data(4);
pld_out_pins(unused3) <= wr_data(3);
pld_out_pins(unused2) <= wr_data(2);
pld_out_pins(unused1) <= wr_data(1);
pld_out_pins(unused0) <= wr_data(0);
pld_out_pins(10 downto 4) <= "0000000";
when "111" =>
audio_input <= wr_data(audio_input_width-1 downto 0);
when others =>
null;
end case;
end if;
 
ma_l1_sdo <= '0';
ma_l2_sdo <= '0';
end if;
 
-- sensor adc
cmp_sens: entity work.lesens generic map (
clk_freq => clk_freq
)
end process;
 
cmp_pld_interface: entity work.pld_interface
port map(
clk => clk,
reset => reset,
out_pins => pld_out_pins,
in_pins => pld_in_pins,
pld_strobe => pld_strobe,
pld_clk => pld_clk,
data => pld_data);
 
cmp_sensor0: entity work.lesens generic map (
clk_freq => clk_freq
)
port map(
clk => clk,
reset => reset,
reset => reset,
dout => sensor0_dout,
sp => s0pi,
sdi => s0di,
sdo => s0do);
 
dout => sensor,
cmp_sensor1: entity work.lesens generic map (
clk_freq => clk_freq
)
port map(
clk => clk,
reset => reset,
dout => sensor1_dout,
sp => s1pi,
sdi => s1di,
sdo => s1do);
cmp_sensor2: entity work.lesens generic map (
clk_freq => clk_freq
)
port map(
clk => clk,
reset => reset,
dout => sensor2_dout,
sp => s2pi,
sdi => s2di,
sdo => s2do);
cmp_motor0: entity work.lego_motor
generic map (
duty_cycle_width => duty_cycle_width,
counter_width => counter_width,
ld_ratio_measure_to_pwm => ld_ratio_measure_to_pwm,
clksd_prescaler_width => clksd_prescaler_width,
clkint_prescaler_width => clkint_prescaler_width,
dout_width => motor_dout_width)
port map (
clk => clk,
reset => reset,
state => motor0_state,
duty_cycle => motor0_duty_cycle,
measure => motor0_measure,
dout_1 => motor0_dout1,
dout_2 => motor0_dout2,
men => m0en,
mdir => m0dir,
mbreak => m0break,
mdia => m0dia,
mdoa => m0doa,
mdib => m0dib,
mdob => m0dob);
 
sp => s1_pow,
sdi => s1_sdi,
sdo => s1_sdo
);
cmp_motor1: entity work.lego_motor
generic map (
duty_cycle_width => duty_cycle_width,
counter_width => counter_width,
ld_ratio_measure_to_pwm => ld_ratio_measure_to_pwm,
clksd_prescaler_width => clksd_prescaler_width,
clkint_prescaler_width => clkint_prescaler_width,
dout_width => motor_dout_width)
port map (
clk => clk,
reset => reset,
state => motor1_state,
duty_cycle => motor1_duty_cycle,
measure => motor1_measure,
dout_1 => motor1_dout1,
dout_2 => motor1_dout2,
men => m1en,
mdir => m1dir,
mbreak => m1break,
mdia => m1dia,
mdoa => m1doa,
mdib => m1dib,
mdob => m1dob);
 
-- no back-emf measurement available for this motor due to lack of pins :(
cmp_motor2: entity work.lego_motor
generic map (
duty_cycle_width => duty_cycle_width,
counter_width => counter_width,
ld_ratio_measure_to_pwm => ld_ratio_measure_to_pwm,
clksd_prescaler_width => clksd_prescaler_width,
clkint_prescaler_width => clkint_prescaler_width,
dout_width => motor_dout_width)
port map (
clk => clk,
reset => reset,
state => motor2_state,
duty_cycle => motor2_duty_cycle,
measure => motor2_measure,
--dout_1 => motor2_dout1,
--dout_2 => motor2_dout2,
men => m2en,
mdir => m2dir,
mbreak => m2break,
mdia => '0',
--mdoa => m2doa,
mdib => '0'
--mdob => m2dob
);
-- XXX
cmp_micro_count: process(clk, reset)
begin
if reset = '1' then
cmp_micro_counter <= (others => '0');
elsif rising_edge(clk) then
cmp_micro_counter <= cmp_micro_counter + 1;
end if;
end process;
 
cmp_micro_clksd <= '1' when (cmp_micro_counter(clksd_prescaler_width-1 downto 0) = 0) else '0';
cmp_micro_clkint <= '1' when (cmp_micro_counter(clkint_prescaler_width-1 downto 0) = 0) else '0';
cmp_micro: entity work.sigma_delta
generic map (
dout_width => adc_width)
port map (
clk => clk,
reset => reset,
clksd => cmp_micro_clksd,
clkint => cmp_micro_clkint,
dout => micro_dout,
sdi => mic1,
sdo => mic1do);
 
cmp_audio: entity work.audio
generic map (
input_width => audio_input_width)
port map (
clk => clk,
reset => reset,
input => audio_input,
output => speaker);
 
end rtl;
/trunk/vhdl/sc_fpu.vhd
85,17 → 85,17
begin
 
if (reset_i='1') then
start_i <= '0';
-- start_i <= '0';
elsif rising_edge(clk_i) then
 
if rd_i='1' then
-- that's our very simple address decoder
if address_i="0011" then
start_i <= '1';
end if;
else
start_i <= '0';
end if;
-- if rd_i='1' then
-- -- that's our very simple address decoder
-- if address_i="0011" then
-- start_i <= '1';
-- end if;
-- else
-- start_i <= '0';
-- end if;
end if;
 
end process;
125,7 → 125,9
opa_i <= (others => '0');
opb_i <= (others => '0');
fpu_op_i <= (others => '0');
start_i <= '0';
elsif rising_edge(clk_i) then
start_i <= '0';
 
if wr_i='1' then
if address_i="0000" then
134,6 → 136,7
opb_i <= wr_data_i;
elsif address_i="0010" then
fpu_op_i <=wr_data_i(2 downto 0);
start_i <= '1';
end if;
end if;
 

powered by: WebSVN 2.1.0

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