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 25 to Rev 26
    Reverse comparison

Rev 25 → Rev 26

/tags/arelease/doc/simpcon.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
tags/arelease/doc/simpcon.pdf Property changes : Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: trunk/vhdl/sc_cnt.vhd =================================================================== --- trunk/vhdl/sc_cnt.vhd (revision 25) +++ trunk/vhdl/sc_cnt.vhd (nonexistent) @@ -1,235 +0,0 @@ --- --- sc_cnt.vhd --- --- counter, interrrupt handling and watchdog bit --- --- Author: Martin Schoeberl martin@good-ear.com --- --- address map: --- --- 0 read clk counter, write irq ena --- 1 read 1 MHz counter, write timer val (us) + irq ack --- 2 write generates sw-int (for yield()) --- 3 write wd port --- 4 write generates SW exception, read exception reason --- --- todo: --- --- --- 2003-07-05 new IO standard --- 2003-08-15 us counter, irq added --- 2005-11-30 change interface to SimpCon --- 2006-01-11 added exception --- 2007-03-17 changed interrupts to records --- - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.jop_types.all; - -entity sc_cnt 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); - --- --- Interrupts from IO devices --- - irq_in : out irq_in_type; - exc_req : in exception_type; - - wd : out std_logic -); -end sc_cnt ; - -architecture rtl of sc_cnt is - - signal clock_cnt : std_logic_vector(31 downto 0); - signal pre_scale : std_logic_vector(7 downto 0); - signal us_cnt : std_logic_vector(31 downto 0); - - constant div_val : integer := clk_freq/1000000-1; - - signal timer_int : std_logic; - signal yield_int : std_logic; - signal int_ack : std_logic; - - signal timer : std_logic; - signal yield : std_logic; - - signal irq_cnt : std_logic_vector(31 downto 0); - signal timer_equ : std_logic; - signal timer_dly : std_logic; - - signal exc_type : std_logic_vector(7 downto 0); - -begin - - rdy_cnt <= "00"; -- no wait states --- --- read cnt values --- -process(clk, reset) -begin - - if (reset='1') then - rd_data <= (others => '0'); - elsif rising_edge(clk) then - - if rd='1' then - case address(2 downto 0) is - when "000" => - rd_data <= clock_cnt; - when "001" => - rd_data <= us_cnt; - when others => - rd_data(7 downto 0) <= exc_type; - rd_data(31 downto 8) <= (others => '0'); - end case; - end if; - end if; - -end process; - --- --- compare timer value and us counter --- and generate single shot --- -process(us_cnt, irq_cnt) begin - timer_equ <= '0'; - if us_cnt = irq_cnt then - timer_equ <= '1'; - end if; -end process; - -process(clk, reset, timer_equ) begin - if (reset='1') then - timer_dly <= '0'; - elsif rising_edge(clk) then - timer_dly <= timer_equ; - end if; -end process; - - timer_int <= timer_equ and not timer_dly; - --- --- int processing from timer and yield request --- -process(clk, reset, timer_int, yield_int) begin - - if (reset='1') then - timer <= '0'; - yield <= '0'; - elsif rising_edge(clk) then - if int_ack='1' then - timer <= '0'; - yield <= '0'; - else - if timer_int='1' then - timer <= '1'; - end if; - if yield_int='1' then - yield <= '1'; - end if; - end if; - end if; - -end process; - - irq_in.irq <= timer or yield; - - --- --- counters --- pre_scale is 8 bit => fmax = 255 MHz --- -process(clk, reset) begin - - if (reset='1') then - - clock_cnt <= (others => '0'); - us_cnt <= (others => '0'); - pre_scale <= std_logic_vector(to_unsigned(div_val, pre_scale'length)); - - elsif rising_edge(clk) then - - clock_cnt <= std_logic_vector(unsigned(clock_cnt) + 1); - pre_scale <= std_logic_vector(unsigned(pre_scale) - 1); - if pre_scale = "00000000" then - pre_scale <= std_logic_vector(to_unsigned(div_val, pre_scale'length)); - us_cnt <= std_logic_vector(unsigned(us_cnt) + 1); - end if; - - end if; -end process; - --- --- io write processing and exception processing --- -process(clk, reset) - -begin - if (reset='1') then - - irq_in.irq_ena <= '0'; - irq_cnt <= (others => '0'); - int_ack <= '0'; - wd <= '0'; - - exc_type <= (others => '0'); - irq_in.exc_int <= '0'; - - elsif rising_edge(clk) then - - int_ack <= '0'; - yield_int <= '0'; - - irq_in.exc_int <= '0'; - - if exc_req.spov='1' then - 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 - when "000" => - irq_in.irq_ena <= wr_data(0); - when "001" => - irq_cnt <= wr_data; - int_ack <= '1'; - when "010" => - yield_int <= '1'; - when "011" => - wd <= wr_data(0); - when others => - exc_type <= wr_data(7 downto 0); - irq_in.exc_int <= '1'; - end case; - end if; - - end if; -end process; - -end rtl; Index: trunk/vhdl/sc_sram32_flash.vhd =================================================================== --- trunk/vhdl/sc_sram32_flash.vhd (revision 25) +++ trunk/vhdl/sc_sram32_flash.vhd (nonexistent) @@ -1,443 +0,0 @@ --- --- sc_sram32_flash.vhd --- --- SimpCon compliant external memory interface --- for 32-bit SRAM (e.g. Cyclone board) --- --- Connection between mem_sc and the external memory bus --- --- memory mapping --- --- 0x000000-x7ffff external SRAM (w mirror) max. 512 kW (4*4 MBit) --- 0x080000-xfffff external Flash (w mirror) max. 512 kB (4 MBit) --- 0x100000-xfffff external NAND flash --- --- RAM: 32 bit word --- ROM: 8 bit word (for flash programming) --- --- todo: --- --- --- 2005-11-22 first version --- 2005-12-02 added flash interface --- - -Library IEEE; -use IEEE.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.jop_types.all; -use work.sc_pack.all; - -entity sc_mem_if is -generic (ram_ws : integer; rom_ws : integer); - -port ( - - clk, reset : in std_logic; - --- --- SimpCon memory interface --- - sc_mem_out : in sc_mem_out_type; - sc_mem_in : out sc_in_type; - --- memory interface - - ram_addr : out std_logic_vector(17 downto 0); - ram_dout : out std_logic_vector(31 downto 0); - ram_din : in std_logic_vector(31 downto 0); - ram_dout_en : out std_logic; - ram_ncs : out std_logic; - ram_noe : out std_logic; - ram_nwe : out std_logic; - --- --- config/program flash and big nand flash interface --- - fl_a : out std_logic_vector(18 downto 0); - fl_d : inout std_logic_vector(7 downto 0); - fl_ncs : out std_logic; - fl_ncsb : out std_logic; - fl_noe : out std_logic; - fl_nwe : out std_logic; - fl_rdy : in std_logic - -); -end sc_mem_if; - -architecture rtl of sc_mem_if is - --- --- signals for mem interface --- - type state_type is ( - idl, rd1, rd2, wr1, - fl_rd1, fl_rd2, fl_wr1, fl_wr2 - ); - signal state : state_type; - signal next_state : state_type; - - signal nwr_int : std_logic; - signal wait_state : unsigned(3 downto 0); - signal cnt : unsigned(1 downto 0); - - signal dout_ena : std_logic; - signal ram_data : std_logic_vector(31 downto 0); - signal ram_data_ena : std_logic; - - signal flash_dout : std_logic_vector(7 downto 0); - signal fl_dout_ena : std_logic; - signal flash_data : std_logic_vector(7 downto 0); - signal flash_data_ena : std_logic; - signal nand_rdy : std_logic; - - signal trans_ram : std_logic; - signal trans_flash : std_logic; - -- selection for read mux - signal ram_access : std_logic; - -- selection for Flash/NAND ncs - signal sel_flash : std_logic; - -begin - - assert MEM_ADDR_SIZE>=21 report "Too less address bits"; - ram_dout_en <= dout_ena; - - sc_mem_in.rdy_cnt <= cnt; - --- --- decode ram/flash --- The signals are only valid for the first cycle --- -process(sc_mem_out.address(20 downto 19)) -begin - - trans_ram <= '0'; - trans_flash <= '0'; - - case sc_mem_out.address(20 downto 19) is - when "00" => - trans_ram <= '1'; - when "01" => - trans_flash <= '1'; - when others => - null; - end case; - -end process; - --- --- Register memory address, write data and read data --- -process(clk, reset) -begin - if reset='1' then - - ram_addr <= (others => '0'); - ram_dout <= (others => '0'); - ram_data <= (others => '0'); - flash_dout <= (others => '0'); - fl_a <= (others => '0'); - sel_flash <= '1'; -- AMD default - ram_access <= '1'; -- RAM default - - elsif rising_edge(clk) then - - if sc_mem_out.rd='1' or sc_mem_out.wr='1' then - if trans_ram='1' then - ram_access <= '1'; - ram_addr <= sc_mem_out.address(17 downto 0); - else - ram_access <= '0'; - fl_a <= sc_mem_out.address(18 downto 0); - -- select flash type - -- and keep it selected - if trans_flash='1' then - sel_flash <= '1'; - else - sel_flash <= '0'; - end if; - end if; - end if; - if sc_mem_out.wr='1' then - if trans_ram='1' then - ram_dout <= sc_mem_out.wr_data; - else - flash_dout <= sc_mem_out.wr_data(7 downto 0); - end if; - end if; - if ram_data_ena='1' then - ram_data <= ram_din; - end if; - if flash_data_ena='1' then - -- signal NAND rdy only for NAND access - nand_rdy <= fl_rdy and not sel_flash; - flash_data <= fl_d; - end if; - - end if; -end process; - --- --- MUX registered RAM and Flash data --- -process(ram_access, ram_data, flash_data, nand_rdy) - -begin - if (ram_access='1') then - sc_mem_in.rd_data <= ram_data; - else - sc_mem_in.rd_data <= std_logic_vector(to_unsigned(0, 32-9)) & nand_rdy & flash_data; - end if; -end process; - --- --- 'delay' nwe 1/2 cycle -> change on falling edge --- -process(clk, reset) - -begin - if (reset='1') then - ram_nwe <= '1'; - elsif falling_edge(clk) then - ram_nwe <= nwr_int; - end if; - -end process; - - --- --- next state logic --- -process(state, sc_mem_out, trans_ram, wait_state) - -begin - - next_state <= state; - - case state is - - when idl => - if sc_mem_out.rd='1' then - if trans_ram='1' then - if ram_ws=0 then - -- then we omit state rd1! - next_state <= rd2; - else - next_state <= rd1; - end if; - else - next_state <= fl_rd1; - end if; - elsif sc_mem_out.wr='1' then - if trans_ram='1' then - next_state <= wr1; - else - next_state <= fl_wr1; - end if; - end if; - - -- the WS state - when rd1 => - if wait_state=2 then - next_state <= rd2; - end if; - - -- last read state - when rd2 => - next_state <= idl; - -- This should do to give us a pipeline - -- level of 2 for read - -- we don't care about a flash trans. - -- in the pipeline! - if sc_mem_out.rd='1' then - if ram_ws=0 then - -- then we omit state rd1! - next_state <= rd2; - else - next_state <= rd1; - end if; - elsif sc_mem_out.wr='1' then - next_state <= wr1; - end if; - - -- the WS state - when wr1 => --- TODO: check what happens on ram_ws=0 --- TODO: do we need a write pipelining? --- not at the moment, but parhaps later when --- we write the stack content to main memory - if wait_state=1 then - next_state <= idl; - end if; - - when fl_rd1 => - if wait_state=2 then - next_state <= fl_rd2; - end if; - - when fl_rd2 => - next_state <= idl; - -- we do no pipelining with the Flashs - - when fl_wr1 => - if wait_state=2 then - next_state <= fl_wr2; - end if; - - when fl_wr2 => - next_state <= idl; - - end case; - -end process; - --- --- state machine register --- output register (RAM, Flash control lines) --- -process(clk, reset) - -begin - if (reset='1') then - state <= idl; - dout_ena <= '0'; - ram_ncs <= '1'; - ram_noe <= '1'; - ram_data_ena <= '0'; - - fl_noe <= '1'; - fl_nwe <= '1'; - flash_data_ena <= '0'; - fl_dout_ena <= '0'; - - elsif rising_edge(clk) then - - state <= next_state; - dout_ena <= '0'; - ram_ncs <= '1'; - ram_noe <= '1'; - ram_data_ena <= '0'; - - fl_noe <= '1'; - fl_nwe <= '1'; - flash_data_ena <= '0'; - fl_dout_ena <= '0'; - - case next_state is - - when idl => - - -- the wait state - when rd1 => - ram_ncs <= '0'; - ram_noe <= '0'; - - -- last read state - when rd2 => - ram_ncs <= '0'; - ram_noe <= '0'; - ram_data_ena <= '1'; - - - -- the WS state - when wr1 => - ram_ncs <= '0'; - dout_ena <= '1'; - - when fl_rd1 => - fl_noe <= '0'; - - when fl_rd2 => - fl_noe <= '0'; - flash_data_ena <= '1'; - - when fl_wr1 => - fl_nwe <= '0'; - fl_dout_ena <= '1'; - - when fl_wr2 => - fl_dout_ena <= '1'; - - end case; - - end if; -end process; - --- --- nwr combinatorial processing --- for the negativ edge --- -process(next_state, state) -begin - - nwr_int <= '1'; - if next_state=wr1 then - nwr_int <= '0'; - end if; - -end process; - --- --- wait_state processing --- cs delay, dout enable --- -process(clk, reset) -begin - if (reset='1') then - wait_state <= (others => '1'); - cnt <= "00"; - elsif rising_edge(clk) then - - wait_state <= wait_state-1; - - cnt <= "11"; - if next_state=idl then - cnt <= "00"; - -- if wait_state<4 then - elsif wait_state(3 downto 2)="00" then - cnt <= wait_state(1 downto 0)-1; - end if; - - if sc_mem_out.rd='1' or sc_mem_out.wr='1' then - if trans_ram='1' then - wait_state <= to_unsigned(ram_ws+1, 4); - if ram_ws<3 then - cnt <= to_unsigned(ram_ws+1, 2); - else - cnt <= "11"; - end if; - else - wait_state <= to_unsigned(rom_ws+1, 4); - cnt <= "11"; - end if; - end if; - - end if; -end process; - --- --- Flash signals --- - --- --- leave last ncs. Only toggle between two flashs. --- - fl_ncs <= not sel_flash; -- Flash ncs - fl_ncsb <= sel_flash; -- NAND ncs - --- --- tristate output --- -process(fl_dout_ena, flash_dout) - -begin - if (fl_dout_ena='1') then - fl_d <= flash_dout(7 downto 0); - else - fl_d <= (others => 'Z'); - end if; -end process; - -end rtl; Index: trunk/vhdl/sc_arbiter_pack.vhd =================================================================== --- trunk/vhdl/sc_arbiter_pack.vhd (revision 25) +++ trunk/vhdl/sc_arbiter_pack.vhd (nonexistent) @@ -1,12 +0,0 @@ -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.sc_pack.all; - -package sc_arbiter_pack is - - type arb_out_type is array (integer range <>) of sc_mem_out_type; - type arb_in_type is array (integer range <>) of sc_in_type; - -end sc_arbiter_pack; Index: trunk/vhdl/sc_arbiter_2m.vhd =================================================================== --- trunk/vhdl/sc_arbiter_2m.vhd (revision 25) +++ trunk/vhdl/sc_arbiter_2m.vhd (nonexistent) @@ -1,390 +0,0 @@ - - --- 150407: first working version with records --- 170407: produce number of registers depending on the cpu_cnt --- 110507: * arbiter that can be used with prefered number of masters --- * full functional arbiter with two masters --- * short modelsim test with 3 masters carried out --- 290607: used for JTRES07 submission - - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.sc_pack.all; -use work.sc_arbiter_pack.all; - -entity arbiter is -generic( - addr_bits : integer; - cpu_cnt : integer); -- number of masters for the arbiter -port ( - clk, reset : in std_logic; - arb_out : in arb_out_type(0 to cpu_cnt-1); - arb_in : out arb_in_type(0 to cpu_cnt-1); - mem_out : out sc_mem_out_type; - mem_in : in sc_in_type -); -end arbiter; - - -architecture rtl of arbiter is - --- signals for the input register of each master - - type reg_type is record - rd : std_logic; - wr : std_logic; - wr_data : std_logic_vector(31 downto 0); - address : std_logic_vector(addr_bits-1 downto 0); - end record; - - type reg_array_type is array (0 to cpu_cnt-1) of reg_type; - signal reg_in : reg_array_type; - --- one fsm for each CPU - - type state_type is (idle, read, write, waitingR, sendR, - waitingW, sendW); - type state_array is array (0 to cpu_cnt-1) of state_type; - signal state : state_array; - signal next_state : state_array; - --- one fsm for each serve - - type serve_type is (idl, serv); - type serve_array is array (0 to cpu_cnt-1) of serve_type; - signal this_state : serve_array; - signal follow_state : serve_array; - --- arbiter - - type set_type is array (0 to cpu_cnt-1) of std_logic; - signal set : set_type; - - -begin - - --- Generates the input register and saves incoming data for each master -gen_register: for i in 0 to cpu_cnt-1 generate - process(clk, reset) - begin - if reset = '1' then - reg_in(i).rd <= '0'; - reg_in(i).wr <= '0'; - reg_in(i).wr_data <= (others => '0'); - reg_in(i).address <= (others => '0'); - elsif rising_edge(clk) then - if arb_out(i).rd = '1' or arb_out(i).wr = '1' then - reg_in(i).rd <= arb_out(i).rd; - reg_in(i).wr <= arb_out(i).wr; - reg_in(i).address <= arb_out(i).address; - reg_in(i).wr_data <= arb_out(i).wr_data; - end if; - end if; - end process; -end generate; - --- Generates next state of the FSM for each master -gen_next_state: for i in 0 to cpu_cnt-1 generate - process(reset, state, arb_out, mem_in, this_state, reg_in) - begin - - next_state(i) <= state(i); - - case state(i) is - when idle => - - if this_state(i) = serv then -- checks if this CPU is on turn - if mem_in.rdy_cnt = 1 and arb_out(i).rd = '1' then - next_state(i) <= read; - elsif (mem_in.rdy_cnt = 0) and (arb_out(i).rd = '1' - or arb_out(i).wr = '1') then - for k in 0 to cpu_cnt-1 loop - if arb_out(k).rd = '1' or arb_out(k).wr = '1' then - if i<=k then - if arb_out(i).rd = '1' then - next_state(i) <= read; - exit; - elsif arb_out(i).wr = '1' then - next_state(i) <= write; - exit; - end if; - else - if arb_out(i).rd = '1' then - next_state(i) <= waitingR; - exit; - elsif arb_out(i).wr = '1' then - next_state(i) <= waitingW; - exit; - end if; - end if; - elsif reg_in(k).rd = '1' or reg_in(k).wr = '1' then - if arb_out(i).rd = '1' then - next_state(i) <= waitingR; - exit; - elsif arb_out(i).wr = '1' then - next_state(i) <= waitingW; - exit; - end if; - else - if arb_out(i).rd = '1' then - next_state(i) <= read; - elsif arb_out(i).wr = '1' then - next_state(i) <= write; - end if; - end if; - end loop; - end if; - else - for j in 0 to cpu_cnt-1 loop - if this_state(j) = serv then - if mem_in.rdy_cnt = 1 and arb_out(j).rd = '1' and - arb_out(i).rd = '1' then - next_state(i) <= waitingR; - exit; - elsif mem_in.rdy_cnt = 1 and arb_out(j).rd = '1' and - arb_out(i).wr = '1' then - next_state(i) <= waitingW; - exit; - end if; - else - if mem_in.rdy_cnt = 0 then - if arb_out(j).rd = '1' or arb_out(j).wr = '1' then - if i<=j then - if arb_out(i).rd = '1' then - next_state(i) <= read; - exit; -- new - elsif arb_out(i).wr = '1' then - next_state(i) <= write; - exit; -- new - end if; - else - if arb_out(i).rd = '1' then - next_state(i) <= waitingR; - exit; - elsif arb_out(i).wr = '1' then - next_state(i) <= waitingW; - exit; - end if; - end if; - -- new - elsif (state(j) = waitingR) or (state(j) = waitingW) then - if arb_out(i).rd = '1' then - next_state(i) <= waitingR; - elsif arb_out(i).wr = '1' then - next_state(i) <= waitingW; - exit; - end if; - -- new - elsif arb_out(i).rd = '1' then - next_state(i) <= read; - elsif arb_out(i).wr = '1' then - next_state(i) <= write; - end if; - else - if arb_out(i).rd = '1' then - next_state(i) <= waitingR; - exit; - elsif arb_out(i).wr = '1' then - next_state(i) <= waitingW; - exit; - end if; - end if; - end if; - end loop; - end if; - - when read => - next_state(i) <= idle; - - when write => - next_state(i) <= idle; - - when waitingR => - if mem_in.rdy_cnt = 0 then - -- checks which CPU in waitingR has highest priority - for j in 0 to cpu_cnt-1 loop - --if arb_out(j).rd = '1' or arb_out(j).wr = '1' then - -- next_state(i) <= waitingR; - -- exit; - --els - if (state(j) = waitingR) or (state(j) = waitingW) then - if j - next_state(i) <= idle; - - when waitingW => - if mem_in.rdy_cnt = 0 then - for j in 0 to cpu_cnt-1 loop - --if arb_out(j).rd = '1' or arb_out(j).wr = '1' then - -- next_state(i) <= waitingW; - -- exit; - --els - if (state(j) = waitingR) or (state(j) = waitingW) then - if j - next_state(i) <= idle; - - end case; - end process; -end generate; - - --- Generates the FSM state for each master -gen_state: for i in 0 to cpu_cnt-1 generate - process (clk, reset) - begin - if (reset = '1') then - state(i) <= idle; - elsif (rising_edge(clk)) then - state(i) <= next_state(i); - end if; - end process; -end generate; - - --- The arbiter output -process (arb_out, reg_in, next_state) -begin - - mem_out.rd <= '0'; - mem_out.wr <= '0'; - mem_out.address <= (others => '0'); - mem_out.wr_data <= (others => '0'); - - for i in 0 to cpu_cnt-1 loop - set(i) <= '0'; - - case next_state(i) is - when idle => - - when read => - set(i) <= '1'; - mem_out.rd <= arb_out(i).rd; - mem_out.address <= arb_out(i).address; - - when write => - set(i) <= '1'; - mem_out.wr <= arb_out(i).wr; - mem_out.address <= arb_out(i).address; - mem_out.wr_data <= arb_out(i).wr_data; - - when waitingR => - - when sendR => - set(i) <= '1'; - mem_out.rd <= reg_in(i).rd; - mem_out.address <= reg_in(i).address; - - when waitingW => - - when sendW => - set(i) <= '1'; - mem_out.wr <= reg_in(i).wr; - mem_out.address <= reg_in(i).address; - mem_out.wr_data <= reg_in(i).wr_data; - - end case; - end loop; -end process; - --- generation of follow_state -gen_serve: for i in 0 to cpu_cnt-1 generate - process(mem_in, set, this_state) - begin - case this_state(i) is - when idl => - follow_state(i) <= idl; - if set(i) = '1' then - follow_state(i) <= serv; - end if; - when serv => - follow_state(i) <= serv; - if mem_in.rdy_cnt = 0 and set(i) = '0' then - follow_state(i) <= idl; - end if; - end case; - end process; -end generate; - -gen_serve2: for i in 0 to cpu_cnt-1 generate - process (clk, reset) - begin - if (reset = '1') then - this_state(i) <= idl; - elsif (rising_edge(clk)) then - this_state(i) <= follow_state(i); - end if; - end process; -end generate; - -gen_rdy_cnt: for i in 0 to cpu_cnt-1 generate - process (mem_in, state, this_state) - begin - arb_in(i).rdy_cnt <= mem_in.rdy_cnt; - arb_in(i).rd_data <= mem_in.rd_data; - - case state(i) is - when idle => - case this_state(i) is - when idl => - arb_in(i).rdy_cnt <= "00"; - when serv => - end case; - - when read => - - when write => - - when waitingR => - arb_in(i).rdy_cnt <= "11"; - - when sendR => - - when waitingW => - arb_in(i).rdy_cnt <= "11"; - - when sendW => - - end case; - end process; -end generate; - -end rtl; Index: trunk/vhdl/sc_lego.vhd =================================================================== --- trunk/vhdl/sc_lego.vhd (revision 25) +++ trunk/vhdl/sc_lego.vhd (nonexistent) @@ -1,444 +0,0 @@ --- --- sc_lego.vhd --- --- 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: --- see read and write processes --- --- --- 2005-12-22 adapted for SimpCon interface --- 2007-03-13 extended for Lego PCB --- --- todo: --- --- - - --- --- lego io --- - -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 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); - - -- speaker - - speaker : out std_logic; - - -- motor stuff - - 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; - - 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; - - m2en : out std_logic; - m2dir : out std_logic; - m2break : out std_logic; - - -- 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; - - mic1do : out std_logic; - mic1 : in std_logic; - - - -- pld - pld_strobe : out std_logic; - pld_data : inout std_logic; - pld_clk : out std_logic - - ); -end sc_lego; - -architecture rtl of sc_lego is - -- settings for components - constant adc_width : integer := 9; - - -- 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; - - - constant audio_input_width : integer := 8; - - - -- pld - - signal pld_out_pins : FORWARDED_PINS; - signal pld_in_pins : FORWARDED_PINS; - - -- 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); - - -- motors - - signal motor0_state: lego_motor_state; - signal motor0_duty_cycle: unsigned(duty_cycle_width-1 downto 0); - signal motor0_measure: std_logic; - - 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; - - 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; - - signal motor1_buf_bemf: std_logic_vector(motor_dout_width*2-1 downto 0); - - -- microphone - - 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 - --- --- The registered MUX is all we need for a SimpCon read. --- The read data is stored in registered rd_data. --- - read: process(clk, reset) - begin - - if (reset='1') then - rd_data <= (others => '0'); - elsif rising_edge(clk) then - - 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; - - --- --- SimpCon write is very simple --- - write: process(clk, reset) - - begin - - if (reset='1') then - pld_out_pins <= (others => '0'); - - motor0_state <= LEGO_MOTOR_STATE_OFF; - motor0_duty_cycle <= (others => '0'); - motor0_measure <= '0'; - - motor1_state <= LEGO_MOTOR_STATE_OFF; - motor1_duty_cycle <= (others => '0'); - motor1_measure <= '0'; - - motor2_state <= LEGO_MOTOR_STATE_OFF; - motor2_duty_cycle <= (others => '0'); - motor2_measure <= '0'; - - elsif rising_edge(clk) then - - if wr='1' then - - 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; - - end if; - - 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, - dout => sensor0_dout, - sp => s0pi, - sdi => s0di, - sdo => s0do); - - 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); - - 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; Index: trunk/vhdl/sc_arbiter.vhd =================================================================== --- trunk/vhdl/sc_arbiter.vhd (revision 25) +++ trunk/vhdl/sc_arbiter.vhd (nonexistent) @@ -1,424 +0,0 @@ - - --- 150407: first working version with records --- 170407: produce number of registers depending on the cpu_cnt --- 110507: * arbiter that can be used with prefered number of masters --- * full functional arbiter with two masters --- * short modelsim test with 3 masters carried out --- 190607: Problem found: Both CPU1 and CPU2 start to read cache line!!! --- 030707: Several bugs are fixed now. CMP with 3 running masters functions! - - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.sc_pack.all; -use work.sc_arbiter_pack.all; - -entity arbiter is -generic( - addr_bits : integer; - cpu_cnt : integer); -- number of masters for the arbiter -port ( - clk, reset : in std_logic; - arb_out : in arb_out_type(0 to cpu_cnt-1); - arb_in : out arb_in_type(0 to cpu_cnt-1); - mem_out : out sc_mem_out_type; - mem_in : in sc_in_type -); -end arbiter; - - -architecture rtl of arbiter is - --- signals for the input register of each master - - type reg_type is record - rd : std_logic; - wr : std_logic; - wr_data : std_logic_vector(31 downto 0); - address : std_logic_vector(addr_bits-1 downto 0); - end record; - - type reg_array_type is array (0 to cpu_cnt-1) of reg_type; - signal reg_in : reg_array_type; - --- one fsm for each CPU - - type state_type is (idle, read, write, waitingR, sendR, - waitingW, sendW); - type state_array is array (0 to cpu_cnt-1) of state_type; - signal state : state_array; - signal next_state : state_array; - --- one fsm for each serve - - type serve_type is (idl, serv); - type serve_array is array (0 to cpu_cnt-1) of serve_type; - signal this_state : serve_array; - signal follow_state : serve_array; - --- arbiter - - type set_type is array (0 to cpu_cnt-1) of std_logic; - signal set : set_type; - signal waiting : set_type; - signal masterWaiting : std_logic; - - -begin - - --- Generates the input register and saves incoming data for each master -gen_register: for i in 0 to cpu_cnt-1 generate - process(clk, reset) - begin - if reset = '1' then - reg_in(i).rd <= '0'; - reg_in(i).wr <= '0'; - reg_in(i).wr_data <= (others => '0'); - reg_in(i).address <= (others => '0'); - elsif rising_edge(clk) then - if arb_out(i).rd = '1' or arb_out(i).wr = '1' then - reg_in(i).rd <= arb_out(i).rd; - reg_in(i).wr <= arb_out(i).wr; - reg_in(i).address <= arb_out(i).address; - reg_in(i).wr_data <= arb_out(i).wr_data; - end if; - end if; - end process; -end generate; - --- Register for masterWaiting -process(clk, reset) - begin - if reset = '1' then - masterWaiting <= '0'; - elsif rising_edge(clk) then - for i in 0 to cpu_cnt-1 loop - if waiting(i) = '1' then - masterWaiting <= '1'; - exit; - else - masterWaiting <= '0'; - end if; - end loop; - end if; - end process; - --- Generates next state of the FSM for each master -gen_next_state: for i in 0 to cpu_cnt-1 generate - process(reset, state, arb_out, mem_in, this_state, reg_in, masterWaiting) - begin - - next_state(i) <= state(i); - waiting(i) <= '0'; - - case state(i) is - when idle => - - -- checks if this CPU is on turn (pipelined access) - if this_state(i) = serv then - -- pipelined access - if mem_in.rdy_cnt = 1 and arb_out(i).rd = '1' then - next_state(i) <= read; - - elsif (mem_in.rdy_cnt = 0 and (arb_out(i).rd = '1' or arb_out(i).wr = '1')) then - - -- check if some master is waiting - if masterWaiting = '1' then - if arb_out(i).rd = '1' then - next_state(i) <= waitingR; - waiting(i) <= '1'; - elsif arb_out(i).wr = '1' then - next_state(i) <= waitingW; - waiting(i) <= '1'; - end if; - - -- check if parallel access - else - for j in 0 to cpu_cnt-1 loop - if arb_out(j).rd = '1' or arb_out(j).wr = '1' then - if i<=j then - if arb_out(i).rd = '1' then - next_state(i) <= read; - exit; - elsif arb_out(i).wr = '1' then - next_state(i) <= write; - exit; - end if; - else - if arb_out(i).rd = '1' then - next_state(i) <= waitingR; - waiting(i) <= '1'; - exit; - elsif arb_out(i).wr = '1' then - next_state(i) <= waitingW; - waiting(i) <= '1'; - exit; - end if; - end if; - end if; - end loop; - end if; - - -- all other kinds of rdy_cnt - else - if arb_out(i).rd = '1' then - next_state(i) <= waitingR; - waiting(i) <= '1'; - elsif arb_out(i).wr = '1' then - next_state(i) <= waitingW; - waiting(i) <= '1'; - end if; - end if; - - -- CPU is not on turn (no pipelined access possible) - else - if (mem_in.rdy_cnt = 0 and (arb_out(i).rd = '1' or arb_out(i).wr = '1')) then - -- check if some master is waiting - if masterWaiting = '1' then - if arb_out(i).rd = '1' then - next_state(i) <= waitingR; - waiting(i) <= '1'; - elsif arb_out(i).wr = '1' then - next_state(i) <= waitingW; - waiting(i) <= '1'; - end if; - - -- check if parallel access - else - for j in 0 to cpu_cnt-1 loop - if arb_out(j).rd = '1' or arb_out(j).wr = '1' then - if i<=j then - if arb_out(i).rd = '1' then - next_state(i) <= read; - exit; - elsif arb_out(i).wr = '1' then - next_state(i) <= write; - exit; - end if; - else - if arb_out(i).rd = '1' then - next_state(i) <= waitingR; - waiting(i) <= '1'; - exit; - elsif arb_out(i).wr = '1' then - next_state(i) <= waitingW; - waiting(i) <= '1'; - exit; - end if; - end if; - -- if no parallel access, master can access - else - if arb_out(i).rd = '1' then - next_state(i) <= read; - elsif arb_out(i).wr = '1' then - next_state(i) <= write; - end if; - end if; - end loop; - end if; - - -- rdy_cnt != 0 - else - if arb_out(i).rd = '1' then - next_state(i) <= waitingR; - waiting(i) <= '1'; - elsif arb_out(i).wr = '1' then - next_state(i) <= waitingW; - waiting(i) <= '1'; - end if; - end if; - end if; - - - when read => - next_state(i) <= idle; - - when write => - next_state(i) <= idle; - - when waitingR => - if mem_in.rdy_cnt = 0 then - -- checks which CPU in waitingR has highest priority - for j in 0 to cpu_cnt-1 loop - if (state(j) = waitingR) or (state(j) = waitingW) then - if j - next_state(i) <= idle; - - when waitingW => - - if mem_in.rdy_cnt = 0 then - for j in 0 to cpu_cnt-1 loop - if (state(j) = waitingR) or (state(j) = waitingW) then - if j - next_state(i) <= idle; - - end case; - end process; -end generate; - - --- Generates the FSM state for each master -gen_state: for i in 0 to cpu_cnt-1 generate - process (clk, reset) - begin - if (reset = '1') then - state(i) <= idle; - elsif (rising_edge(clk)) then - state(i) <= next_state(i); - end if; - end process; -end generate; - - --- The arbiter output -process (arb_out, reg_in, next_state) -begin - - mem_out.rd <= '0'; - mem_out.wr <= '0'; - mem_out.address <= (others => '0'); - mem_out.wr_data <= (others => '0'); - - for i in 0 to cpu_cnt-1 loop - set(i) <= '0'; - - case next_state(i) is - when idle => - - when read => - set(i) <= '1'; - mem_out.rd <= arb_out(i).rd; - mem_out.address <= arb_out(i).address; - - when write => - set(i) <= '1'; - mem_out.wr <= arb_out(i).wr; - mem_out.address <= arb_out(i).address; - mem_out.wr_data <= arb_out(i).wr_data; - - when waitingR => - - when sendR => - set(i) <= '1'; - mem_out.rd <= reg_in(i).rd; - mem_out.address <= reg_in(i).address; - - when waitingW => - - when sendW => - set(i) <= '1'; - mem_out.wr <= reg_in(i).wr; - mem_out.address <= reg_in(i).address; - mem_out.wr_data <= reg_in(i).wr_data; - - end case; - end loop; -end process; - --- generation of follow_state -gen_serve: for i in 0 to cpu_cnt-1 generate - process(mem_in, set, this_state) - begin - case this_state(i) is - when idl => - follow_state(i) <= idl; - if set(i) = '1' then - follow_state(i) <= serv; - end if; - when serv => - follow_state(i) <= serv; - if mem_in.rdy_cnt = 0 and set(i) = '0' then - follow_state(i) <= idl; - end if; - end case; - end process; -end generate; - -gen_serve2: for i in 0 to cpu_cnt-1 generate - process (clk, reset) - begin - if (reset = '1') then - this_state(i) <= idl; - elsif (rising_edge(clk)) then - this_state(i) <= follow_state(i); - end if; - end process; -end generate; - -gen_rdy_cnt: for i in 0 to cpu_cnt-1 generate - process (mem_in, state, this_state) - begin - arb_in(i).rdy_cnt <= mem_in.rdy_cnt; - arb_in(i).rd_data <= mem_in.rd_data; - - case state(i) is - when idle => - case this_state(i) is - when idl => - arb_in(i).rdy_cnt <= "00"; - when serv => - end case; - - when read => - - when write => - - when waitingR => - arb_in(i).rdy_cnt <= "11"; - - when sendR => - - when waitingW => - arb_in(i).rdy_cnt <= "11"; - - when sendW => - - end case; - end process; -end generate; - -end rtl; Index: trunk/vhdl/sc_usb.vhd =================================================================== --- trunk/vhdl/sc_usb.vhd (revision 25) +++ trunk/vhdl/sc_usb.vhd (nonexistent) @@ -1,266 +0,0 @@ --- --- sc_usb.vhd --- --- Interface to FTDI FT2232C parallel port B --- --- Author: Martin Schoeberl martin@jopdesign.com --- --- --- resources on Cyclone --- --- xx LCs, max xx MHz --- --- --- 2005-08-23 first version --- --- todo: --- --- - - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.jop_types.all; - -entity sc_usb 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); - --- FTDI 2232 connection - - data : inout std_logic_vector(7 downto 0); - nrxf : in std_logic; - ntxe : in std_logic; - nrd : out std_logic; - ft_wr : out std_logic; - nsi : out std_logic -); -end sc_usb; - -architecture rtl of sc_usb is - - signal usb_out : std_logic_vector(7 downto 0); - signal usb_in : std_logic_vector(7 downto 0); - - signal read_ack : std_logic; - signal fifo_wr : std_logic; - --- --- - constant WS : integer := (clk_freq/20000000)+1; - signal cnt : integer range 0 to WS; - --- --- FIFO signals --- - signal tf_dout : std_logic_vector(7 downto 0); -- fifo out - signal tf_rd : std_logic; - signal tf_empty : std_logic; - signal tf_full : std_logic; - - signal rf_din : std_logic_vector(7 downto 0); -- fifo input - signal rf_wr : std_logic; - signal rf_empty : std_logic; - signal rf_full : std_logic; - - --- --- USB interface signals --- - type state_type is (idle, inact, rx1, rx2, tx1, tx2); - signal state : state_type; - - signal usb_dout : std_logic_vector(7 downto 0); - signal usb_din : std_logic_vector(7 downto 0); - - signal nrxf_buf : std_logic_vector(1 downto 0); - signal ntxe_buf : std_logic_vector(1 downto 0); - signal rdr, wrr : std_logic_vector(7 downto 0); - signal data_oe : std_logic; - -begin - - rdy_cnt <= "00"; -- no wait states - rd_data(31 downto 8) <= std_logic_vector(to_unsigned(0, 24)); --- --- The registered MUX is all we need for a SimpCon read. --- The read data is stored in registered rd_data. --- -process(clk, reset) -begin - - if (reset='1') then - rd_data(7 downto 0) <= (others => '0'); - elsif rising_edge(clk) then - - read_ack <= '0'; - if rd='1' then - -- that's our very simple address decoder - if address(0)='0' then - rd_data(7 downto 0) <= "000000" & not rf_empty & not tf_full; - else - rd_data(7 downto 0) <= usb_dout; - read_ack <= rd; - end if; - end if; - end if; - -end process; - - -- write is on address offest 1 - fifo_wr <= wr and address(0); - - -- we don't use the send immediate - nsi <= '1'; - - --- --- receive fifo --- - rxfifo: entity work.fifo generic map ( - width => 8, - depth => 4, - thres => 2 -- we don't care about the half signal - ) port map ( - clk => clk, - reset => reset, - din => rf_din, - dout => usb_dout, - rd => read_ack, - wr => rf_wr, - empty => rf_empty, - full => rf_full, - half => open - ); - --- --- transmit fifo --- - txfifo: entity work.fifo generic map ( - width => 8, - depth => 4, - thres => 2 -- we don't care about the half signal - ) port map ( - clk => clk, - reset => reset, - din => wr_data(7 downto 0), - dout => tf_dout, - rd => tf_rd, - wr => fifo_wr, - empty => tf_empty, - full => tf_full, - half => open - ); - - --- --- state machine for the usb bus --- -process(clk, reset) - -begin - - if (reset='1') then - state <= idle; - nrxf_buf <= "11"; - ntxe_buf <= "11"; - cnt <= WS; - - rdr <= (others => '0'); - wrr <= (others => '0'); - - tf_rd <= '0'; - rf_wr <= '0'; - - nrd <= '1'; - ft_wr <= '0'; - - elsif rising_edge(clk) then - - -- input register - nrxf_buf(0) <= nrxf; - nrxf_buf(1) <= nrxf_buf(0); - ntxe_buf(0) <= ntxe; - ntxe_buf(1) <= ntxe_buf(0); - - case state is - - when idle => - cnt <= WS; - tf_rd <= '0'; - rf_wr <= '0'; - nrd <= '1'; - ft_wr <= '0'; - data_oe <= '0'; - if rf_full='0' and nrxf_buf(1)='0' then - nrd <= '0'; - state <= rx1; - elsif tf_empty='0' and ntxe_buf(1)='0' then - ft_wr <= '1'; - wrr <= tf_dout; - tf_rd <= '1'; - state <= tx1; - end if; - - when inact => - tf_rd <= '0'; - rf_wr <= '0'; - nrd <= '1'; - ft_wr <= '0'; - data_oe <= '0'; - cnt <= cnt-1; - if cnt=0 then - state <= idle; - end if; - - - when rx1 => - cnt <= cnt-1; - if cnt=0 then - state <= rx2; - rdr <= data; - end if; - - when rx2 => - nrd <= '1'; - rf_wr <= '1'; - cnt <= WS; - state <= inact; - - when tx1 => - tf_rd <= '0'; - data_oe <= '1'; - cnt <= cnt-1; - if cnt=0 then - state <= tx2; - ft_wr <= '0'; - end if; - - when tx2 => - data_oe <= '0'; - cnt <= WS; - state <= inact; - - end case; - end if; - -end process; - - data <= wrr when data_oe='1' else (others => 'Z'); - rf_din <= data; - -end rtl; Index: trunk/vhdl/sc_fpu.vhd =================================================================== --- trunk/vhdl/sc_fpu.vhd (revision 25) +++ trunk/vhdl/sc_fpu.vhd (nonexistent) @@ -1,148 +0,0 @@ --- This is the SimpCon interface to the FPU --- - -Library IEEE; -use IEEE.std_logic_1164.all; -use ieee.std_logic_unsigned.all; -use ieee.numeric_std.all; - -entity sc_fpu is -generic (ADDR_WIDTH : integer); - -port ( - clk_i : in std_logic; - reset_i : in std_logic; - --- SimpCon interface - - address_i : in std_logic_vector(ADDR_WIDTH-1 downto 0); - wr_data_i : in std_logic_vector(31 downto 0); - rd_i, wr_i : in std_logic; - rd_data_o : out std_logic_vector(31 downto 0); - rdy_cnt_o : out unsigned(1 downto 0) - -); -end sc_fpu; - -architecture rtl of sc_fpu is - - component fpu - port ( - clk_i : in std_logic; - opa_i : in std_logic_vector(31 downto 0); - opb_i : in std_logic_vector(31 downto 0); - fpu_op_i : in std_logic_vector(2 downto 0); - rmode_i : in std_logic_vector(1 downto 0); - - output_o : out std_logic_vector(31 downto 0); - ine_o : out std_logic; - overflow_o : out std_logic; - underflow_o : out std_logic; - div_zero_o : out std_logic; - inf_o : out std_logic; - zero_o : out std_logic; - qnan_o : out std_logic; - snan_o : out std_logic; - - start_i : in std_logic; - ready_o : out std_logic - ); - end component; - - signal opa_i, opb_i : std_logic_vector(31 downto 0); - signal fpu_op_i : std_logic_vector(2 downto 0); - signal rmode_i : std_logic_vector(1 downto 0); - signal output_o : std_logic_vector(31 downto 0); - signal start_i, ready_o : std_logic ; - --signal ine_o, overflow_o, underflow_o, div_zero_o, inf_o, zero_o, qnan_o, snan_o: std_logic; - -begin - - - -- instantiate the fpu - i_fpu: fpu port map ( - clk_i => clk_i, - opa_i => opa_i, - opb_i => opb_i, - fpu_op_i => fpu_op_i, - rmode_i => rmode_i, - output_o => output_o, - ine_o => open, - overflow_o => open, - underflow_o => open, - div_zero_o => open, - inf_o => open, - zero_o => open, - qnan_o => open, - snan_o => open, - start_i => start_i, - ready_o => ready_o); - -rmode_i <= "00"; -- default rounding mode= round-to-nearest-even - --- master reads from FPU -process(clk_i, reset_i) -begin - - if (reset_i='1') then --- 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; - end if; - -end process; - --- set rdy_cnt -process(clk_i) -begin - if (reset_i='1') then - rdy_cnt_o <= "11"; - elsif rising_edge(clk_i) then - if start_i='1' then - rdy_cnt_o <= "11"; - elsif ready_o = '1' then - rdy_cnt_o <= "00"; - rd_data_o <= output_o; - end if; - end if; -end process; - - --- master writes to FPU -process(clk_i, reset_i) - -begin - - if (reset_i='1') then - 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 - opa_i <= wr_data_i; - elsif address_i="0001" then - 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; - - end if; - -end process; - - -end rtl; Index: trunk/vhdl/sc2wb.vhd =================================================================== --- trunk/vhdl/sc2wb.vhd (revision 25) +++ trunk/vhdl/sc2wb.vhd (nonexistent) @@ -1,170 +0,0 @@ --- --- sc2wb.vhd --- --- SimpCon/Wishbone bridge --- --- Author: Martin Schoeberl martin@jopdesign.com --- --- --- --- WISHBONE DATA SHEET --- --- Revision Level: B.3, Released: September 7, 2002 --- Type: MASTER --- --- Signals: record and address size is defined in wb_pack.vhd --- --- Port Width Direction Description --- ------------------------------------------------------------------------ --- clk 1 Input Master clock, see JOP top level --- reset 1 Input Reset, see JOP top level --- dat_o 32 Output Data from SimpCon --- adr_o 8 Output Address bits for the slaves, see wb_pack.vhd --- Only addr_bits bits are actually used --- we_o 1 Output Write enable output --- cyc_o 1 Output Valid bus cycle output --- stb_o 1 Output Strobe signal output --- dat_i 32 Input Data from the slaves to JOP --- ack_i 1 Input Bus cycle acknowledge input --- --- Port size: 32-bit --- Port granularity: 32-bit --- Maximum operand size: 32-bit --- Data transfer ordering: BIG/LITTLE ENDIAN --- Sequence of data transfer: UNDEFINED --- --- --- 2005-12-20 first version --- --- - - -library ieee ; -use ieee.std_logic_1164.all ; -use ieee.numeric_std.all ; - -use work.wb_pack.all; - -entity sc2wb is - -generic (addr_bits : 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); - --- Wishbone interfac - - wb_out : out wb_master_out_type; - wb_in : in wb_master_in_type - -); -end sc2wb; - -architecture rtl of sc2wb is - --- --- Wishbone specific signals --- - signal wb_data : std_logic_vector(31 downto 0); -- output of wishbone module - signal wb_addr : std_logic_vector(7 downto 0); -- wishbone read/write address - signal wb_rd, wb_wr, wb_bsy : std_logic; - signal wb_rd_reg, wb_wr_reg : std_logic; - -begin - --- --- Wishbone interface --- - - -- just use the SimpCon rd/wr - wb_rd <= rd; - wb_wr <= wr; - - rd_data <= wb_data; - - wb_out.adr_o <= wb_addr; - - rdy_cnt <= "11" when wb_bsy='1' else "00"; - --- --- Handle the Wishbone protocoll. --- rd and wr request are registered for additional WSs. --- -process(clk, reset) -begin - if (reset='1') then - - wb_addr <= (others => '0'); - - wb_out.stb_o <= '0'; - wb_out.cyc_o <= '0'; - wb_out.we_o <= '0'; - - wb_rd_reg <= '0'; - wb_wr_reg <= '0'; - wb_bsy <= '0'; - - elsif rising_edge(clk) then - - -- read request: - -- address is registered from SimpCon address and valid in the next - -- cycle - if wb_rd='1' then - -- store read address - wb_addr(M_ADDR_SIZE-1 downto addr_bits) <= (others => '0'); - wb_addr(addr_bits-1 downto 0) <= address; - - wb_out.stb_o <= '1'; - wb_out.cyc_o <= '1'; - wb_out.we_o <= '0'; - wb_rd_reg <= '1'; - wb_bsy <= '1'; - elsif wb_rd_reg='1' then - -- do we need a timeout??? - if wb_in.ack_i='1' then - wb_out.stb_o <= '0'; - wb_out.cyc_o <= '0'; - wb_rd_reg <= '0'; - wb_bsy <= '0'; - wb_data <= wb_in.dat_i; - end if; - -- write request - -- address and data are stored and valid in - -- the next cycle - elsif wb_wr='1' then - -- store write address - wb_addr(M_ADDR_SIZE-1 downto addr_bits) <= (others => '0'); - wb_addr(addr_bits-1 downto 0) <= address; - - -- this keeps the write data registered, - -- but costs a latency of one cycle. - wb_out.dat_o <= wr_data; - - wb_out.stb_o <= '1'; - wb_out.cyc_o <= '1'; - wb_out.we_o <= '1'; - wb_wr_reg <= '1'; - wb_bsy <= '1'; - elsif wb_wr_reg='1' then - -- do we need a timeout??? - if wb_in.ack_i='1' then - wb_out.stb_o <= '0'; - wb_out.cyc_o <= '0'; - wb_out.we_o <= '0'; - wb_wr_reg <= '0'; - wb_bsy <= '0'; - end if; - end if; - - end if; -end process; - -end rtl; Index: trunk/vhdl/fifo.vhd =================================================================== --- trunk/vhdl/fifo.vhd (revision 25) +++ trunk/vhdl/fifo.vhd (nonexistent) @@ -1,158 +0,0 @@ --- --- fifo.vhd --- --- simple fifo --- --- uses FF and every rd or wr has to 'bubble' through the hole fifo. --- --- Author: Martin Schoeberl martin.schoeberl@chello.at --- --- --- resources on ACEX1K --- --- (width+2)*depth-1 LCs --- --- --- 2002-01-06 first working version --- 2002-11-03 a signal for reaching threshold --- 2005-02-20 change entity order for modelsim vcom --- - -library ieee; -use ieee.std_logic_1164.all; - -entity fifo_elem is - -generic (width : integer); -port ( - clk : in std_logic; - reset : in std_logic; - - din : in std_logic_vector(width-1 downto 0); - dout : out std_logic_vector(width-1 downto 0); - - rd : in std_logic; - wr : in std_logic; - - rd_prev : out std_logic; - full : out std_logic -); -end fifo_elem; - -architecture rtl of fifo_elem is - - signal buf : std_logic_vector(width-1 downto 0); - signal f : std_logic; - -begin - - dout <= buf; - -process(clk, reset, f) - -begin - - full <= f; - - if (reset='1') then - - buf <= (others => '0'); - f <= '0'; - rd_prev <= '0'; - - elsif rising_edge(clk) then - - rd_prev <= '0'; - if f='0' then - if wr='1' then - rd_prev <= '1'; - buf <= din; - f <= '1'; - end if; - else - if rd='1' then - f <= '0'; - end if; - end if; - - end if; - -end process; - -end rtl; - -library ieee; -use ieee.std_logic_1164.all; - -entity fifo is - -generic (width : integer := 8; depth : integer := 4; thres : integer := 2); -port ( - clk : in std_logic; - reset : in std_logic; - - din : in std_logic_vector(width-1 downto 0); - dout : out std_logic_vector(width-1 downto 0); - - rd : in std_logic; - wr : in std_logic; - - empty : out std_logic; - full : out std_logic; - half : out std_logic -); -end fifo ; - -architecture rtl of fifo is - -component fifo_elem is - -generic (width : integer); -port ( - clk : in std_logic; - reset : in std_logic; - - din : in std_logic_vector(width-1 downto 0); - dout : out std_logic_vector(width-1 downto 0); - - rd : in std_logic; - wr : in std_logic; - - rd_prev : out std_logic; - full : out std_logic -); -end component; - - signal r, w, rp, f : std_logic_vector(depth-1 downto 0); - type d_array is array (0 to depth-1) of std_logic_vector(width-1 downto 0); - signal di, do : d_array; - - - -begin - - - g1: for i in 0 to depth-1 generate - - f1: fifo_elem generic map (width) - port map (clk, reset, di(i), do(i), r(i), w(i), rp(i), f(i)); - - x: if i "MAXIMIZE_SPEED=5", - lpm_pipeline => 16, - lpm_representation => "SIGNED", - lpm_type => "LPM_MULT", - lpm_widtha => 32, - lpm_widthb => 32, - lpm_widthp => 64, - lpm_widths => 1 - ) - PORT MAP ( - dataa => opa, - datab => opb, - clock => clk, - result => sub_wire0 - ); - - mul_res <= unsigned(sub_wire0); - - - -process(clk, reset) - -begin - if reset='1' then - acc <= (others => '0'); - - elsif rising_edge(clk) then - - case state is - - when idle => - if start='1' then - state <= mul; - cnt <= "010010"; -- for shure - end if; - - when mul => - cnt <= cnt-1; - if cnt=0 then - state <= add; - end if; - - when add => - acc <= acc + mul_res; - state <= idle; - - end case; - - if clear='1' then - acc <= (others => '0'); - end if; - - end if; - - result <= std_logic_vector(acc); - -end process; - -end rtl; - - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -entity sc_mac is -generic (addr_bits : integer; scale : integer := 16); - -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) - -); -end sc_mac; - -architecture rtl of sc_mac is - - signal opa, opb : std_logic_vector(31 downto 0); - signal result : std_logic_vector(63 downto 0); - - signal start : std_logic; - signal clear : std_logic; - -begin - - rdy_cnt <= "00"; -- no wait states, we are hopefully fast enough - - cm: entity work.mac - port map( - clk => clk, - reset => reset, - - opa => opa, - opb => opb, - start => start, - clear => clear, - result => result - ); - --- --- SimpCon read and write --- -process(clk, reset) - -begin - - if reset='1' then - rd_data <= (others => '0'); - - elsif rising_edge(clk) then - - start <= '0'; - if wr='1' then - if address(0)='0' then - opa <= wr_data; - else - opb <= wr_data; - start <= '1'; - end if; - end if; - - -- get MAC result scaled by 'scale' and clear the accumulator - clear <= '0'; - if rd='1' then --- if address(0)='0' then - rd_data <= result(31+scale downto scale); - clear <= '1'; --- else --- rd_data <= result(63 downto 32); --- end if; - end if; - - end if; -end process; - - -end rtl; Index: trunk/vhdl/sc_test_top.vhd =================================================================== --- trunk/vhdl/sc_test_top.vhd (revision 25) +++ trunk/vhdl/sc_test_top.vhd (nonexistent) @@ -1,110 +0,0 @@ --- --- scio_test_top.vhd --- --- The top level to test SimpCon IO devices. --- Do the address decoding here for the various slaves. --- --- Author: Martin Schoeberl martin@jopdesign.com --- --- --- 2005-11-30 first version with two simple test slaves --- --- --- - - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.jop_types.all; - -entity scio is -generic (addr_bits : 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) - -); -end scio; - -architecture rtl of scio is - - constant SLAVE_CNT : integer := 4; - -- SLAVE_CNT <= 2**DECODE_BITS - constant DECODE_BITS : integer := 2; - -- number of bits that can be used inside the slave - constant SLAVE_ADDR_BITS : integer := 4; - - type slave_bit is array(0 to SLAVE_CNT-1) of std_logic; - signal sc_rd, sc_wr : slave_bit; - - type slave_dout is array(0 to SLAVE_CNT-1) of std_logic_vector(31 downto 0); - signal sc_dout : slave_dout; - - type slave_rdy_cnt is array(0 to SLAVE_CNT-1) of unsigned(1 downto 0); - signal sc_rdy_cnt : slave_rdy_cnt; - - signal sel, sel_reg : integer range 0 to 2**DECODE_BITS-1; - -begin - - assert SLAVE_CNT <= 2**DECODE_BITS report "Wrong constant in scio"; - - sel <= to_integer(unsigned(address(SLAVE_ADDR_BITS+DECODE_BITS-1 downto SLAVE_ADDR_BITS))); - - -- What happens when sel_reg > SLAVE_CNT-1?? - rd_data <= sc_dout(sel_reg); - rdy_cnt <= sc_rdy_cnt(sel_reg); - - -- - -- Connect SLAVE_CNT simple test slaves - -- - gsl: for i in 0 to SLAVE_CNT-1 generate - - sc_rd(i) <= rd when i=sel else '0'; - sc_wr(i) <= wr when i=sel else '0'; - - scsl: entity work.sc_test_slave - generic map ( - -- shall we use less address bits inside the slaves? - addr_bits => SLAVE_ADDR_BITS - ) - port map ( - clk => clk, - reset => reset, - - address => address(SLAVE_ADDR_BITS-1 downto 0), - wr_data => wr_data, - rd => sc_rd(i), - wr => sc_wr(i), - rd_data => sc_dout(i), - rdy_cnt => sc_rdy_cnt(i) - ); - end generate; - - -- - -- Register read mux selector - -- - process(clk, reset) - begin - if (reset='1') then - sel_reg <= 0; - elsif rising_edge(clk) then - if rd='1' then - sel_reg <= sel; - end if; - end if; - end process; - - -end rtl; Index: trunk/vhdl/sc2avalon.vhd =================================================================== --- trunk/vhdl/sc2avalon.vhd (revision 25) +++ trunk/vhdl/sc2avalon.vhd (nonexistent) @@ -1,215 +0,0 @@ --- --- sc2avalon.vhd --- --- SimpCon to Avalon bridge --- --- Author: Martin Schoeberl martin@jopdesign.com --- --- 2006-08-10 first version --- - -Library IEEE; -use IEEE.std_logic_1164.all; -use ieee.numeric_std.all; - -entity sc2avalon is -generic (addr_bits : integer); - -port ( - - clk, reset : in std_logic; - --- SimpCon interface - - sc_address : in std_logic_vector(addr_bits-1 downto 0); - sc_wr_data : in std_logic_vector(31 downto 0); - sc_rd, sc_wr : in std_logic; - sc_rd_data : out std_logic_vector(31 downto 0); - sc_rdy_cnt : out unsigned(1 downto 0); - --- Avalon interface - - av_address : out std_logic_vector(addr_bits-1+2 downto 0); - av_writedata : out std_logic_vector(31 downto 0); - av_byteenable : out std_logic_vector(3 downto 0); - av_readdata : in std_logic_vector(31 downto 0); - av_read : out std_logic; - av_write : out std_logic; - av_waitrequest : in std_logic - -); -end sc2avalon; - -architecture rtl of sc2avalon is - - type state_type is (idl, rd, rdw, wr, wrw); - signal state : state_type; - signal next_state : state_type; - - signal reg_addr : std_logic_vector(addr_bits-1 downto 0); - signal reg_wr_data : std_logic_vector(31 downto 0); - signal reg_rd_data : std_logic_vector(31 downto 0); - - signal reg_rd : std_logic; - signal reg_wr : std_logic; - -begin - - av_byteenable <= "1111"; -- we use only 32 bit transfers - av_address(1 downto 0) <= "00"; - - sc_rd_data <= reg_rd_data; - - --- --- Register memory address, write data and read data --- -process(clk, reset) -begin - if reset='1' then - - reg_addr <= (others => '0'); - reg_wr_data <= (others => '0'); - - elsif rising_edge(clk) then - - if sc_rd='1' or sc_wr='1' then - reg_addr <= sc_address; - end if; - if sc_wr='1' then - reg_wr_data <= sc_wr_data; - end if; - - end if; -end process; - - --- --- The address MUX slightly violates the Avalon --- specification. The address changes from the sc_address --- to the registerd address in the second cycle. However, --- as both registers contain the same value there should be --- no real glitch. For synchronous peripherals this is not --- an issue. For asynchronous peripherals (SRAM) the possible --- glitch should be short enough to be not seen on the output --- pins. --- -process(sc_rd, sc_wr, sc_address, reg_addr) -begin - if sc_rd='1' or sc_wr='1' then - av_address(addr_bits-1+2 downto 2) <= sc_address; - else - av_address(addr_bits-1+2 downto 2) <= reg_addr; - end if; -end process; - --- Same game for the write data and write/read control -process(sc_wr, sc_wr_data, reg_wr_data) -begin - if sc_wr='1' then - av_writedata <= sc_wr_data; - else - av_writedata <= reg_wr_data; - end if; -end process; - - av_write <= sc_wr or reg_wr; - av_read <= sc_rd or reg_rd; - - - --- --- next state logic --- --- At the moment we do not support back to back read --- or write. We don't need it for JOP, right? --- If needed just copy the idl code to rd and wr. --- -process(state, sc_rd, sc_wr, av_waitrequest) - -begin - - next_state <= state; - - case state is - - when idl => - if sc_rd='1' then - if av_waitrequest='0' then - next_state <= rd; - else - next_state <= rdw; - end if; - elsif sc_wr='1' then - if av_waitrequest='0' then - next_state <= wr; - else - next_state <= wrw; - end if; - end if; - - when rdw => - if av_waitrequest='0' then - next_state <= rd; - end if; - - when rd => - next_state <= idl; - - when wrw => - if av_waitrequest='0' then - next_state <= wr; - end if; - - when wr => - next_state <= idl; - - - end case; - -end process; - --- --- state machine register --- and output register --- -process(clk, reset) - -begin - if (reset='1') then - state <= idl; - reg_rd_data <= (others => '0'); - sc_rdy_cnt <= "00"; - reg_rd <= '0'; - reg_wr <= '0'; - - elsif rising_edge(clk) then - - state <= next_state; - sc_rdy_cnt <= "00"; - reg_rd <= '0'; - reg_wr <= '0'; - - case next_state is - - when idl => - - when rdw => - sc_rdy_cnt <= "11"; - reg_rd <= '1'; - - when rd => - reg_rd_data <= av_readdata; - - when wrw => - sc_rdy_cnt <= "11"; - reg_wr <= '1'; - - when wr => - - end case; - - end if; -end process; - -end rtl; Index: trunk/vhdl/sc_sigdel.vhd =================================================================== --- trunk/vhdl/sc_sigdel.vhd (revision 25) +++ trunk/vhdl/sc_sigdel.vhd (nonexistent) @@ -1,216 +0,0 @@ --- --- sc_sigdel.vhd --- --- A simple sigma-delta ADC and PWM DAC for the SimpCon interface --- --- Author: Martin Schoeberl martin@jopdesign.com --- --- --- resources on Cyclone --- --- xx LCs, max xx MHz --- --- --- 2006-04-16 first version --- --- todo: --- --- - - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.jop_config.all; - -entity sc_sigdel is -generic (addr_bits : integer; fsamp : 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); - --- io ports - sdi : in std_logic; -- input of the sigma-delta ADC - sdo : out std_logic; -- output of the sigma-delta ADC - dac : out std_logic -- output of the PWM DAC -); -end sc_sigdel; - -architecture rtl of sc_sigdel is - - -- we use a 10MHz sigma-delta clock - constant SDF : integer := 10000000; - constant SDTICK : integer := (clk_freq+SDF/2)/SDF; - signal clksd : integer range 0 to SDTICK; - constant CNT_MAX : integer := (SDF+fsamp/2)/fsamp; - signal cnt : integer range 0 to CNT_MAX; - signal dac_cnt : integer range 0 to CNT_MAX; - - signal rx_d : std_logic; - signal serdata : std_logic; - signal spike : std_logic_vector(2 downto 0); -- sync in, filter - signal sum : unsigned(15 downto 0); - signal delta : unsigned(15 downto 0); - - signal audio_in : std_logic_vector(15 downto 0); - signal audio_out : std_logic_vector(15 downto 0); - - signal sample_rdy : std_logic; - signal sample_rd : std_logic; - signal sample_wr : std_logic; - -begin - - rdy_cnt <= "00"; -- no wait states - -- we use only 16 bits - -- bit 31 is the ready bit - rd_data(30 downto 16) <= (others => '0'); - --- --- The registered MUX is all we need for a SimpCon read. --- The read data is stored in registered rd_data. --- -process(clk, reset) -begin - - if (reset='1') then - rd_data(15 downto 0) <= (others => '0'); - rd_data(31) <= '0'; - sample_rd <= '0'; - elsif rising_edge(clk) then - - sample_rd <= '0'; - if rd='1' then - rd_data(15 downto 0) <= audio_in; - rd_data(31) <= sample_rdy; - sample_rd <= '1'; - end if; - end if; - -end process; - - --- --- SimpCon write is very simple --- -process(clk, reset) - -begin - - if (reset='1') then - audio_out <= (others => '0'); - sample_wr <= '0'; - elsif rising_edge(clk) then - sample_wr <= '0'; - if wr='1' then - audio_out <= wr_data(15 downto 0); - sample_wr <= '1'; - end if; - end if; -end process; - - --- --- Here we go with the simple sigma-delta converter: --- -process(clk, reset) - -begin - - if reset='1' then - - spike <= "000"; - clksd <= 0; - cnt <= 0; - sum <= (others => '0'); - sample_rdy <= '0'; - - elsif rising_edge(clk) then - - if clksd=0 then - clksd <= SDTICK-1; - spike(0) <= sdi; - spike(2 downto 1) <= spike(1 downto 0); - sdo <= not rx_d; - serdata <= rx_d; - - if cnt=0 then - cnt <= CNT_MAX-1; - audio_in <= std_logic_vector(sum); - sample_rdy <= '1'; - sum <= (others => '0'); - -- BTW: we miss one sigma-delta sample here... - else - cnt <= cnt-1; - if serdata='1' then - sum <= sum+1; - end if; - end if; - else - clksd <= clksd-1; - end if; - - -- reset ready flag after read - if sample_rd='1' then - sample_rdy <= '0'; - end if; - - end if; - -end process; - --- --- filter input (majority voting) --- - 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; - --- --- and here comes the primitive version of the --- digital delta part - not really delta... --- it's just a simple PWM... --- now do it with the main clock... --- -process(clk, reset) - -begin - if reset='1' then - delta <= (others => '0'); - dac <= '0'; - dac_cnt <= 0; - elsif rising_edge(clk) then - - if dac_cnt=0 then - dac_cnt <= CNT_MAX-1; - delta <= unsigned(audio_out); - else - dac_cnt <= dac_cnt-1; - dac <= '0'; - if delta /= 0 then - delta <= delta-1; - dac <= '1'; - end if; - end if; - - end if; -end process; - -end rtl; Index: trunk/vhdl/sc_sram32.vhd =================================================================== --- trunk/vhdl/sc_sram32.vhd (revision 25) +++ trunk/vhdl/sc_sram32.vhd (nonexistent) @@ -1,274 +0,0 @@ --- --- sc_sram32.vhd --- --- SimpCon compliant external memory interface --- for 32-bit SRAM (e.g. Cyclone board, Spartan-3 Starter Kit) --- --- Connection between mem_sc and the external memory bus --- --- memory mapping --- --- 000000-x7ffff external SRAM (w mirror) max. 512 kW (4*4 MBit) --- --- RAM: 32 bit word --- --- --- 2005-11-22 first version --- 2007-03-17 changed SimpCon to records --- - -Library IEEE; -use IEEE.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.jop_types.all; -use work.sc_pack.all; - -entity sc_mem_if is -generic (ram_ws : integer; addr_bits : integer); - -port ( - - clk, reset : in std_logic; - --- --- SimpCon memory interface --- - sc_mem_out : in sc_mem_out_type; - sc_mem_in : out sc_in_type; - --- memory interface - - ram_addr : out std_logic_vector(addr_bits-1 downto 0); - ram_dout : out std_logic_vector(31 downto 0); - ram_din : in std_logic_vector(31 downto 0); - ram_dout_en : out std_logic; - ram_ncs : out std_logic; - ram_noe : out std_logic; - ram_nwe : out std_logic - -); -end sc_mem_if; - -architecture rtl of sc_mem_if is - --- --- signals for mem interface --- - type state_type is ( - idl, rd1, rd2, - wr1 - ); - signal state : state_type; - signal next_state : state_type; - - signal nwr_int : std_logic; - signal wait_state : unsigned(3 downto 0); - signal cnt : unsigned(1 downto 0); - - signal dout_ena : std_logic; - signal rd_data_ena : std_logic; - -begin - - assert MEM_ADDR_SIZE>=addr_bits report "Too less address bits"; - ram_dout_en <= dout_ena; - - sc_mem_in.rdy_cnt <= cnt; - --- --- Register memory address, write data and read data --- -process(clk, reset) -begin - if reset='1' then - - ram_addr <= (others => '0'); - ram_dout <= (others => '0'); - sc_mem_in.rd_data <= (others => '0'); - - elsif rising_edge(clk) then - - if sc_mem_out.rd='1' or sc_mem_out.wr='1' then - ram_addr <= sc_mem_out.address(addr_bits-1 downto 0); - end if; - if sc_mem_out.wr='1' then - ram_dout <= sc_mem_out.wr_data; - end if; - if rd_data_ena='1' then - sc_mem_in.rd_data <= ram_din; - end if; - - end if; -end process; - --- --- 'delay' nwe 1/2 cycle -> change on falling edge --- -process(clk, reset) - -begin - if (reset='1') then - ram_nwe <= '1'; - elsif falling_edge(clk) then - ram_nwe <= nwr_int; - end if; - -end process; - - --- --- next state logic --- -process(state, sc_mem_out.rd, sc_mem_out.wr, wait_state) - -begin - - next_state <= state; - - - case state is - - when idl => - if sc_mem_out.rd='1' then - if ram_ws=0 then - -- then we omit state rd1! - next_state <= rd2; - else - next_state <= rd1; - end if; - elsif sc_mem_out.wr='1' then - next_state <= wr1; - end if; - - -- the WS state - when rd1 => - if wait_state=2 then - next_state <= rd2; - end if; - - -- last read state - when rd2 => - next_state <= idl; - -- This should do to give us a pipeline - -- level of 2 for read - if sc_mem_out.rd='1' then - if ram_ws=0 then - -- then we omit state rd1! - next_state <= rd2; - else - next_state <= rd1; - end if; - elsif sc_mem_out.wr='1' then - next_state <= wr1; - end if; - - -- the WS state - when wr1 => --- TODO: check what happens on ram_ws=0 --- TODO: do we need a write pipelining? --- not at the moment, but parhaps later when --- we write the stack content to main memory - if wait_state=1 then - next_state <= idl; - end if; - - end case; - -end process; - --- --- state machine register --- output register --- -process(clk, reset) - -begin - if (reset='1') then - state <= idl; - dout_ena <= '0'; - ram_ncs <= '1'; - ram_noe <= '1'; - rd_data_ena <= '0'; - elsif rising_edge(clk) then - - state <= next_state; - dout_ena <= '0'; - ram_ncs <= '1'; - ram_noe <= '1'; - rd_data_ena <= '0'; - - case next_state is - - when idl => - - -- the wait state - when rd1 => - ram_ncs <= '0'; - ram_noe <= '0'; - - -- last read state - when rd2 => - ram_ncs <= '0'; - ram_noe <= '0'; - rd_data_ena <= '1'; - - - -- the WS state - when wr1 => - ram_ncs <= '0'; - dout_ena <= '1'; - - end case; - - end if; -end process; - --- --- nwr combinatorial processing --- for the negativ edge --- -process(next_state, state) -begin - - nwr_int <= '1'; - if next_state=wr1 then - nwr_int <= '0'; - end if; - -end process; - --- --- wait_state processing --- cs delay, dout enable --- -process(clk, reset) -begin - if (reset='1') then - wait_state <= (others => '1'); - cnt <= "00"; - elsif rising_edge(clk) then - - wait_state <= wait_state-1; - - cnt <= "11"; - if next_state=idl then - cnt <= "00"; - -- if wait_state<4 then - elsif wait_state(3 downto 2)="00" then - cnt <= wait_state(1 downto 0)-1; - end if; - - if sc_mem_out.rd='1' or sc_mem_out.wr='1' then - wait_state <= to_unsigned(ram_ws+1, 4); - if ram_ws<3 then - cnt <= to_unsigned(ram_ws+1, 2); - else - cnt <= "11"; - end if; - end if; - - end if; -end process; - -end rtl; Index: trunk/vhdl/sc_test_slave.vhd =================================================================== --- trunk/vhdl/sc_test_slave.vhd (revision 25) +++ trunk/vhdl/sc_test_slave.vhd (nonexistent) @@ -1,100 +0,0 @@ --- --- sc_test_slave.vhd --- --- A simple test slave for the SimpCon interface --- --- Author: Martin Schoeberl martin@jopdesign.com --- --- --- resources on Cyclone --- --- xx LCs, max xx MHz --- --- --- 2005-11-29 first version --- --- todo: --- --- - - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -entity sc_test_slave is -generic (addr_bits : 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) - -); -end sc_test_slave; - -architecture rtl of sc_test_slave is - - signal xyz : std_logic_vector(31 downto 0); - signal cnt : unsigned(31 downto 0); - -begin - - 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 - - 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 <= std_logic_vector(cnt); - else - rd_data <= xyz; - end if; - end if; - end if; - -end process; - - --- --- SimpCon write is very simple --- -process(clk, reset) - -begin - - if (reset='1') then - xyz <= (others => '0'); - cnt <= (others => '0'); - - elsif rising_edge(clk) then - - if wr='1' then - xyz <= wr_data; - end if; - - cnt <= cnt+1; - - end if; - -end process; - - -end rtl; Index: trunk/vhdl/sc_sram16.vhd =================================================================== --- trunk/vhdl/sc_sram16.vhd (revision 25) +++ trunk/vhdl/sc_sram16.vhd (nonexistent) @@ -1,377 +0,0 @@ --- --- sc_sram16.vhd --- --- SimpCon compliant external memory interface --- for 16-bit SRAM (e.g. Altera DE2 board) --- --- High 16-bit word is at lower address --- --- Connection between mem_sc and the external memory bus --- --- memory mapping --- --- 000000-x7ffff external SRAM (w mirror) max. 512 kW (4*4 MBit) --- --- RAM: 16 bit word --- --- --- 2006-08-01 Adapted from sc_ram32.vhd --- 2006-08-16 Rebuilding the already working (lost) version --- Use wait_state, din register without MUX --- 2007-06-04 changed SimpCon to records --- 2007-09-09 Additional input register for high data (correct SimpCon violation) --- - -Library IEEE; -use IEEE.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.jop_types.all; -use work.sc_pack.all; - -entity sc_mem_if is -generic (ram_ws : integer; addr_bits : integer); - -port ( - - clk, reset : in std_logic; - --- --- SimpCon memory interface --- - sc_mem_out : in sc_mem_out_type; - sc_mem_in : out sc_in_type; - --- memory interface - - ram_addr : out std_logic_vector(addr_bits-1 downto 0); - ram_dout : out std_logic_vector(15 downto 0); - ram_din : in std_logic_vector(15 downto 0); - ram_dout_en : out std_logic; - ram_ncs : out std_logic; - ram_noe : out std_logic; - ram_nwe : out std_logic - -); -end sc_mem_if; - -architecture rtl of sc_mem_if is - --- --- signals for mem interface --- - type state_type is ( - idl, rd1_h, rd2_h, rd1_l, rd2_l, - wr_h, wr_idl, wr_l - ); - signal state : state_type; - signal next_state : state_type; - - signal nwr_int : std_logic; - signal wait_state : unsigned(3 downto 0); - signal cnt : unsigned(1 downto 0); - - signal dout_ena : std_logic; - signal rd_data_ena_h : std_logic; - signal rd_data_ena_l : std_logic; - signal inc_addr : std_logic; - signal wr_low : std_logic; - - signal ram_dout_low : std_logic_vector(15 downto 0); - signal ram_din_high : std_logic_vector(15 downto 0); - - signal ram_din_reg : std_logic_vector(31 downto 0); - -begin - - ram_dout_en <= dout_ena; - - sc_mem_in.rdy_cnt <= cnt; - --- --- Register memory address, write data and read data --- -process(clk, reset) -begin - if reset='1' then - - ram_addr <= (others => '0'); - ram_dout <= (others => '0'); - ram_dout_low <= (others => '0'); - - elsif rising_edge(clk) then - - if sc_mem_out.rd='1' or sc_mem_out.wr='1' then - ram_addr <= sc_mem_out.address(addr_bits-2 downto 0) & "0"; - end if; - if inc_addr='1' then - ram_addr(0) <= '1'; - end if; - if sc_mem_out.wr='1' then - ram_dout <= sc_mem_out.wr_data(31 downto 16); - ram_dout_low <= sc_mem_out.wr_data(15 downto 0); - end if; - if wr_low='1' then - ram_dout <= ram_dout_low; - end if; - -- use an addtional input register to adhire the SimpCon spec - -- to not change rd_data untill the full new word is available - -- results in input MUX at RAM data input - if rd_data_ena_h='1' then - ram_din_high <= ram_din; - end if; - if rd_data_ena_l='1' then - -- move first word to higher half - ram_din_reg(31 downto 16) <= ram_din_high; - -- read second word - ram_din_reg(15 downto 0) <= ram_din; - end if; - - end if; -end process; - - sc_mem_in.rd_data <= ram_din_reg; - --- --- 'delay' nwe 1/2 cycle -> change on falling edge --- -process(clk, reset) - -begin - if (reset='1') then - ram_nwe <= '1'; - elsif falling_edge(clk) then - ram_nwe <= nwr_int; - end if; - -end process; - - --- --- next state logic --- -process(state, sc_mem_out.rd, sc_mem_out.wr, wait_state) - -begin - - next_state <= state; - - case state is - - when idl => - if sc_mem_out.rd='1' then - if ram_ws=0 then - -- then we omit state rd1! - next_state <= rd2_h; - else - next_state <= rd1_h; - end if; - elsif sc_mem_out.wr='1' then - next_state <= wr_h; - end if; - - -- the WS state - when rd1_h => - if wait_state=2 then - next_state <= rd2_h; - end if; - - when rd2_h => - -- go to read low word - if ram_ws=0 then - -- then we omit state rd1! - next_state <= rd2_l; - else - next_state <= rd1_l; - end if; - - -- the WS state - when rd1_l => - if wait_state=2 then - next_state <= rd2_l; - end if; - - -- last read state - when rd2_l => - next_state <= idl; - -- This should do to give us a pipeline - -- level of 2 for read - if sc_mem_out.rd='1' then - if ram_ws=0 then - -- then we omit state rd1! - next_state <= rd2_h; - else - next_state <= rd1_h; - end if; - elsif sc_mem_out.wr='1' then - next_state <= wr_h; - end if; - - -- the WS state - when wr_h => --- TODO: check what happens on ram_ws=0 --- TODO: do we need a write pipelining? --- not at the moment, but parhaps later when --- we write the stack content to main memory - if wait_state=1 then - next_state <= wr_idl; - end if; - - -- one idle state for nwr to go high - when wr_idl => - next_state <= wr_l; - - -- the WS state - when wr_l => - if wait_state=1 then - next_state <= idl; - end if; - - end case; - -end process; - --- --- state machine register --- output register --- -process(clk, reset) - -begin - if (reset='1') then - state <= idl; - dout_ena <= '0'; - ram_ncs <= '1'; - ram_noe <= '1'; - rd_data_ena_h <= '0'; - rd_data_ena_l <= '0'; - inc_addr <= '0'; - wr_low <= '0'; - elsif rising_edge(clk) then - - state <= next_state; - dout_ena <= '0'; - ram_ncs <= '1'; - ram_noe <= '1'; - rd_data_ena_h <= '0'; - rd_data_ena_l <= '0'; - inc_addr <= '0'; - wr_low <= '0'; - - case next_state is - - when idl => - - -- the wait state - when rd1_h => - ram_ncs <= '0'; - ram_noe <= '0'; - - -- high word last read state - when rd2_h => - ram_ncs <= '0'; - ram_noe <= '0'; - rd_data_ena_h <= '1'; - inc_addr <= '1'; - - -- the wait state - when rd1_l => - ram_ncs <= '0'; - ram_noe <= '0'; - - -- low word last read state - when rd2_l => - ram_ncs <= '0'; - ram_noe <= '0'; - rd_data_ena_l <= '1'; - - -- the WS state - when wr_h => - ram_ncs <= '0'; - dout_ena <= '1'; - - -- high word last write state - when wr_idl => - ram_ncs <= '1'; - dout_ena <= '1'; - inc_addr <= '1'; - wr_low <= '1'; - - -- the WS state - when wr_l => - ram_ncs <= '0'; - dout_ena <= '1'; - - end case; - - end if; -end process; - --- --- nwr combinatorial processing --- for the negativ edge --- -process(next_state, state) -begin - - nwr_int <= '1'; - -- this is the 'correct' version wich needs - -- at minimum 2 cycles for the RAM access --- if (state=wr_l and next_state=wr_l) or --- (state=wr_h and next_state=wr_h) then - -- Slightly out of the SRAM spec. nwr goes - -- low befor ncs to allow single cycle - -- access - if next_state=wr_l or next_state=wr_h then - - nwr_int <= '0'; - end if; - -end process; - --- --- wait_state processing --- -process(clk, reset) -begin - if (reset='1') then - wait_state <= (others => '1'); - cnt <= "00"; - elsif rising_edge(clk) then - - wait_state <= wait_state-1; - - cnt <= "11"; - if next_state=idl then - cnt <= "00"; - end if; - - if sc_mem_out.rd='1' or sc_mem_out.wr='1' then - wait_state <= to_unsigned(ram_ws+1, 4); - end if; - - if state=rd2_h or state=wr_idl then - wait_state <= to_unsigned(ram_ws+1, 4); - if ram_ws<3 then - cnt <= to_unsigned(ram_ws+1, 2); - else - cnt <= "11"; - end if; - end if; - - if state=rd1_l or state=rd2_l or state=wr_l then - -- take care for pipelined cach transfer - -- there is no idl state and cnt should - -- go back to "11" - if sc_mem_out.rd='0' and sc_mem_out.wr='0' then - -- if wait_state<4 then - if wait_state(3 downto 2)="00" then - cnt <= wait_state(1 downto 0)-1; - end if; - end if; - end if; - - end if; -end process; - -end rtl; Index: trunk/vhdl/sc_uart_tal.vhd =================================================================== --- trunk/vhdl/sc_uart_tal.vhd (revision 25) +++ trunk/vhdl/sc_uart_tal.vhd (nonexistent) @@ -1,404 +0,0 @@ --- --- sc_uart_tal.vhd --- --- 8-N-1 serial interface --- conf_reg: baud_rate and 2400, HW hs on/off, DTR --- default: 101 => baud_rate, no HW hs, DTR on --- --- wr, rd should be one cycle long => trde, rdrf goes 0 one cycle later --- --- Author: Martin Schoeberl martin@jopdesign.com --- --- --- resources on ACEX1K30-3 --- --- 100 LCs, max 90 MHz --- --- resetting rts with fifo_full-1 works with C program on pc --- but not with javax.comm: sends some more bytes after deassert --- of rts (16 byte blocks regardless of rts). --- Try to stop with half full fifo. --- --- todo: --- --- --- 2000-12-02 first working version --- 2002-01-06 changed tdr and rdr to fifos. --- 2002-05-15 changed clkdiv calculation --- 2002-11-01 don't wait if read fifo is full, just drop the byte --- 2002-11-03 use threshold in fifo to reset rts --- don't send if cts is '0' --- 2002-11-08 rx fifo to 20 characters and stop after 4 --- 2003-07-05 new IO standard, change cts/rts to neg logic --- 2003-09-19 sync ncts in! --- 2004-03-23 two stop bits --- 2004-04-23 Version for TAL --- 2004-04-26 DTR is inverted conf_reg(0) => '1' means set DTR! --- 2005-02-28 Changed default conf_reg to no hand shake (ignore ncts) --- 2005-12-27 change interface to SimpCon --- 2006-08-13 use 3 FFs for the rxd input at clk --- - - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -entity sc_uart_tal is - -generic (addr_bits : integer; - clk_freq : integer; - baud_rate : integer; - txf_depth : integer; txf_thres : integer; - rxf_depth : integer; rxf_thres : 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); - - txd : out std_logic; - rxd : in std_logic; - ncts : in std_logic; - nrts : out std_logic; - dtr : out std_logic -); -end sc_uart_tal; - -architecture rtl of sc_uart_tal is - -component fifo is - -generic (width : integer; depth : integer; thres : integer); -port ( - clk : in std_logic; - reset : in std_logic; - - din : in std_logic_vector(width-1 downto 0); - dout : out std_logic_vector(width-1 downto 0); - - rd : in std_logic; - wr : in std_logic; - - empty : out std_logic; - full : out std_logic; - half : out std_logic -); -end component; - --- --- signals for uart connection --- - signal ua_dout : std_logic_vector(7 downto 0); - signal ua_wr, tdre : std_logic; - signal ua_rd, rdrf : std_logic; - - signal conf_reg : std_logic_vector(2 downto 0); - - type uart_tx_state_type is (s0, s1); - signal uart_tx_state : uart_tx_state_type; - - signal tf_dout : std_logic_vector(7 downto 0); -- fifo out - signal tf_rd : std_logic; - signal tf_empty : std_logic; - signal tf_full : std_logic; - signal tf_half : std_logic; - - signal ncts_buf : std_logic_vector(2 downto 0); -- sync in - signal ncts_in : std_logic; - - signal tsr : std_logic_vector(9 downto 0); -- tx shift register - - signal tx_clk : std_logic; - - - type uart_rx_state_type is (s0, s1, s2); - signal uart_rx_state : uart_rx_state_type; - - signal rf_wr : std_logic; - signal rf_empty : std_logic; - signal rf_full : std_logic; - signal rf_half : std_logic; - - signal rxd_reg : std_logic_vector(2 downto 0); - signal rx_buf : std_logic_vector(2 downto 0); -- sync in, filter - signal rx_d : std_logic; -- rx serial data - - signal rsr : std_logic_vector(9 downto 0); -- rx shift register - - signal rx_clk : std_logic; - signal rx_clk_ena : std_logic; - - constant clk16_fast_cnt : integer := (clk_freq/baud_rate+8)/16-1; - constant clk16_slow_cnt : integer := (clk_freq/2400+8)/16-1; - - signal clk16_cnt : integer range 0 to clk16_slow_cnt; - - -begin - - rdy_cnt <= "00"; -- no wait states - rd_data(31 downto 8) <= std_logic_vector(to_unsigned(0, 24)); --- --- The registered MUX is all we need for a SimpCon read. --- The read data is stored in registered rd_data. --- -process(clk, reset) -begin - - if (reset='1') then - rd_data(7 downto 0) <= (others => '0'); - elsif rising_edge(clk) then - - ua_rd <= '0'; - if rd='1' then - -- that's our very simple address decoder - if address(0)='0' then - rd_data(7 downto 0) <= "000000" & rdrf & tdre; - else - rd_data(7 downto 0) <= ua_dout; - ua_rd <= rd; - end if; - end if; - end if; - -end process; - - -- write is on address offest 1 - ua_wr <= wr and address(0); - --- --- SimpCon write is very simple --- -process(clk, reset) - -begin - - if (reset='1') then - conf_reg <= "101"; - elsif rising_edge(clk) then - -- config register is at offset 0 - if wr='1' and address(0)='0' then - conf_reg <= wr_data(2 downto 0); - end if; - - if conf_reg(2)='1' then - clk16_cnt <= clk16_fast_cnt; - else - clk16_cnt <= clk16_slow_cnt; - end if; - end if; -end process; - - dtr <= not conf_reg(0); - --- --- serial clock --- -process(clk, reset) - - variable clk16 : integer range 0 to clk16_slow_cnt; - variable clktx : unsigned(3 downto 0); - variable clkrx : unsigned(3 downto 0); - -begin - if (reset='1') then - clk16 := 0; - clktx := "0000"; - clkrx := "0000"; - tx_clk <= '0'; - rx_clk <= '0'; - rx_buf <= "111"; - - elsif rising_edge(clk) then - - rxd_reg(0) <= rxd; -- to avoid setup timing error in Quartus - rxd_reg(1) <= rxd_reg(0); - rxd_reg(2) <= rxd_reg(1); - - if (clk16=clk16_cnt) then -- 16 x serial clock - clk16 := 0; --- --- tx clock --- - clktx := clktx + 1; - if (clktx="0000") then - tx_clk <= '1'; - else - tx_clk <= '0'; - end if; --- --- rx clock --- - if (rx_clk_ena='1') then - clkrx := clkrx + 1; - if (clkrx="1000") then - rx_clk <= '1'; - else - rx_clk <= '0'; - end if; - else - clkrx := "0000"; - end if; --- --- sync in filter buffer --- - rx_buf(0) <= rxd_reg(2); - rx_buf(2 downto 1) <= rx_buf(1 downto 0); - else - clk16 := clk16 + 1; - tx_clk <= '0'; - rx_clk <= '0'; - end if; - - - end if; - -end process; - --- --- transmit fifo --- - cmp_tf: fifo generic map (8, txf_depth, txf_thres) - port map (clk, reset, wr_data(7 downto 0), tf_dout, tf_rd, ua_wr, tf_empty, tf_full, tf_half); - --- --- state machine for actual shift out --- -process(clk, reset) - - variable i : integer range 0 to 11; - -begin - - if (reset='1') then - uart_tx_state <= s0; - tsr <= "1111111111"; - tf_rd <= '0'; - ncts_buf <= "111"; - ncts_in <= '1'; - - elsif rising_edge(clk) then - - ncts_buf(0) <= ncts; - ncts_buf(2 downto 1) <= ncts_buf(1 downto 0); - if conf_reg(1)='1' then - ncts_in <= ncts_buf(2); - else - ncts_in <= '0'; - end if; - - case uart_tx_state is - - when s0 => - i := 0; - if (tf_empty='0' and ncts_in='0') then - uart_tx_state <= s1; - tsr <= tf_dout & '0' & '1'; - tf_rd <= '1'; - end if; - - when s1 => - tf_rd <= '0'; - if (tx_clk='1') then - tsr(9) <= '1'; - tsr(8 downto 0) <= tsr(9 downto 1); - i := i+1; - if (i=11) then -- two stop bits - uart_tx_state <= s0; - end if; - end if; - - end case; - end if; - -end process; - - txd <= tsr(0); - tdre <= not tf_full; - - --- --- receive fifo --- - cmp_rf: fifo generic map (8, rxf_depth, rxf_thres) - port map (clk, reset, rsr(8 downto 1), ua_dout, ua_rd, rf_wr, rf_empty, rf_full, rf_half); - - rdrf <= not rf_empty; - nrts <= rf_half; -- glitches even on empty fifo! - --- --- filter rxd --- - with rx_buf 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; - --- --- state machine for actual shift in --- -process(clk, reset) - - variable i : integer range 0 to 10; - -begin - - if (reset='1') then - uart_rx_state <= s0; - rsr <= "0000000000"; - rf_wr <= '0'; - rx_clk_ena <= '0'; - - elsif rising_edge(clk) then - - case uart_rx_state is - - - when s0 => - i := 0; - rf_wr <= '0'; - if (rx_d='0') then - rx_clk_ena <= '1'; - uart_rx_state <= s1; - else - rx_clk_ena <= '0'; - end if; - - when s1 => - if (rx_clk='1') then - rsr(9) <= rx_d; - rsr(8 downto 0) <= rsr(9 downto 1); - i := i+1; - if (i=10) then - uart_rx_state <= s2; - end if; - end if; - - when s2 => - rx_clk_ena <= '0'; - if rsr(0)='0' and rsr(9)='1' then - if rf_full='0' then -- if full just drop it - rf_wr <= '1'; - end if; - end if; - uart_rx_state <= s0; - - end case; - end if; - -end process; - -end rtl; Index: trunk/vhdl/scio_min.vhd =================================================================== --- trunk/vhdl/scio_min.vhd (revision 25) +++ trunk/vhdl/scio_min.vhd (nonexistent) @@ -1,199 +0,0 @@ --- --- scio_min.vhd --- --- io devices for minimal configuration --- only counter, wd and serial line, alle io pins are tri statet --- --- --- io address mapping: --- --- IO Base is 0xffffff80 for 'fast' constants (bipush) --- --- 0x00 0-3 system clock counter, us counter, timer int, wd bit --- 0x10 0-1 uart (download) --- --- status word in uarts: --- 0 uart transmit data register empty --- 1 uart read data register full --- --- --- todo: --- --- --- 2003-07-09 created --- 2005-08-27 ignore ncts on uart --- 2005-11-30 changed to SimpCon --- 2007-03-17 use records --- --- - - -Library IEEE; -use IEEE.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.jop_types.all; -use work.sc_pack.all; -use work.jop_config.all; - -entity scio is -generic (cpu_id : integer := 0); -port ( - clk : in std_logic; - reset : in std_logic; - --- --- SimpCon IO interface --- - sc_io_out : in sc_io_out_type; - sc_io_in : out sc_in_type; - --- --- Interrupts from IO devices --- - 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; - rxd : in std_logic; - ncts : in std_logic; - nrts : out std_logic; - --- watch dog - - wd : out std_logic; - --- core i/o pins - l : inout std_logic_vector(20 downto 1); - r : inout std_logic_vector(20 downto 1); - t : inout std_logic_vector(6 downto 1); - b : inout std_logic_vector(10 downto 1) -); -end scio; - - -architecture rtl of scio is - - constant SLAVE_CNT : integer := 3; - -- SLAVE_CNT <= 2**DECODE_BITS - -- take care of USB address 0x20! - constant DECODE_BITS : integer := 2; - -- number of bits that can be used inside the slave - constant SLAVE_ADDR_BITS : integer := 4; - - type slave_bit is array(0 to SLAVE_CNT-1) of std_logic; - signal sc_rd, sc_wr : slave_bit; - - type slave_dout is array(0 to SLAVE_CNT-1) of std_logic_vector(31 downto 0); - signal sc_dout : slave_dout; - - type slave_rdy_cnt is array(0 to SLAVE_CNT-1) of unsigned(1 downto 0); - signal sc_rdy_cnt : slave_rdy_cnt; - - signal sel, sel_reg : integer range 0 to 2**DECODE_BITS-1; - -begin - --- --- unused and input pins tri state --- - l <= (others => 'Z'); - r <= (others => 'Z'); - t <= (others => 'Z'); - b <= (others => 'Z'); - - assert SLAVE_CNT <= 2**DECODE_BITS report "Wrong constant in scio"; - - sel <= to_integer(unsigned(sc_io_out.address(SLAVE_ADDR_BITS+DECODE_BITS-1 downto SLAVE_ADDR_BITS))); - - -- What happens when sel_reg > SLAVE_CNT-1?? - 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 - -- - gsl: for i in 0 to SLAVE_CNT-1 generate - - sc_rd(i) <= sc_io_out.rd when i=sel else '0'; - sc_wr(i) <= sc_io_out.wr when i=sel else '0'; - - end generate; - - -- - -- Register read mux selector - -- - process(clk, reset) - begin - if (reset='1') then - sel_reg <= 0; - elsif rising_edge(clk) then - if sc_io_out.rd='1' then - sel_reg <= sel; - end if; - end if; - end process; - - cmp_sys: entity work.sc_sys generic map ( - addr_bits => SLAVE_ADDR_BITS, - clk_freq => clk_freq, - cpu_id => cpu_id - ) - port map( - clk => clk, - reset => reset, - - address => sc_io_out.address(SLAVE_ADDR_BITS-1 downto 0), - wr_data => sc_io_out.wr_data, - rd => sc_rd(0), - wr => sc_wr(0), - rd_data => sc_dout(0), - rdy_cnt => sc_rdy_cnt(0), - - irq_in => irq_in, - exc_req => exc_req, - - sync_out => sync_out, - sync_in => sync_in, - - wd => wd - ); - - cmp_ua: entity work.sc_uart generic map ( - addr_bits => SLAVE_ADDR_BITS, - clk_freq => clk_freq, - baud_rate => 115200, - txf_depth => 2, - txf_thres => 1, - rxf_depth => 2, - rxf_thres => 1 - ) - port map( - clk => clk, - reset => reset, - - address => sc_io_out.address(SLAVE_ADDR_BITS-1 downto 0), - wr_data => sc_io_out.wr_data, - rd => sc_rd(1), - wr => sc_wr(1), - rd_data => sc_dout(1), - rdy_cnt => sc_rdy_cnt(1), - - txd => txd, - rxd => rxd, - ncts => '0', - nrts => nrts - ); - -end rtl; Index: trunk/vhdl/sc_uart.vhd =================================================================== --- trunk/vhdl/sc_uart.vhd (revision 25) +++ trunk/vhdl/sc_uart.vhd (nonexistent) @@ -1,362 +0,0 @@ --- --- sc_uart.vhd --- --- 8-N-1 serial interface --- --- wr, rd should be one cycle long => trde, rdrf goes 0 one cycle later --- --- Author: Martin Schoeberl martin@jopdesign.com --- --- --- resources on ACEX1K30-3 --- --- 100 LCs, max 90 MHz --- --- resetting rts with fifo_full-1 works with C program on pc --- but not with javax.comm: sends some more bytes after deassert --- of rts (16 byte blocks regardless of rts). --- Try to stop with half full fifo. --- --- todo: --- --- --- 2000-12-02 first working version --- 2002-01-06 changed tdr and rdr to fifos. --- 2002-05-15 changed clkdiv calculation --- 2002-11-01 don't wait if read fifo is full, just drop the byte --- 2002-11-03 use threshold in fifo to reset rts --- don't send if cts is '0' --- 2002-11-08 rx fifo to 20 characters and stop after 4 --- 2003-07-05 new IO standard, change cts/rts to neg logic --- 2003-09-19 sync ncts in! --- 2004-03-23 two stop bits --- 2005-11-30 change interface to SimpCon --- 2006-08-07 rxd input register with clk to avoid Quartus tsu violation --- 2006-08-13 use 3 FFs for the rxd input at clk --- - - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -entity sc_uart is - -generic (addr_bits : integer; - clk_freq : integer; - baud_rate : integer; - txf_depth : integer; txf_thres : integer; - rxf_depth : integer; rxf_thres : 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); - - txd : out std_logic; - rxd : in std_logic; - ncts : in std_logic; - nrts : out std_logic -); -end sc_uart; - -architecture rtl of sc_uart is - -component fifo is - -generic (width : integer; depth : integer; thres : integer); -port ( - clk : in std_logic; - reset : in std_logic; - - din : in std_logic_vector(width-1 downto 0); - dout : out std_logic_vector(width-1 downto 0); - - rd : in std_logic; - wr : in std_logic; - - empty : out std_logic; - full : out std_logic; - half : out std_logic -); -end component; - --- --- signals for uart connection --- - signal ua_dout : std_logic_vector(7 downto 0); - signal ua_wr, tdre : std_logic; - signal ua_rd, rdrf : std_logic; - - type uart_tx_state_type is (s0, s1); - signal uart_tx_state : uart_tx_state_type; - - signal tf_dout : std_logic_vector(7 downto 0); -- fifo out - signal tf_rd : std_logic; - signal tf_empty : std_logic; - signal tf_full : std_logic; - signal tf_half : std_logic; - - signal ncts_buf : std_logic_vector(2 downto 0); -- sync in - - signal tsr : std_logic_vector(9 downto 0); -- tx shift register - - signal tx_clk : std_logic; - - - type uart_rx_state_type is (s0, s1, s2); - signal uart_rx_state : uart_rx_state_type; - - signal rf_wr : std_logic; - signal rf_empty : std_logic; - signal rf_full : std_logic; - signal rf_half : std_logic; - - signal rxd_reg : std_logic_vector(2 downto 0); - signal rx_buf : std_logic_vector(2 downto 0); -- sync in, filter - signal rx_d : std_logic; -- rx serial data - - signal rsr : std_logic_vector(9 downto 0); -- rx shift register - - signal rx_clk : std_logic; - signal rx_clk_ena : std_logic; - - constant clk16_cnt : integer := (clk_freq/baud_rate+8)/16-1; - - -begin - - rdy_cnt <= "00"; -- no wait states - rd_data(31 downto 8) <= std_logic_vector(to_unsigned(0, 24)); --- --- The registered MUX is all we need for a SimpCon read. --- The read data is stored in registered rd_data. --- -process(clk, reset) -begin - - if (reset='1') then - rd_data(7 downto 0) <= (others => '0'); - elsif rising_edge(clk) then - - ua_rd <= '0'; - if rd='1' then - -- that's our very simple address decoder - if address(0)='0' then - rd_data(7 downto 0) <= "000000" & rdrf & tdre; - else - rd_data(7 downto 0) <= ua_dout; - ua_rd <= rd; - end if; - end if; - end if; - -end process; - - -- write is on address offest 1 - ua_wr <= wr and address(0); - --- --- serial clock --- -process(clk, reset) - - variable clk16 : integer range 0 to clk16_cnt; - variable clktx : unsigned(3 downto 0); - variable clkrx : unsigned(3 downto 0); - -begin - if (reset='1') then - clk16 := 0; - clktx := "0000"; - clkrx := "0000"; - tx_clk <= '0'; - rx_clk <= '0'; - rx_buf <= "111"; - - elsif rising_edge(clk) then - - rxd_reg(0) <= rxd; -- to avoid setup timing error in Quartus - rxd_reg(1) <= rxd_reg(0); - rxd_reg(2) <= rxd_reg(1); - - if (clk16=clk16_cnt) then -- 16 x serial clock - clk16 := 0; --- --- tx clock --- - clktx := clktx + 1; - if (clktx="0000") then - tx_clk <= '1'; - else - tx_clk <= '0'; - end if; --- --- rx clock --- - if (rx_clk_ena='1') then - clkrx := clkrx + 1; - if (clkrx="1000") then - rx_clk <= '1'; - else - rx_clk <= '0'; - end if; - else - clkrx := "0000"; - end if; --- --- sync in filter buffer --- - rx_buf(0) <= rxd_reg(2); - rx_buf(2 downto 1) <= rx_buf(1 downto 0); - else - clk16 := clk16 + 1; - tx_clk <= '0'; - rx_clk <= '0'; - end if; - - - end if; - -end process; - --- --- transmit fifo --- - cmp_tf: fifo generic map (8, txf_depth, txf_thres) - port map (clk, reset, wr_data(7 downto 0), tf_dout, tf_rd, ua_wr, tf_empty, tf_full, tf_half); - --- --- state machine for actual shift out --- -process(clk, reset) - - variable i : integer range 0 to 11; - -begin - - if (reset='1') then - uart_tx_state <= s0; - tsr <= "1111111111"; - tf_rd <= '0'; - ncts_buf <= "111"; - - elsif rising_edge(clk) then - - ncts_buf(0) <= ncts; - ncts_buf(2 downto 1) <= ncts_buf(1 downto 0); - - case uart_tx_state is - - when s0 => - i := 0; - if (tf_empty='0' and ncts_buf(2)='0') then - uart_tx_state <= s1; - tsr <= tf_dout & '0' & '1'; - tf_rd <= '1'; - end if; - - when s1 => - tf_rd <= '0'; - if (tx_clk='1') then - tsr(9) <= '1'; - tsr(8 downto 0) <= tsr(9 downto 1); - i := i+1; - if (i=11) then -- two stop bits - uart_tx_state <= s0; - end if; - end if; - - end case; - end if; - -end process; - - txd <= tsr(0); - tdre <= not tf_full; - - --- --- receive fifo --- - cmp_rf: fifo generic map (8, rxf_depth, rxf_thres) - port map (clk, reset, rsr(8 downto 1), ua_dout, ua_rd, rf_wr, rf_empty, rf_full, rf_half); - - rdrf <= not rf_empty; - nrts <= rf_half; -- glitches even on empty fifo! - --- --- filter rxd --- - with rx_buf 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; - --- --- state machine for actual shift in --- -process(clk, reset) - - variable i : integer range 0 to 10; - -begin - - if (reset='1') then - uart_rx_state <= s0; - rsr <= "0000000000"; - rf_wr <= '0'; - rx_clk_ena <= '0'; - - elsif rising_edge(clk) then - - case uart_rx_state is - - - when s0 => - i := 0; - rf_wr <= '0'; - if (rx_d='0') then - rx_clk_ena <= '1'; - uart_rx_state <= s1; - else - rx_clk_ena <= '0'; - end if; - - when s1 => - if (rx_clk='1') then - rsr(9) <= rx_d; - rsr(8 downto 0) <= rsr(9 downto 1); - i := i+1; - if (i=10) then - uart_rx_state <= s2; - end if; - end if; - - when s2 => - rx_clk_ena <= '0'; - if rsr(0)='0' and rsr(9)='1' then - if rf_full='0' then -- if full just drop it - rf_wr <= '1'; - end if; - end if; - uart_rx_state <= s0; - - end case; - end if; - -end process; - -end rtl; Index: trunk/vhdl/sc2ahbsl.vhd =================================================================== --- trunk/vhdl/sc2ahbsl.vhd (revision 25) +++ trunk/vhdl/sc2ahbsl.vhd (nonexistent) @@ -1,208 +0,0 @@ --- --- sc2ahbsl.vhd --- --- SimpCon to AMBA bridge --- --- Author: Martin Schoeberl martin@jopdesign.com --- --- 2007-03-16 first version --- - -Library IEEE; -use IEEE.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.sc_pack.all; - -library grlib; -use grlib.amba.all; ---use grlib.tech.all; -library gaisler; -use gaisler.memctrl.all; ---use gaisler.pads.all; -- used for I/O pads ---use gaisler.misc.all; - -entity sc2ahbsl is - -port ( - - clk, reset : in std_logic; - --- SimpCon memory interface - scmo : in sc_mem_out_type; - scmi : out sc_in_type; - --- AMBA slave interface - ahbsi : out ahb_slv_in_type; - ahbso : in ahb_slv_out_type -); -end sc2ahbsl; - -architecture rtl of sc2ahbsl is - - type state_type is (idl, rd, rdw, wr, wrw); - signal state : state_type; - signal next_state : state_type; - - signal reg_wr_data : std_logic_vector(31 downto 0); - signal reg_rd_data : std_logic_vector(31 downto 0); - -begin - --- --- some defaults --- - ahbsi.hsel(1 to NAHBSLV-1) <= (others => '0'); -- we use only slave 0 - ahbsi.hsel(0) <= scmo.rd or scmo.wr; -- slave select - -- do we need to store the addrsss in a register? - ahbsi.haddr(MEM_ADDR_SIZE-1+2 downto 2) <= scmo.address; -- address bus (byte) - ahbsi.haddr(1 downto 0) <= (others => '0'); - ahbsi.haddr(31 downto MEM_ADDR_SIZE+2) <= (others => '0'); - ahbsi.hwrite <= scmo.wr; -- read/write - ahbsi.htrans <= HTRANS_NONSEQ; -- transfer type - ahbsi.hsize <= "010"; -- transfer size 32 bits - ahbsi.hburst <= HBURST_SINGLE; -- burst type - ahbsi.hwdata <= reg_wr_data; -- write data bus - ahbsi.hprot <= "0000"; -- ? protection control - ahbsi.hready <= '1'; -- ? transer done - ahbsi.hmaster <= "0000"; -- current master - ahbsi.hmastlock <= '0'; -- locked access - ahbsi.hmbsel(0) <= '0'; -- memory bank select - ahbsi.hmbsel(1) <= '1'; -- second is SRAM - ahbsi.hmbsel(2 to NAHBAMR-1) <= (others => '0'); - ahbsi.hcache <= '1'; -- cacheable - ahbsi.hirq <= (others => '0'); -- interrupt result bus - - - - --- --- Register write data --- -process(clk, reset) -begin - if reset='1' then - - reg_wr_data <= (others => '0'); - - elsif rising_edge(clk) then - - if scmo.wr='1' then - reg_wr_data <= scmo.wr_data; - end if; - - end if; -end process; - --- --- next state logic --- -process(state, scmo, ahbso.hready) - -begin - - next_state <= state; - - case state is - - when idl => - if scmo.rd='1' then - next_state <= rdw; - elsif scmo.wr='1' then - next_state <= wrw; - end if; - - when rdw => - if ahbso.hready='1' then - next_state <= rd; - end if; - - when rd => - next_state <= idl; - if scmo.rd='1' then - next_state <= rdw; - elsif scmo.wr='1' then - next_state <= wrw; - end if; - - when wrw => - if ahbso.hready='1' then - next_state <= wr; - end if; - - when wr => - next_state <= idl; - if scmo.rd='1' then - next_state <= rdw; - elsif scmo.wr='1' then - next_state <= wrw; - end if; - - - end case; - -end process; - --- --- state machine register --- and output register --- -process(clk, reset) - -begin - if (reset='1') then - state <= idl; - reg_rd_data <= (others => '0'); - - elsif rising_edge(clk) then - - state <= next_state; - - case next_state is - - when idl => - - when rdw => - - when rd => - reg_rd_data <= ahbso.hrdata; - - when wrw => - - when wr => - - end case; - - end if; -end process; - --- --- combinatorial state machine output --- -process(next_state) - -begin - - scmi.rdy_cnt <= "00"; - scmi.rd_data <= reg_rd_data; - - case next_state is - - when idl => - - when rdw => - scmi.rdy_cnt <= "11"; - - when rd => - scmi.rd_data <= ahbso.hrdata; - - when wrw => - scmi.rdy_cnt <= "11"; - - when wr => - - end case; - -end process; - -end rtl; Index: trunk/vhdl/sc_isa.vhd =================================================================== --- trunk/vhdl/sc_isa.vhd (revision 25) +++ trunk/vhdl/sc_isa.vhd (nonexistent) @@ -1,119 +0,0 @@ --- --- sc_isa.vhd --- --- ISA bus for ethernet chip --- --- Author: Martin Schoeberl martin@jopdesign.com --- --- --- resources on Cyclone --- --- xx LCs, max xx MHz --- --- --- 2005-12-28 changed for SimpCon --- --- todo: --- --- - - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -entity sc_isa is -generic (addr_bits : 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); - --- ISA bus - - isa_d : inout std_logic_vector(7 downto 0); - isa_a : out std_logic_vector(4 downto 0); - isa_reset : out std_logic; - isa_nior : out std_logic; - isa_niow : out std_logic -); -end sc_isa; - -architecture rtl of sc_isa is - --- --- signal for isa data bus --- - signal isa_data : std_logic_vector(7 downto 0); - signal isa_dir : std_logic; -- direction of isa_d ('1' means driving out) - -begin - - rdy_cnt <= "00"; -- no wait states - --- --- The registered MUX is all we need for a SimpCon read. --- -process(clk, reset) -begin - - if (reset='1') then - rd_data <= (others => '0'); - elsif rising_edge(clk) then - - if rd='1' then - -- no address decoding - rd_data <= std_logic_vector(to_unsigned(0, 24)) & isa_d; - end if; - end if; - -end process; - - --- --- SimpCon write is very simple --- -process(clk, reset) - -begin - - if (reset='1') then - - isa_data <= (others => '0'); - isa_a <= (others => '0'); - isa_reset <= '0'; - isa_nior <= '1'; - isa_niow <= '1'; - isa_dir <= '0'; - - elsif rising_edge(clk) then - - if wr='1' then - if address(0)='0' then - isa_a <= wr_data(4 downto 0); - isa_reset <= wr_data(5); - isa_nior <= not wr_data(6); - isa_niow <= not wr_data(7); - isa_dir <= wr_data(8); - else - isa_data <= wr_data(7 downto 0); - end if; - end if; - - end if; -end process; - --- --- isa data bus --- - isa_d <= isa_data when isa_dir='1' else "ZZZZZZZZ"; - -end rtl; Index: trunk/vhdl/sc_pack.vhd =================================================================== --- trunk/vhdl/sc_pack.vhd (revision 25) +++ trunk/vhdl/sc_pack.vhd (nonexistent) @@ -1,45 +0,0 @@ --- --- sc_pack.vhd --- --- Package for SimpCon defines --- --- Author: Martin Schoeberl (martin@jopdesign.com) --- --- --- 2007-03-16 first version --- --- - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -package sc_pack is - - constant MEM_ADDR_SIZE : integer := 21; - constant IO_ADDR_SIZE : integer := 7; - constant RDY_CNT_SIZE : integer := 2; - - type sc_mem_out_type is record - address : std_logic_vector(MEM_ADDR_SIZE-1 downto 0); - wr_data : std_logic_vector(31 downto 0); - rd : std_logic; - wr : std_logic; - end record; - - type sc_io_out_type is record - address : std_logic_vector(IO_ADDR_SIZE-1 downto 0); - wr_data : std_logic_vector(31 downto 0); - 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; Index: trunk/vhdl/sc_sys.vhd =================================================================== --- trunk/vhdl/sc_sys.vhd (revision 25) +++ trunk/vhdl/sc_sys.vhd (nonexistent) @@ -1,258 +0,0 @@ --- --- sc_sys.vhd --- --- counter, interrrupt handling and watchdog bit --- --- Author: Martin Schoeberl martin@good-ear.com --- --- address map: --- --- 0 read clk counter, write irq ena --- 1 read 1 MHz counter, write timer val (us) + irq ack --- 2 write generates sw-int (for yield()) --- 3 write wd port --- 4 write generates SW exception, read exception reason --- --- todo: --- --- --- 2003-07-05 new IO standard --- 2003-08-15 us counter, irq added --- 2005-11-30 change interface to SimpCon --- 2006-01-11 added exception --- 2007-03-17 changed interrupts to records --- 2007-06-01 changed name from sc_cnt to sc_sys --- - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -use work.jop_types.all; - -entity sc_sys is - -generic (addr_bits : integer; - clk_freq : integer; - cpu_id : 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); - --- --- Interrupts from IO devices --- - irq_in : out irq_in_type; - exc_req : in exception_type; - - sync_out : in sync_out_type; - sync_in : out sync_in_type; - - wd : out std_logic - -); -end sc_sys ; - -architecture rtl of sc_sys is - - signal clock_cnt : std_logic_vector(31 downto 0); - signal pre_scale : std_logic_vector(7 downto 0); - signal us_cnt : std_logic_vector(31 downto 0); - - constant div_val : integer := clk_freq/1000000-1; - - signal timer_int : std_logic; - signal yield_int : std_logic; - signal int_ack : std_logic; - - signal timer : std_logic; - signal yield : std_logic; - - signal irq_cnt : std_logic_vector(31 downto 0); - signal timer_equ : std_logic; - signal timer_dly : std_logic; - - signal exc_type : std_logic_vector(7 downto 0); - - signal cpu_identity : std_logic_vector(31 downto 0); - - -begin - - cpu_identity <= std_logic_vector(to_unsigned(cpu_id,32)); - rdy_cnt <= "00"; -- no wait states - --- --- read cnt values --- -process(clk, reset) -begin - - if (reset='1') then - rd_data <= (others => '0'); - elsif rising_edge(clk) then - - if rd='1' then - case address(2 downto 0) is - when "000" => - rd_data <= clock_cnt; - when "001" => - rd_data <= us_cnt; - when "100" => - rd_data(7 downto 0) <= exc_type; - rd_data(31 downto 8) <= (others => '0'); - when "110" => - rd_data <= cpu_identity; --- when "111" => - when others => - rd_data(0) <= sync_out.s_out; - rd_data(31 downto 1) <= (others => '0'); - end case; - end if; - end if; - -end process; - --- --- compare timer value and us counter --- and generate single shot --- -process(us_cnt, irq_cnt) begin - timer_equ <= '0'; - if us_cnt = irq_cnt then - timer_equ <= '1'; - end if; -end process; - -process(clk, reset, timer_equ) begin - if (reset='1') then - timer_dly <= '0'; - elsif rising_edge(clk) then - timer_dly <= timer_equ; - end if; -end process; - - timer_int <= timer_equ and not timer_dly; - --- --- int processing from timer and yield request --- -process(clk, reset, timer_int, yield_int) begin - - if (reset='1') then - timer <= '0'; - yield <= '0'; - elsif rising_edge(clk) then - if int_ack='1' then - timer <= '0'; - yield <= '0'; - else - if timer_int='1' then - timer <= '1'; - end if; - if yield_int='1' then - yield <= '1'; - end if; - end if; - end if; - -end process; - - irq_in.irq <= timer or yield; - - --- --- counters --- pre_scale is 8 bit => fmax = 255 MHz --- -process(clk, reset) begin - - if (reset='1') then - - clock_cnt <= (others => '0'); - us_cnt <= (others => '0'); - pre_scale <= std_logic_vector(to_unsigned(div_val, pre_scale'length)); - - elsif rising_edge(clk) then - - clock_cnt <= std_logic_vector(unsigned(clock_cnt) + 1); - pre_scale <= std_logic_vector(unsigned(pre_scale) - 1); - if pre_scale = "00000000" then - pre_scale <= std_logic_vector(to_unsigned(div_val, pre_scale'length)); - us_cnt <= std_logic_vector(unsigned(us_cnt) + 1); - end if; - - end if; -end process; - --- --- io write processing and exception processing --- -process(clk, reset) - -begin - if (reset='1') then - - irq_in.irq_ena <= '0'; - irq_cnt <= (others => '0'); - int_ack <= '0'; - wd <= '0'; - sync_in.s_in <= '0'; - - exc_type <= (others => '0'); - irq_in.exc_int <= '0'; - - elsif rising_edge(clk) then - - int_ack <= '0'; - yield_int <= '0'; - - irq_in.exc_int <= '0'; - - if exc_req.spov='1' then - 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 - when "000" => - irq_in.irq_ena <= wr_data(0); - when "001" => - irq_cnt <= wr_data; - int_ack <= '1'; - when "010" => - yield_int <= '1'; - when "011" => - wd <= wr_data(0); - when "100" => - exc_type <= wr_data(7 downto 0); - irq_in.exc_int <= '1'; - when "110" => - -- nothing, processor id is read only - when others => --- when "111" => - sync_in.s_in <= wr_data(0); - end case; - end if; - - end if; -end process; - -end rtl; Index: trunk/vhdl/wb_pack.vhd =================================================================== --- trunk/vhdl/wb_pack.vhd (revision 25) +++ trunk/vhdl/wb_pack.vhd (nonexistent) @@ -1,214 +0,0 @@ --- --- --- Package for Wishbone defines and testbench procedures --- - -library std; -use std.textio.all; - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -package wb_pack is - - constant TIMEOUT : integer := 10; - constant M_ADDR_SIZE : integer := 8; - constant S_ADDR_SIZE : integer := 4; - - --- --- type definitions for the memory WISHBONE interface --- - - -- 21 bits as example for the SRAM/Flash/NAND interface - constant MEM_ADDR_SIZE : integer := 21; - - type wb_mem_out_type is record - dat : std_logic_vector(31 downto 0); - adr : std_logic_vector(MEM_ADDR_SIZE-1 downto 0); - we : std_logic; - cyc : std_logic; - sel : std_logic_vector(3 downto 0); - stb : std_logic; - end record; - type wb_mem_in_type is record - dat : std_logic_vector(31 downto 0); - ack : std_logic; - end record; - --- --- type definitions for the IO WISHBONE interface --- - - type wb_slave_in_type is record - dat_i : std_logic_vector(31 downto 0); - adr_i : std_logic_vector(S_ADDR_SIZE-1 downto 0); - we_i : std_logic; - cyc_i : std_logic; - stb_i : std_logic; - end record; - type wb_slave_out_type is record - dat_o : std_logic_vector(31 downto 0); - ack_o : std_logic; - end record; - - type wb_master_out_type is record - dat_o : std_logic_vector(31 downto 0); - adr_o : std_logic_vector(M_ADDR_SIZE-1 downto 0); - we_o : std_logic; - cyc_o : std_logic; - stb_o : std_logic; - end record; - type wb_master_in_type is record - dat_i : std_logic_vector(31 downto 0); - ack_i : std_logic; - end record; - - procedure wb_connect( - signal m_in : out wb_master_in_type; - signal m_out : in wb_master_out_type; - signal s_in : out wb_slave_in_type; - signal s_out : in wb_slave_out_type); - - procedure wb_write( - signal clk : in std_logic; - constant addr : in natural; - constant data : in natural; - signal wb_in : in wb_master_in_type; - signal wb_out : out wb_master_out_type); - - procedure wb_read( - signal clk : in std_logic; - constant addr : in natural; - variable data : out natural; - signal wb_in : in wb_master_in_type; - signal wb_out : out wb_master_out_type); - -end wb_pack; - -package body wb_pack is - - procedure wb_connect( - signal m_in : out wb_master_in_type; - signal m_out : in wb_master_out_type; - signal s_in : out wb_slave_in_type; - signal s_out : in wb_slave_out_type) is - - begin - - s_in.dat_i <= m_out.dat_o; - s_in.we_i <= m_out.we_o; - s_in.adr_i <= m_out.adr_o(S_ADDR_SIZE-1 downto 0); - s_in.cyc_i <= m_out.cyc_o; - s_in.stb_i <= m_out.stb_o; - - m_in.dat_i <= s_out.dat_o; - m_in.ack_i <= s_out.ack_o; - - end; - - procedure wb_write( - signal clk : in std_logic; - constant addr : in natural; - constant data : in natural; - signal wb_in : in wb_master_in_type; - signal wb_out : out wb_master_out_type) is - - variable txt : line; - - begin - - -- start cycle on positive edge - wait until rising_edge(clk); - write(txt, now, right, 8); - write(txt, string'(" wrote ")); - write(txt, data); - write(txt, string'(" to addr. ")); - write(txt, addr); - - wb_out.dat_o <= std_logic_vector(to_unsigned(data, wb_out.dat_o'length)); - wb_out.adr_o <= std_logic_vector(to_unsigned(addr, wb_out.adr_o'length)); - - wb_out.we_o <= '1'; - wb_out.cyc_o <= '1'; - wb_out.stb_o <= '1'; - - -- wait for acknowledge - wait until rising_edge(clk); - if wb_in.ack_i /= '1' then - for i in 1 to TIMEOUT loop - wait until rising_edge(clk); - exit when wb_in.ack_i = '1'; - if (i = TIMEOUT) then - write (txt, string'("No acknowledge recevied!")); - end if; - end loop; - end if; - - wb_out.dat_o <= (others => '0'); - wb_out.adr_o <= (others => '0'); - wb_out.we_o <= '0'; - wb_out.cyc_o <= '0'; - wb_out.stb_o <= '0'; - - writeline(output, txt); - - end; - - procedure wb_read( - signal clk : in std_logic; - constant addr : in natural; - variable data : out natural; - signal wb_in : in wb_master_in_type; - signal wb_out : out wb_master_out_type) is - - variable txt : line; - variable in_data : natural; - - begin - - -- start cycle on positive edge - wait until rising_edge(clk); - write(txt, now, right, 8); - write(txt, string'(" read from addr. ")); - write(txt, addr); - writeline(output, txt); - - wb_out.adr_o <= std_logic_vector(to_unsigned(addr, wb_out.adr_o'length)); - wb_out.dat_o <= (others => '0'); - - wb_out.we_o <= '0'; - wb_out.cyc_o <= '1'; - wb_out.stb_o <= '1'; - - -- wait for acknowledge - wait until rising_edge(clk); - if wb_in.ack_i /= '1' then - for i in 1 to TIMEOUT loop - wait until rising_edge(clk); - exit when wb_in.ack_i = '1'; - if (i = TIMEOUT) then - write (txt, string'("No acknowledge recevied!")); - end if; - end loop; - end if; - - in_data := to_integer(unsigned(wb_in.dat_i)); - data := in_data; - - wb_out.adr_o <= (others => '0'); - wb_out.we_o <= '0'; - wb_out.cyc_o <= '0'; - wb_out.stb_o <= '0'; - - write(txt, now, right, 8); - write(txt, string'(" value: ")); - write(txt, in_data); - - writeline(output, txt); - - end; - - -end wb_pack; Index: trunk/vhdl/sigdel.vhd =================================================================== --- trunk/vhdl/sigdel.vhd (revision 25) +++ trunk/vhdl/sigdel.vhd (nonexistent) @@ -1,146 +0,0 @@ --- --- sigdel.vhd --- --- sigma delta AD converter --- --- without external comperator: --- input threshhold of Acex is used as comperator --- (not very exact but only 3 external components) --- --- --- 100k --- ___ --- sdo o--|___|--+ --- | --- 100k | --- ___ | --- uin o--|___|--o----------o sdi --- | --- --- --- --- 100n --- | --- | --- --- --- - --- --- --- Author: Martin Schoeberl martin@jopdesign.com --- --- --- resources on ACEX1K30-3 --- --- xx LCs, max xx MHz --- --- --- todo: --- use clk_freq, make it configurable --- use a 'real' LP --- --- --- 2002-02-23 first working version --- 2002-08-08 free running 16 bit counter -> 16 bit ADC --- 2003-09-23 new IO standard --- 2005-12-28 just a simple data port --- - - -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -entity sigdel is - -generic (clk_freq : integer); -port ( - clk : in std_logic; - reset : in std_logic; - dout : out std_logic_vector(15 downto 0); - - sdi : in std_logic; - sdo : out std_logic -); -end sigdel ; - -architecture rtl of sigdel is - - signal clksd : unsigned(4 downto 0); - - signal clkint : unsigned(15 downto 0); - signal val : unsigned(15 downto 0); - signal sd_dout : std_logic_vector(15 downto 0); - - signal rx_d : std_logic; - signal serdata : std_logic; - - signal spike : std_logic_vector(2 downto 0); -- sync in, filter - -begin - - sdo <= serdata; - dout <= sd_dout; - --- --- sigma delta converter --- -process(clk, reset) - -begin - if (reset='1') then - clksd <= "00000"; - spike <= "000"; - sd_dout <= (others => '0'); - val <= (others => '0'); - clkint <= (others => '0'); - serdata <= '0'; - - elsif rising_edge(clk) then - - clksd <= clksd+1; - - if clksd="00000" then -- with 20 MHz => 625 kHz - --- --- delay --- - spike(0) <= sdi; - spike(2 downto 1) <= spike(1 downto 0); - serdata <= rx_d; -- no inverter, using an invert. comperator --- serdata <= not rx_d; -- without comperator - --- --- integrate --- - - if serdata='0' then -- 'invert' value - val <= val+1; - end if; - - if clkint=0 then -- some time... (9.5 Hz) - sd_dout <= std_logic_vector(val); - val <= (others => '0'); - 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; Index: trunk/doc/simpcon.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: trunk/doc/simpcon.pdf =================================================================== --- trunk/doc/simpcon.pdf (revision 25) +++ trunk/doc/simpcon.pdf (nonexistent)
trunk/doc/simpcon.pdf Property changes : Deleted: svn:mime-type ## -1 +0,0 ## -application/octet-stream \ No newline at end of property Index: simpcon/trunk/doc/simpcon.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: simpcon/trunk/doc/simpcon.pdf =================================================================== --- simpcon/trunk/doc/simpcon.pdf (nonexistent) +++ simpcon/trunk/doc/simpcon.pdf (revision 26)
simpcon/trunk/doc/simpcon.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: simpcon/trunk/vhdl/sc2ahbsl.vhd =================================================================== --- simpcon/trunk/vhdl/sc2ahbsl.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc2ahbsl.vhd (revision 26) @@ -0,0 +1,208 @@ +-- +-- sc2ahbsl.vhd +-- +-- SimpCon to AMBA bridge +-- +-- Author: Martin Schoeberl martin@jopdesign.com +-- +-- 2007-03-16 first version +-- + +Library IEEE; +use IEEE.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.sc_pack.all; + +library grlib; +use grlib.amba.all; +--use grlib.tech.all; +library gaisler; +use gaisler.memctrl.all; +--use gaisler.pads.all; -- used for I/O pads +--use gaisler.misc.all; + +entity sc2ahbsl is + +port ( + + clk, reset : in std_logic; + +-- SimpCon memory interface + scmo : in sc_mem_out_type; + scmi : out sc_in_type; + +-- AMBA slave interface + ahbsi : out ahb_slv_in_type; + ahbso : in ahb_slv_out_type +); +end sc2ahbsl; + +architecture rtl of sc2ahbsl is + + type state_type is (idl, rd, rdw, wr, wrw); + signal state : state_type; + signal next_state : state_type; + + signal reg_wr_data : std_logic_vector(31 downto 0); + signal reg_rd_data : std_logic_vector(31 downto 0); + +begin + +-- +-- some defaults +-- + ahbsi.hsel(1 to NAHBSLV-1) <= (others => '0'); -- we use only slave 0 + ahbsi.hsel(0) <= scmo.rd or scmo.wr; -- slave select + -- do we need to store the addrsss in a register? + ahbsi.haddr(MEM_ADDR_SIZE-1+2 downto 2) <= scmo.address; -- address bus (byte) + ahbsi.haddr(1 downto 0) <= (others => '0'); + ahbsi.haddr(31 downto MEM_ADDR_SIZE+2) <= (others => '0'); + ahbsi.hwrite <= scmo.wr; -- read/write + ahbsi.htrans <= HTRANS_NONSEQ; -- transfer type + ahbsi.hsize <= "010"; -- transfer size 32 bits + ahbsi.hburst <= HBURST_SINGLE; -- burst type + ahbsi.hwdata <= reg_wr_data; -- write data bus + ahbsi.hprot <= "0000"; -- ? protection control + ahbsi.hready <= '1'; -- ? transer done + ahbsi.hmaster <= "0000"; -- current master + ahbsi.hmastlock <= '0'; -- locked access + ahbsi.hmbsel(0) <= '0'; -- memory bank select + ahbsi.hmbsel(1) <= '1'; -- second is SRAM + ahbsi.hmbsel(2 to NAHBAMR-1) <= (others => '0'); + ahbsi.hcache <= '1'; -- cacheable + ahbsi.hirq <= (others => '0'); -- interrupt result bus + + + + +-- +-- Register write data +-- +process(clk, reset) +begin + if reset='1' then + + reg_wr_data <= (others => '0'); + + elsif rising_edge(clk) then + + if scmo.wr='1' then + reg_wr_data <= scmo.wr_data; + end if; + + end if; +end process; + +-- +-- next state logic +-- +process(state, scmo, ahbso.hready) + +begin + + next_state <= state; + + case state is + + when idl => + if scmo.rd='1' then + next_state <= rdw; + elsif scmo.wr='1' then + next_state <= wrw; + end if; + + when rdw => + if ahbso.hready='1' then + next_state <= rd; + end if; + + when rd => + next_state <= idl; + if scmo.rd='1' then + next_state <= rdw; + elsif scmo.wr='1' then + next_state <= wrw; + end if; + + when wrw => + if ahbso.hready='1' then + next_state <= wr; + end if; + + when wr => + next_state <= idl; + if scmo.rd='1' then + next_state <= rdw; + elsif scmo.wr='1' then + next_state <= wrw; + end if; + + + end case; + +end process; + +-- +-- state machine register +-- and output register +-- +process(clk, reset) + +begin + if (reset='1') then + state <= idl; + reg_rd_data <= (others => '0'); + + elsif rising_edge(clk) then + + state <= next_state; + + case next_state is + + when idl => + + when rdw => + + when rd => + reg_rd_data <= ahbso.hrdata; + + when wrw => + + when wr => + + end case; + + end if; +end process; + +-- +-- combinatorial state machine output +-- +process(next_state) + +begin + + scmi.rdy_cnt <= "00"; + scmi.rd_data <= reg_rd_data; + + case next_state is + + when idl => + + when rdw => + scmi.rdy_cnt <= "11"; + + when rd => + scmi.rd_data <= ahbso.hrdata; + + when wrw => + scmi.rdy_cnt <= "11"; + + when wr => + + end case; + +end process; + +end rtl; Index: simpcon/trunk/vhdl/sc2wb.vhd =================================================================== --- simpcon/trunk/vhdl/sc2wb.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc2wb.vhd (revision 26) @@ -0,0 +1,170 @@ +-- +-- sc2wb.vhd +-- +-- SimpCon/Wishbone bridge +-- +-- Author: Martin Schoeberl martin@jopdesign.com +-- +-- +-- +-- WISHBONE DATA SHEET +-- +-- Revision Level: B.3, Released: September 7, 2002 +-- Type: MASTER +-- +-- Signals: record and address size is defined in wb_pack.vhd +-- +-- Port Width Direction Description +-- ------------------------------------------------------------------------ +-- clk 1 Input Master clock, see JOP top level +-- reset 1 Input Reset, see JOP top level +-- dat_o 32 Output Data from SimpCon +-- adr_o 8 Output Address bits for the slaves, see wb_pack.vhd +-- Only addr_bits bits are actually used +-- we_o 1 Output Write enable output +-- cyc_o 1 Output Valid bus cycle output +-- stb_o 1 Output Strobe signal output +-- dat_i 32 Input Data from the slaves to JOP +-- ack_i 1 Input Bus cycle acknowledge input +-- +-- Port size: 32-bit +-- Port granularity: 32-bit +-- Maximum operand size: 32-bit +-- Data transfer ordering: BIG/LITTLE ENDIAN +-- Sequence of data transfer: UNDEFINED +-- +-- +-- 2005-12-20 first version +-- +-- + + +library ieee ; +use ieee.std_logic_1164.all ; +use ieee.numeric_std.all ; + +use work.wb_pack.all; + +entity sc2wb is + +generic (addr_bits : 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); + +-- Wishbone interfac + + wb_out : out wb_master_out_type; + wb_in : in wb_master_in_type + +); +end sc2wb; + +architecture rtl of sc2wb is + +-- +-- Wishbone specific signals +-- + signal wb_data : std_logic_vector(31 downto 0); -- output of wishbone module + signal wb_addr : std_logic_vector(7 downto 0); -- wishbone read/write address + signal wb_rd, wb_wr, wb_bsy : std_logic; + signal wb_rd_reg, wb_wr_reg : std_logic; + +begin + +-- +-- Wishbone interface +-- + + -- just use the SimpCon rd/wr + wb_rd <= rd; + wb_wr <= wr; + + rd_data <= wb_data; + + wb_out.adr_o <= wb_addr; + + rdy_cnt <= "11" when wb_bsy='1' else "00"; + +-- +-- Handle the Wishbone protocoll. +-- rd and wr request are registered for additional WSs. +-- +process(clk, reset) +begin + if (reset='1') then + + wb_addr <= (others => '0'); + + wb_out.stb_o <= '0'; + wb_out.cyc_o <= '0'; + wb_out.we_o <= '0'; + + wb_rd_reg <= '0'; + wb_wr_reg <= '0'; + wb_bsy <= '0'; + + elsif rising_edge(clk) then + + -- read request: + -- address is registered from SimpCon address and valid in the next + -- cycle + if wb_rd='1' then + -- store read address + wb_addr(M_ADDR_SIZE-1 downto addr_bits) <= (others => '0'); + wb_addr(addr_bits-1 downto 0) <= address; + + wb_out.stb_o <= '1'; + wb_out.cyc_o <= '1'; + wb_out.we_o <= '0'; + wb_rd_reg <= '1'; + wb_bsy <= '1'; + elsif wb_rd_reg='1' then + -- do we need a timeout??? + if wb_in.ack_i='1' then + wb_out.stb_o <= '0'; + wb_out.cyc_o <= '0'; + wb_rd_reg <= '0'; + wb_bsy <= '0'; + wb_data <= wb_in.dat_i; + end if; + -- write request + -- address and data are stored and valid in + -- the next cycle + elsif wb_wr='1' then + -- store write address + wb_addr(M_ADDR_SIZE-1 downto addr_bits) <= (others => '0'); + wb_addr(addr_bits-1 downto 0) <= address; + + -- this keeps the write data registered, + -- but costs a latency of one cycle. + wb_out.dat_o <= wr_data; + + wb_out.stb_o <= '1'; + wb_out.cyc_o <= '1'; + wb_out.we_o <= '1'; + wb_wr_reg <= '1'; + wb_bsy <= '1'; + elsif wb_wr_reg='1' then + -- do we need a timeout??? + if wb_in.ack_i='1' then + wb_out.stb_o <= '0'; + wb_out.cyc_o <= '0'; + wb_out.we_o <= '0'; + wb_wr_reg <= '0'; + wb_bsy <= '0'; + end if; + end if; + + end if; +end process; + +end rtl; Index: simpcon/trunk/vhdl/wb_pack.vhd =================================================================== --- simpcon/trunk/vhdl/wb_pack.vhd (nonexistent) +++ simpcon/trunk/vhdl/wb_pack.vhd (revision 26) @@ -0,0 +1,214 @@ +-- +-- +-- Package for Wishbone defines and testbench procedures +-- + +library std; +use std.textio.all; + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package wb_pack is + + constant TIMEOUT : integer := 10; + constant M_ADDR_SIZE : integer := 8; + constant S_ADDR_SIZE : integer := 4; + + +-- +-- type definitions for the memory WISHBONE interface +-- + + -- 21 bits as example for the SRAM/Flash/NAND interface + constant MEM_ADDR_SIZE : integer := 21; + + type wb_mem_out_type is record + dat : std_logic_vector(31 downto 0); + adr : std_logic_vector(MEM_ADDR_SIZE-1 downto 0); + we : std_logic; + cyc : std_logic; + sel : std_logic_vector(3 downto 0); + stb : std_logic; + end record; + type wb_mem_in_type is record + dat : std_logic_vector(31 downto 0); + ack : std_logic; + end record; + +-- +-- type definitions for the IO WISHBONE interface +-- + + type wb_slave_in_type is record + dat_i : std_logic_vector(31 downto 0); + adr_i : std_logic_vector(S_ADDR_SIZE-1 downto 0); + we_i : std_logic; + cyc_i : std_logic; + stb_i : std_logic; + end record; + type wb_slave_out_type is record + dat_o : std_logic_vector(31 downto 0); + ack_o : std_logic; + end record; + + type wb_master_out_type is record + dat_o : std_logic_vector(31 downto 0); + adr_o : std_logic_vector(M_ADDR_SIZE-1 downto 0); + we_o : std_logic; + cyc_o : std_logic; + stb_o : std_logic; + end record; + type wb_master_in_type is record + dat_i : std_logic_vector(31 downto 0); + ack_i : std_logic; + end record; + + procedure wb_connect( + signal m_in : out wb_master_in_type; + signal m_out : in wb_master_out_type; + signal s_in : out wb_slave_in_type; + signal s_out : in wb_slave_out_type); + + procedure wb_write( + signal clk : in std_logic; + constant addr : in natural; + constant data : in natural; + signal wb_in : in wb_master_in_type; + signal wb_out : out wb_master_out_type); + + procedure wb_read( + signal clk : in std_logic; + constant addr : in natural; + variable data : out natural; + signal wb_in : in wb_master_in_type; + signal wb_out : out wb_master_out_type); + +end wb_pack; + +package body wb_pack is + + procedure wb_connect( + signal m_in : out wb_master_in_type; + signal m_out : in wb_master_out_type; + signal s_in : out wb_slave_in_type; + signal s_out : in wb_slave_out_type) is + + begin + + s_in.dat_i <= m_out.dat_o; + s_in.we_i <= m_out.we_o; + s_in.adr_i <= m_out.adr_o(S_ADDR_SIZE-1 downto 0); + s_in.cyc_i <= m_out.cyc_o; + s_in.stb_i <= m_out.stb_o; + + m_in.dat_i <= s_out.dat_o; + m_in.ack_i <= s_out.ack_o; + + end; + + procedure wb_write( + signal clk : in std_logic; + constant addr : in natural; + constant data : in natural; + signal wb_in : in wb_master_in_type; + signal wb_out : out wb_master_out_type) is + + variable txt : line; + + begin + + -- start cycle on positive edge + wait until rising_edge(clk); + write(txt, now, right, 8); + write(txt, string'(" wrote ")); + write(txt, data); + write(txt, string'(" to addr. ")); + write(txt, addr); + + wb_out.dat_o <= std_logic_vector(to_unsigned(data, wb_out.dat_o'length)); + wb_out.adr_o <= std_logic_vector(to_unsigned(addr, wb_out.adr_o'length)); + + wb_out.we_o <= '1'; + wb_out.cyc_o <= '1'; + wb_out.stb_o <= '1'; + + -- wait for acknowledge + wait until rising_edge(clk); + if wb_in.ack_i /= '1' then + for i in 1 to TIMEOUT loop + wait until rising_edge(clk); + exit when wb_in.ack_i = '1'; + if (i = TIMEOUT) then + write (txt, string'("No acknowledge recevied!")); + end if; + end loop; + end if; + + wb_out.dat_o <= (others => '0'); + wb_out.adr_o <= (others => '0'); + wb_out.we_o <= '0'; + wb_out.cyc_o <= '0'; + wb_out.stb_o <= '0'; + + writeline(output, txt); + + end; + + procedure wb_read( + signal clk : in std_logic; + constant addr : in natural; + variable data : out natural; + signal wb_in : in wb_master_in_type; + signal wb_out : out wb_master_out_type) is + + variable txt : line; + variable in_data : natural; + + begin + + -- start cycle on positive edge + wait until rising_edge(clk); + write(txt, now, right, 8); + write(txt, string'(" read from addr. ")); + write(txt, addr); + writeline(output, txt); + + wb_out.adr_o <= std_logic_vector(to_unsigned(addr, wb_out.adr_o'length)); + wb_out.dat_o <= (others => '0'); + + wb_out.we_o <= '0'; + wb_out.cyc_o <= '1'; + wb_out.stb_o <= '1'; + + -- wait for acknowledge + wait until rising_edge(clk); + if wb_in.ack_i /= '1' then + for i in 1 to TIMEOUT loop + wait until rising_edge(clk); + exit when wb_in.ack_i = '1'; + if (i = TIMEOUT) then + write (txt, string'("No acknowledge recevied!")); + end if; + end loop; + end if; + + in_data := to_integer(unsigned(wb_in.dat_i)); + data := in_data; + + wb_out.adr_o <= (others => '0'); + wb_out.we_o <= '0'; + wb_out.cyc_o <= '0'; + wb_out.stb_o <= '0'; + + write(txt, now, right, 8); + write(txt, string'(" value: ")); + write(txt, in_data); + + writeline(output, txt); + + end; + + +end wb_pack; Index: simpcon/trunk/vhdl/sc_sys.vhd =================================================================== --- simpcon/trunk/vhdl/sc_sys.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc_sys.vhd (revision 26) @@ -0,0 +1,258 @@ +-- +-- sc_sys.vhd +-- +-- counter, interrrupt handling and watchdog bit +-- +-- Author: Martin Schoeberl martin@good-ear.com +-- +-- address map: +-- +-- 0 read clk counter, write irq ena +-- 1 read 1 MHz counter, write timer val (us) + irq ack +-- 2 write generates sw-int (for yield()) +-- 3 write wd port +-- 4 write generates SW exception, read exception reason +-- +-- todo: +-- +-- +-- 2003-07-05 new IO standard +-- 2003-08-15 us counter, irq added +-- 2005-11-30 change interface to SimpCon +-- 2006-01-11 added exception +-- 2007-03-17 changed interrupts to records +-- 2007-06-01 changed name from sc_cnt to sc_sys +-- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.jop_types.all; + +entity sc_sys is + +generic (addr_bits : integer; + clk_freq : integer; + cpu_id : 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); + +-- +-- Interrupts from IO devices +-- + irq_in : out irq_in_type; + exc_req : in exception_type; + + sync_out : in sync_out_type; + sync_in : out sync_in_type; + + wd : out std_logic + +); +end sc_sys ; + +architecture rtl of sc_sys is + + signal clock_cnt : std_logic_vector(31 downto 0); + signal pre_scale : std_logic_vector(7 downto 0); + signal us_cnt : std_logic_vector(31 downto 0); + + constant div_val : integer := clk_freq/1000000-1; + + signal timer_int : std_logic; + signal yield_int : std_logic; + signal int_ack : std_logic; + + signal timer : std_logic; + signal yield : std_logic; + + signal irq_cnt : std_logic_vector(31 downto 0); + signal timer_equ : std_logic; + signal timer_dly : std_logic; + + signal exc_type : std_logic_vector(7 downto 0); + + signal cpu_identity : std_logic_vector(31 downto 0); + + +begin + + cpu_identity <= std_logic_vector(to_unsigned(cpu_id,32)); + rdy_cnt <= "00"; -- no wait states + +-- +-- read cnt values +-- +process(clk, reset) +begin + + if (reset='1') then + rd_data <= (others => '0'); + elsif rising_edge(clk) then + + if rd='1' then + case address(2 downto 0) is + when "000" => + rd_data <= clock_cnt; + when "001" => + rd_data <= us_cnt; + when "100" => + rd_data(7 downto 0) <= exc_type; + rd_data(31 downto 8) <= (others => '0'); + when "110" => + rd_data <= cpu_identity; +-- when "111" => + when others => + rd_data(0) <= sync_out.s_out; + rd_data(31 downto 1) <= (others => '0'); + end case; + end if; + end if; + +end process; + +-- +-- compare timer value and us counter +-- and generate single shot +-- +process(us_cnt, irq_cnt) begin + timer_equ <= '0'; + if us_cnt = irq_cnt then + timer_equ <= '1'; + end if; +end process; + +process(clk, reset, timer_equ) begin + if (reset='1') then + timer_dly <= '0'; + elsif rising_edge(clk) then + timer_dly <= timer_equ; + end if; +end process; + + timer_int <= timer_equ and not timer_dly; + +-- +-- int processing from timer and yield request +-- +process(clk, reset, timer_int, yield_int) begin + + if (reset='1') then + timer <= '0'; + yield <= '0'; + elsif rising_edge(clk) then + if int_ack='1' then + timer <= '0'; + yield <= '0'; + else + if timer_int='1' then + timer <= '1'; + end if; + if yield_int='1' then + yield <= '1'; + end if; + end if; + end if; + +end process; + + irq_in.irq <= timer or yield; + + +-- +-- counters +-- pre_scale is 8 bit => fmax = 255 MHz +-- +process(clk, reset) begin + + if (reset='1') then + + clock_cnt <= (others => '0'); + us_cnt <= (others => '0'); + pre_scale <= std_logic_vector(to_unsigned(div_val, pre_scale'length)); + + elsif rising_edge(clk) then + + clock_cnt <= std_logic_vector(unsigned(clock_cnt) + 1); + pre_scale <= std_logic_vector(unsigned(pre_scale) - 1); + if pre_scale = "00000000" then + pre_scale <= std_logic_vector(to_unsigned(div_val, pre_scale'length)); + us_cnt <= std_logic_vector(unsigned(us_cnt) + 1); + end if; + + end if; +end process; + +-- +-- io write processing and exception processing +-- +process(clk, reset) + +begin + if (reset='1') then + + irq_in.irq_ena <= '0'; + irq_cnt <= (others => '0'); + int_ack <= '0'; + wd <= '0'; + sync_in.s_in <= '0'; + + exc_type <= (others => '0'); + irq_in.exc_int <= '0'; + + elsif rising_edge(clk) then + + int_ack <= '0'; + yield_int <= '0'; + + irq_in.exc_int <= '0'; + + if exc_req.spov='1' then + 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 + when "000" => + irq_in.irq_ena <= wr_data(0); + when "001" => + irq_cnt <= wr_data; + int_ack <= '1'; + when "010" => + yield_int <= '1'; + when "011" => + wd <= wr_data(0); + when "100" => + exc_type <= wr_data(7 downto 0); + irq_in.exc_int <= '1'; + when "110" => + -- nothing, processor id is read only + when others => +-- when "111" => + sync_in.s_in <= wr_data(0); + end case; + end if; + + end if; +end process; + +end rtl; Index: simpcon/trunk/vhdl/sc_sram32_flash.vhd =================================================================== --- simpcon/trunk/vhdl/sc_sram32_flash.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc_sram32_flash.vhd (revision 26) @@ -0,0 +1,443 @@ +-- +-- sc_sram32_flash.vhd +-- +-- SimpCon compliant external memory interface +-- for 32-bit SRAM (e.g. Cyclone board) +-- +-- Connection between mem_sc and the external memory bus +-- +-- memory mapping +-- +-- 0x000000-x7ffff external SRAM (w mirror) max. 512 kW (4*4 MBit) +-- 0x080000-xfffff external Flash (w mirror) max. 512 kB (4 MBit) +-- 0x100000-xfffff external NAND flash +-- +-- RAM: 32 bit word +-- ROM: 8 bit word (for flash programming) +-- +-- todo: +-- +-- +-- 2005-11-22 first version +-- 2005-12-02 added flash interface +-- + +Library IEEE; +use IEEE.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.jop_types.all; +use work.sc_pack.all; + +entity sc_mem_if is +generic (ram_ws : integer; rom_ws : integer); + +port ( + + clk, reset : in std_logic; + +-- +-- SimpCon memory interface +-- + sc_mem_out : in sc_mem_out_type; + sc_mem_in : out sc_in_type; + +-- memory interface + + ram_addr : out std_logic_vector(17 downto 0); + ram_dout : out std_logic_vector(31 downto 0); + ram_din : in std_logic_vector(31 downto 0); + ram_dout_en : out std_logic; + ram_ncs : out std_logic; + ram_noe : out std_logic; + ram_nwe : out std_logic; + +-- +-- config/program flash and big nand flash interface +-- + fl_a : out std_logic_vector(18 downto 0); + fl_d : inout std_logic_vector(7 downto 0); + fl_ncs : out std_logic; + fl_ncsb : out std_logic; + fl_noe : out std_logic; + fl_nwe : out std_logic; + fl_rdy : in std_logic + +); +end sc_mem_if; + +architecture rtl of sc_mem_if is + +-- +-- signals for mem interface +-- + type state_type is ( + idl, rd1, rd2, wr1, + fl_rd1, fl_rd2, fl_wr1, fl_wr2 + ); + signal state : state_type; + signal next_state : state_type; + + signal nwr_int : std_logic; + signal wait_state : unsigned(3 downto 0); + signal cnt : unsigned(1 downto 0); + + signal dout_ena : std_logic; + signal ram_data : std_logic_vector(31 downto 0); + signal ram_data_ena : std_logic; + + signal flash_dout : std_logic_vector(7 downto 0); + signal fl_dout_ena : std_logic; + signal flash_data : std_logic_vector(7 downto 0); + signal flash_data_ena : std_logic; + signal nand_rdy : std_logic; + + signal trans_ram : std_logic; + signal trans_flash : std_logic; + -- selection for read mux + signal ram_access : std_logic; + -- selection for Flash/NAND ncs + signal sel_flash : std_logic; + +begin + + assert MEM_ADDR_SIZE>=21 report "Too less address bits"; + ram_dout_en <= dout_ena; + + sc_mem_in.rdy_cnt <= cnt; + +-- +-- decode ram/flash +-- The signals are only valid for the first cycle +-- +process(sc_mem_out.address(20 downto 19)) +begin + + trans_ram <= '0'; + trans_flash <= '0'; + + case sc_mem_out.address(20 downto 19) is + when "00" => + trans_ram <= '1'; + when "01" => + trans_flash <= '1'; + when others => + null; + end case; + +end process; + +-- +-- Register memory address, write data and read data +-- +process(clk, reset) +begin + if reset='1' then + + ram_addr <= (others => '0'); + ram_dout <= (others => '0'); + ram_data <= (others => '0'); + flash_dout <= (others => '0'); + fl_a <= (others => '0'); + sel_flash <= '1'; -- AMD default + ram_access <= '1'; -- RAM default + + elsif rising_edge(clk) then + + if sc_mem_out.rd='1' or sc_mem_out.wr='1' then + if trans_ram='1' then + ram_access <= '1'; + ram_addr <= sc_mem_out.address(17 downto 0); + else + ram_access <= '0'; + fl_a <= sc_mem_out.address(18 downto 0); + -- select flash type + -- and keep it selected + if trans_flash='1' then + sel_flash <= '1'; + else + sel_flash <= '0'; + end if; + end if; + end if; + if sc_mem_out.wr='1' then + if trans_ram='1' then + ram_dout <= sc_mem_out.wr_data; + else + flash_dout <= sc_mem_out.wr_data(7 downto 0); + end if; + end if; + if ram_data_ena='1' then + ram_data <= ram_din; + end if; + if flash_data_ena='1' then + -- signal NAND rdy only for NAND access + nand_rdy <= fl_rdy and not sel_flash; + flash_data <= fl_d; + end if; + + end if; +end process; + +-- +-- MUX registered RAM and Flash data +-- +process(ram_access, ram_data, flash_data, nand_rdy) + +begin + if (ram_access='1') then + sc_mem_in.rd_data <= ram_data; + else + sc_mem_in.rd_data <= std_logic_vector(to_unsigned(0, 32-9)) & nand_rdy & flash_data; + end if; +end process; + +-- +-- 'delay' nwe 1/2 cycle -> change on falling edge +-- +process(clk, reset) + +begin + if (reset='1') then + ram_nwe <= '1'; + elsif falling_edge(clk) then + ram_nwe <= nwr_int; + end if; + +end process; + + +-- +-- next state logic +-- +process(state, sc_mem_out, trans_ram, wait_state) + +begin + + next_state <= state; + + case state is + + when idl => + if sc_mem_out.rd='1' then + if trans_ram='1' then + if ram_ws=0 then + -- then we omit state rd1! + next_state <= rd2; + else + next_state <= rd1; + end if; + else + next_state <= fl_rd1; + end if; + elsif sc_mem_out.wr='1' then + if trans_ram='1' then + next_state <= wr1; + else + next_state <= fl_wr1; + end if; + end if; + + -- the WS state + when rd1 => + if wait_state=2 then + next_state <= rd2; + end if; + + -- last read state + when rd2 => + next_state <= idl; + -- This should do to give us a pipeline + -- level of 2 for read + -- we don't care about a flash trans. + -- in the pipeline! + if sc_mem_out.rd='1' then + if ram_ws=0 then + -- then we omit state rd1! + next_state <= rd2; + else + next_state <= rd1; + end if; + elsif sc_mem_out.wr='1' then + next_state <= wr1; + end if; + + -- the WS state + when wr1 => +-- TODO: check what happens on ram_ws=0 +-- TODO: do we need a write pipelining? +-- not at the moment, but parhaps later when +-- we write the stack content to main memory + if wait_state=1 then + next_state <= idl; + end if; + + when fl_rd1 => + if wait_state=2 then + next_state <= fl_rd2; + end if; + + when fl_rd2 => + next_state <= idl; + -- we do no pipelining with the Flashs + + when fl_wr1 => + if wait_state=2 then + next_state <= fl_wr2; + end if; + + when fl_wr2 => + next_state <= idl; + + end case; + +end process; + +-- +-- state machine register +-- output register (RAM, Flash control lines) +-- +process(clk, reset) + +begin + if (reset='1') then + state <= idl; + dout_ena <= '0'; + ram_ncs <= '1'; + ram_noe <= '1'; + ram_data_ena <= '0'; + + fl_noe <= '1'; + fl_nwe <= '1'; + flash_data_ena <= '0'; + fl_dout_ena <= '0'; + + elsif rising_edge(clk) then + + state <= next_state; + dout_ena <= '0'; + ram_ncs <= '1'; + ram_noe <= '1'; + ram_data_ena <= '0'; + + fl_noe <= '1'; + fl_nwe <= '1'; + flash_data_ena <= '0'; + fl_dout_ena <= '0'; + + case next_state is + + when idl => + + -- the wait state + when rd1 => + ram_ncs <= '0'; + ram_noe <= '0'; + + -- last read state + when rd2 => + ram_ncs <= '0'; + ram_noe <= '0'; + ram_data_ena <= '1'; + + + -- the WS state + when wr1 => + ram_ncs <= '0'; + dout_ena <= '1'; + + when fl_rd1 => + fl_noe <= '0'; + + when fl_rd2 => + fl_noe <= '0'; + flash_data_ena <= '1'; + + when fl_wr1 => + fl_nwe <= '0'; + fl_dout_ena <= '1'; + + when fl_wr2 => + fl_dout_ena <= '1'; + + end case; + + end if; +end process; + +-- +-- nwr combinatorial processing +-- for the negativ edge +-- +process(next_state, state) +begin + + nwr_int <= '1'; + if next_state=wr1 then + nwr_int <= '0'; + end if; + +end process; + +-- +-- wait_state processing +-- cs delay, dout enable +-- +process(clk, reset) +begin + if (reset='1') then + wait_state <= (others => '1'); + cnt <= "00"; + elsif rising_edge(clk) then + + wait_state <= wait_state-1; + + cnt <= "11"; + if next_state=idl then + cnt <= "00"; + -- if wait_state<4 then + elsif wait_state(3 downto 2)="00" then + cnt <= wait_state(1 downto 0)-1; + end if; + + if sc_mem_out.rd='1' or sc_mem_out.wr='1' then + if trans_ram='1' then + wait_state <= to_unsigned(ram_ws+1, 4); + if ram_ws<3 then + cnt <= to_unsigned(ram_ws+1, 2); + else + cnt <= "11"; + end if; + else + wait_state <= to_unsigned(rom_ws+1, 4); + cnt <= "11"; + end if; + end if; + + end if; +end process; + +-- +-- Flash signals +-- + +-- +-- leave last ncs. Only toggle between two flashs. +-- + fl_ncs <= not sel_flash; -- Flash ncs + fl_ncsb <= sel_flash; -- NAND ncs + +-- +-- tristate output +-- +process(fl_dout_ena, flash_dout) + +begin + if (fl_dout_ena='1') then + fl_d <= flash_dout(7 downto 0); + else + fl_d <= (others => 'Z'); + end if; +end process; + +end rtl; Index: simpcon/trunk/vhdl/sc_arbiter_pack.vhd =================================================================== --- simpcon/trunk/vhdl/sc_arbiter_pack.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc_arbiter_pack.vhd (revision 26) @@ -0,0 +1,12 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.sc_pack.all; + +package sc_arbiter_pack is + + type arb_out_type is array (integer range <>) of sc_mem_out_type; + type arb_in_type is array (integer range <>) of sc_in_type; + +end sc_arbiter_pack; Index: simpcon/trunk/vhdl/sc_arbiter_2m.vhd =================================================================== --- simpcon/trunk/vhdl/sc_arbiter_2m.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc_arbiter_2m.vhd (revision 26) @@ -0,0 +1,390 @@ + + +-- 150407: first working version with records +-- 170407: produce number of registers depending on the cpu_cnt +-- 110507: * arbiter that can be used with prefered number of masters +-- * full functional arbiter with two masters +-- * short modelsim test with 3 masters carried out +-- 290607: used for JTRES07 submission + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.sc_pack.all; +use work.sc_arbiter_pack.all; + +entity arbiter is +generic( + addr_bits : integer; + cpu_cnt : integer); -- number of masters for the arbiter +port ( + clk, reset : in std_logic; + arb_out : in arb_out_type(0 to cpu_cnt-1); + arb_in : out arb_in_type(0 to cpu_cnt-1); + mem_out : out sc_mem_out_type; + mem_in : in sc_in_type +); +end arbiter; + + +architecture rtl of arbiter is + +-- signals for the input register of each master + + type reg_type is record + rd : std_logic; + wr : std_logic; + wr_data : std_logic_vector(31 downto 0); + address : std_logic_vector(addr_bits-1 downto 0); + end record; + + type reg_array_type is array (0 to cpu_cnt-1) of reg_type; + signal reg_in : reg_array_type; + +-- one fsm for each CPU + + type state_type is (idle, read, write, waitingR, sendR, + waitingW, sendW); + type state_array is array (0 to cpu_cnt-1) of state_type; + signal state : state_array; + signal next_state : state_array; + +-- one fsm for each serve + + type serve_type is (idl, serv); + type serve_array is array (0 to cpu_cnt-1) of serve_type; + signal this_state : serve_array; + signal follow_state : serve_array; + +-- arbiter + + type set_type is array (0 to cpu_cnt-1) of std_logic; + signal set : set_type; + + +begin + + +-- Generates the input register and saves incoming data for each master +gen_register: for i in 0 to cpu_cnt-1 generate + process(clk, reset) + begin + if reset = '1' then + reg_in(i).rd <= '0'; + reg_in(i).wr <= '0'; + reg_in(i).wr_data <= (others => '0'); + reg_in(i).address <= (others => '0'); + elsif rising_edge(clk) then + if arb_out(i).rd = '1' or arb_out(i).wr = '1' then + reg_in(i).rd <= arb_out(i).rd; + reg_in(i).wr <= arb_out(i).wr; + reg_in(i).address <= arb_out(i).address; + reg_in(i).wr_data <= arb_out(i).wr_data; + end if; + end if; + end process; +end generate; + +-- Generates next state of the FSM for each master +gen_next_state: for i in 0 to cpu_cnt-1 generate + process(reset, state, arb_out, mem_in, this_state, reg_in) + begin + + next_state(i) <= state(i); + + case state(i) is + when idle => + + if this_state(i) = serv then -- checks if this CPU is on turn + if mem_in.rdy_cnt = 1 and arb_out(i).rd = '1' then + next_state(i) <= read; + elsif (mem_in.rdy_cnt = 0) and (arb_out(i).rd = '1' + or arb_out(i).wr = '1') then + for k in 0 to cpu_cnt-1 loop + if arb_out(k).rd = '1' or arb_out(k).wr = '1' then + if i<=k then + if arb_out(i).rd = '1' then + next_state(i) <= read; + exit; + elsif arb_out(i).wr = '1' then + next_state(i) <= write; + exit; + end if; + else + if arb_out(i).rd = '1' then + next_state(i) <= waitingR; + exit; + elsif arb_out(i).wr = '1' then + next_state(i) <= waitingW; + exit; + end if; + end if; + elsif reg_in(k).rd = '1' or reg_in(k).wr = '1' then + if arb_out(i).rd = '1' then + next_state(i) <= waitingR; + exit; + elsif arb_out(i).wr = '1' then + next_state(i) <= waitingW; + exit; + end if; + else + if arb_out(i).rd = '1' then + next_state(i) <= read; + elsif arb_out(i).wr = '1' then + next_state(i) <= write; + end if; + end if; + end loop; + end if; + else + for j in 0 to cpu_cnt-1 loop + if this_state(j) = serv then + if mem_in.rdy_cnt = 1 and arb_out(j).rd = '1' and + arb_out(i).rd = '1' then + next_state(i) <= waitingR; + exit; + elsif mem_in.rdy_cnt = 1 and arb_out(j).rd = '1' and + arb_out(i).wr = '1' then + next_state(i) <= waitingW; + exit; + end if; + else + if mem_in.rdy_cnt = 0 then + if arb_out(j).rd = '1' or arb_out(j).wr = '1' then + if i<=j then + if arb_out(i).rd = '1' then + next_state(i) <= read; + exit; -- new + elsif arb_out(i).wr = '1' then + next_state(i) <= write; + exit; -- new + end if; + else + if arb_out(i).rd = '1' then + next_state(i) <= waitingR; + exit; + elsif arb_out(i).wr = '1' then + next_state(i) <= waitingW; + exit; + end if; + end if; + -- new + elsif (state(j) = waitingR) or (state(j) = waitingW) then + if arb_out(i).rd = '1' then + next_state(i) <= waitingR; + elsif arb_out(i).wr = '1' then + next_state(i) <= waitingW; + exit; + end if; + -- new + elsif arb_out(i).rd = '1' then + next_state(i) <= read; + elsif arb_out(i).wr = '1' then + next_state(i) <= write; + end if; + else + if arb_out(i).rd = '1' then + next_state(i) <= waitingR; + exit; + elsif arb_out(i).wr = '1' then + next_state(i) <= waitingW; + exit; + end if; + end if; + end if; + end loop; + end if; + + when read => + next_state(i) <= idle; + + when write => + next_state(i) <= idle; + + when waitingR => + if mem_in.rdy_cnt = 0 then + -- checks which CPU in waitingR has highest priority + for j in 0 to cpu_cnt-1 loop + --if arb_out(j).rd = '1' or arb_out(j).wr = '1' then + -- next_state(i) <= waitingR; + -- exit; + --els + if (state(j) = waitingR) or (state(j) = waitingW) then + if j + next_state(i) <= idle; + + when waitingW => + if mem_in.rdy_cnt = 0 then + for j in 0 to cpu_cnt-1 loop + --if arb_out(j).rd = '1' or arb_out(j).wr = '1' then + -- next_state(i) <= waitingW; + -- exit; + --els + if (state(j) = waitingR) or (state(j) = waitingW) then + if j + next_state(i) <= idle; + + end case; + end process; +end generate; + + +-- Generates the FSM state for each master +gen_state: for i in 0 to cpu_cnt-1 generate + process (clk, reset) + begin + if (reset = '1') then + state(i) <= idle; + elsif (rising_edge(clk)) then + state(i) <= next_state(i); + end if; + end process; +end generate; + + +-- The arbiter output +process (arb_out, reg_in, next_state) +begin + + mem_out.rd <= '0'; + mem_out.wr <= '0'; + mem_out.address <= (others => '0'); + mem_out.wr_data <= (others => '0'); + + for i in 0 to cpu_cnt-1 loop + set(i) <= '0'; + + case next_state(i) is + when idle => + + when read => + set(i) <= '1'; + mem_out.rd <= arb_out(i).rd; + mem_out.address <= arb_out(i).address; + + when write => + set(i) <= '1'; + mem_out.wr <= arb_out(i).wr; + mem_out.address <= arb_out(i).address; + mem_out.wr_data <= arb_out(i).wr_data; + + when waitingR => + + when sendR => + set(i) <= '1'; + mem_out.rd <= reg_in(i).rd; + mem_out.address <= reg_in(i).address; + + when waitingW => + + when sendW => + set(i) <= '1'; + mem_out.wr <= reg_in(i).wr; + mem_out.address <= reg_in(i).address; + mem_out.wr_data <= reg_in(i).wr_data; + + end case; + end loop; +end process; + +-- generation of follow_state +gen_serve: for i in 0 to cpu_cnt-1 generate + process(mem_in, set, this_state) + begin + case this_state(i) is + when idl => + follow_state(i) <= idl; + if set(i) = '1' then + follow_state(i) <= serv; + end if; + when serv => + follow_state(i) <= serv; + if mem_in.rdy_cnt = 0 and set(i) = '0' then + follow_state(i) <= idl; + end if; + end case; + end process; +end generate; + +gen_serve2: for i in 0 to cpu_cnt-1 generate + process (clk, reset) + begin + if (reset = '1') then + this_state(i) <= idl; + elsif (rising_edge(clk)) then + this_state(i) <= follow_state(i); + end if; + end process; +end generate; + +gen_rdy_cnt: for i in 0 to cpu_cnt-1 generate + process (mem_in, state, this_state) + begin + arb_in(i).rdy_cnt <= mem_in.rdy_cnt; + arb_in(i).rd_data <= mem_in.rd_data; + + case state(i) is + when idle => + case this_state(i) is + when idl => + arb_in(i).rdy_cnt <= "00"; + when serv => + end case; + + when read => + + when write => + + when waitingR => + arb_in(i).rdy_cnt <= "11"; + + when sendR => + + when waitingW => + arb_in(i).rdy_cnt <= "11"; + + when sendW => + + end case; + end process; +end generate; + +end rtl; Index: simpcon/trunk/vhdl/sc_arbiter.vhd =================================================================== --- simpcon/trunk/vhdl/sc_arbiter.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc_arbiter.vhd (revision 26) @@ -0,0 +1,424 @@ + + +-- 150407: first working version with records +-- 170407: produce number of registers depending on the cpu_cnt +-- 110507: * arbiter that can be used with prefered number of masters +-- * full functional arbiter with two masters +-- * short modelsim test with 3 masters carried out +-- 190607: Problem found: Both CPU1 and CPU2 start to read cache line!!! +-- 030707: Several bugs are fixed now. CMP with 3 running masters functions! + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.sc_pack.all; +use work.sc_arbiter_pack.all; + +entity arbiter is +generic( + addr_bits : integer; + cpu_cnt : integer); -- number of masters for the arbiter +port ( + clk, reset : in std_logic; + arb_out : in arb_out_type(0 to cpu_cnt-1); + arb_in : out arb_in_type(0 to cpu_cnt-1); + mem_out : out sc_mem_out_type; + mem_in : in sc_in_type +); +end arbiter; + + +architecture rtl of arbiter is + +-- signals for the input register of each master + + type reg_type is record + rd : std_logic; + wr : std_logic; + wr_data : std_logic_vector(31 downto 0); + address : std_logic_vector(addr_bits-1 downto 0); + end record; + + type reg_array_type is array (0 to cpu_cnt-1) of reg_type; + signal reg_in : reg_array_type; + +-- one fsm for each CPU + + type state_type is (idle, read, write, waitingR, sendR, + waitingW, sendW); + type state_array is array (0 to cpu_cnt-1) of state_type; + signal state : state_array; + signal next_state : state_array; + +-- one fsm for each serve + + type serve_type is (idl, serv); + type serve_array is array (0 to cpu_cnt-1) of serve_type; + signal this_state : serve_array; + signal follow_state : serve_array; + +-- arbiter + + type set_type is array (0 to cpu_cnt-1) of std_logic; + signal set : set_type; + signal waiting : set_type; + signal masterWaiting : std_logic; + + +begin + + +-- Generates the input register and saves incoming data for each master +gen_register: for i in 0 to cpu_cnt-1 generate + process(clk, reset) + begin + if reset = '1' then + reg_in(i).rd <= '0'; + reg_in(i).wr <= '0'; + reg_in(i).wr_data <= (others => '0'); + reg_in(i).address <= (others => '0'); + elsif rising_edge(clk) then + if arb_out(i).rd = '1' or arb_out(i).wr = '1' then + reg_in(i).rd <= arb_out(i).rd; + reg_in(i).wr <= arb_out(i).wr; + reg_in(i).address <= arb_out(i).address; + reg_in(i).wr_data <= arb_out(i).wr_data; + end if; + end if; + end process; +end generate; + +-- Register for masterWaiting +process(clk, reset) + begin + if reset = '1' then + masterWaiting <= '0'; + elsif rising_edge(clk) then + for i in 0 to cpu_cnt-1 loop + if waiting(i) = '1' then + masterWaiting <= '1'; + exit; + else + masterWaiting <= '0'; + end if; + end loop; + end if; + end process; + +-- Generates next state of the FSM for each master +gen_next_state: for i in 0 to cpu_cnt-1 generate + process(reset, state, arb_out, mem_in, this_state, reg_in, masterWaiting) + begin + + next_state(i) <= state(i); + waiting(i) <= '0'; + + case state(i) is + when idle => + + -- checks if this CPU is on turn (pipelined access) + if this_state(i) = serv then + -- pipelined access + if mem_in.rdy_cnt = 1 and arb_out(i).rd = '1' then + next_state(i) <= read; + + elsif (mem_in.rdy_cnt = 0 and (arb_out(i).rd = '1' or arb_out(i).wr = '1')) then + + -- check if some master is waiting + if masterWaiting = '1' then + if arb_out(i).rd = '1' then + next_state(i) <= waitingR; + waiting(i) <= '1'; + elsif arb_out(i).wr = '1' then + next_state(i) <= waitingW; + waiting(i) <= '1'; + end if; + + -- check if parallel access + else + for j in 0 to cpu_cnt-1 loop + if arb_out(j).rd = '1' or arb_out(j).wr = '1' then + if i<=j then + if arb_out(i).rd = '1' then + next_state(i) <= read; + exit; + elsif arb_out(i).wr = '1' then + next_state(i) <= write; + exit; + end if; + else + if arb_out(i).rd = '1' then + next_state(i) <= waitingR; + waiting(i) <= '1'; + exit; + elsif arb_out(i).wr = '1' then + next_state(i) <= waitingW; + waiting(i) <= '1'; + exit; + end if; + end if; + end if; + end loop; + end if; + + -- all other kinds of rdy_cnt + else + if arb_out(i).rd = '1' then + next_state(i) <= waitingR; + waiting(i) <= '1'; + elsif arb_out(i).wr = '1' then + next_state(i) <= waitingW; + waiting(i) <= '1'; + end if; + end if; + + -- CPU is not on turn (no pipelined access possible) + else + if (mem_in.rdy_cnt = 0 and (arb_out(i).rd = '1' or arb_out(i).wr = '1')) then + -- check if some master is waiting + if masterWaiting = '1' then + if arb_out(i).rd = '1' then + next_state(i) <= waitingR; + waiting(i) <= '1'; + elsif arb_out(i).wr = '1' then + next_state(i) <= waitingW; + waiting(i) <= '1'; + end if; + + -- check if parallel access + else + for j in 0 to cpu_cnt-1 loop + if arb_out(j).rd = '1' or arb_out(j).wr = '1' then + if i<=j then + if arb_out(i).rd = '1' then + next_state(i) <= read; + exit; + elsif arb_out(i).wr = '1' then + next_state(i) <= write; + exit; + end if; + else + if arb_out(i).rd = '1' then + next_state(i) <= waitingR; + waiting(i) <= '1'; + exit; + elsif arb_out(i).wr = '1' then + next_state(i) <= waitingW; + waiting(i) <= '1'; + exit; + end if; + end if; + -- if no parallel access, master can access + else + if arb_out(i).rd = '1' then + next_state(i) <= read; + elsif arb_out(i).wr = '1' then + next_state(i) <= write; + end if; + end if; + end loop; + end if; + + -- rdy_cnt != 0 + else + if arb_out(i).rd = '1' then + next_state(i) <= waitingR; + waiting(i) <= '1'; + elsif arb_out(i).wr = '1' then + next_state(i) <= waitingW; + waiting(i) <= '1'; + end if; + end if; + end if; + + + when read => + next_state(i) <= idle; + + when write => + next_state(i) <= idle; + + when waitingR => + if mem_in.rdy_cnt = 0 then + -- checks which CPU in waitingR has highest priority + for j in 0 to cpu_cnt-1 loop + if (state(j) = waitingR) or (state(j) = waitingW) then + if j + next_state(i) <= idle; + + when waitingW => + + if mem_in.rdy_cnt = 0 then + for j in 0 to cpu_cnt-1 loop + if (state(j) = waitingR) or (state(j) = waitingW) then + if j + next_state(i) <= idle; + + end case; + end process; +end generate; + + +-- Generates the FSM state for each master +gen_state: for i in 0 to cpu_cnt-1 generate + process (clk, reset) + begin + if (reset = '1') then + state(i) <= idle; + elsif (rising_edge(clk)) then + state(i) <= next_state(i); + end if; + end process; +end generate; + + +-- The arbiter output +process (arb_out, reg_in, next_state) +begin + + mem_out.rd <= '0'; + mem_out.wr <= '0'; + mem_out.address <= (others => '0'); + mem_out.wr_data <= (others => '0'); + + for i in 0 to cpu_cnt-1 loop + set(i) <= '0'; + + case next_state(i) is + when idle => + + when read => + set(i) <= '1'; + mem_out.rd <= arb_out(i).rd; + mem_out.address <= arb_out(i).address; + + when write => + set(i) <= '1'; + mem_out.wr <= arb_out(i).wr; + mem_out.address <= arb_out(i).address; + mem_out.wr_data <= arb_out(i).wr_data; + + when waitingR => + + when sendR => + set(i) <= '1'; + mem_out.rd <= reg_in(i).rd; + mem_out.address <= reg_in(i).address; + + when waitingW => + + when sendW => + set(i) <= '1'; + mem_out.wr <= reg_in(i).wr; + mem_out.address <= reg_in(i).address; + mem_out.wr_data <= reg_in(i).wr_data; + + end case; + end loop; +end process; + +-- generation of follow_state +gen_serve: for i in 0 to cpu_cnt-1 generate + process(mem_in, set, this_state) + begin + case this_state(i) is + when idl => + follow_state(i) <= idl; + if set(i) = '1' then + follow_state(i) <= serv; + end if; + when serv => + follow_state(i) <= serv; + if mem_in.rdy_cnt = 0 and set(i) = '0' then + follow_state(i) <= idl; + end if; + end case; + end process; +end generate; + +gen_serve2: for i in 0 to cpu_cnt-1 generate + process (clk, reset) + begin + if (reset = '1') then + this_state(i) <= idl; + elsif (rising_edge(clk)) then + this_state(i) <= follow_state(i); + end if; + end process; +end generate; + +gen_rdy_cnt: for i in 0 to cpu_cnt-1 generate + process (mem_in, state, this_state) + begin + arb_in(i).rdy_cnt <= mem_in.rdy_cnt; + arb_in(i).rd_data <= mem_in.rd_data; + + case state(i) is + when idle => + case this_state(i) is + when idl => + arb_in(i).rdy_cnt <= "00"; + when serv => + end case; + + when read => + + when write => + + when waitingR => + arb_in(i).rdy_cnt <= "11"; + + when sendR => + + when waitingW => + arb_in(i).rdy_cnt <= "11"; + + when sendW => + + end case; + end process; +end generate; + +end rtl; Index: simpcon/trunk/vhdl/sc_sram16.vhd =================================================================== --- simpcon/trunk/vhdl/sc_sram16.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc_sram16.vhd (revision 26) @@ -0,0 +1,377 @@ +-- +-- sc_sram16.vhd +-- +-- SimpCon compliant external memory interface +-- for 16-bit SRAM (e.g. Altera DE2 board) +-- +-- High 16-bit word is at lower address +-- +-- Connection between mem_sc and the external memory bus +-- +-- memory mapping +-- +-- 000000-x7ffff external SRAM (w mirror) max. 512 kW (4*4 MBit) +-- +-- RAM: 16 bit word +-- +-- +-- 2006-08-01 Adapted from sc_ram32.vhd +-- 2006-08-16 Rebuilding the already working (lost) version +-- Use wait_state, din register without MUX +-- 2007-06-04 changed SimpCon to records +-- 2007-09-09 Additional input register for high data (correct SimpCon violation) +-- + +Library IEEE; +use IEEE.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.jop_types.all; +use work.sc_pack.all; + +entity sc_mem_if is +generic (ram_ws : integer; addr_bits : integer); + +port ( + + clk, reset : in std_logic; + +-- +-- SimpCon memory interface +-- + sc_mem_out : in sc_mem_out_type; + sc_mem_in : out sc_in_type; + +-- memory interface + + ram_addr : out std_logic_vector(addr_bits-1 downto 0); + ram_dout : out std_logic_vector(15 downto 0); + ram_din : in std_logic_vector(15 downto 0); + ram_dout_en : out std_logic; + ram_ncs : out std_logic; + ram_noe : out std_logic; + ram_nwe : out std_logic + +); +end sc_mem_if; + +architecture rtl of sc_mem_if is + +-- +-- signals for mem interface +-- + type state_type is ( + idl, rd1_h, rd2_h, rd1_l, rd2_l, + wr_h, wr_idl, wr_l + ); + signal state : state_type; + signal next_state : state_type; + + signal nwr_int : std_logic; + signal wait_state : unsigned(3 downto 0); + signal cnt : unsigned(1 downto 0); + + signal dout_ena : std_logic; + signal rd_data_ena_h : std_logic; + signal rd_data_ena_l : std_logic; + signal inc_addr : std_logic; + signal wr_low : std_logic; + + signal ram_dout_low : std_logic_vector(15 downto 0); + signal ram_din_high : std_logic_vector(15 downto 0); + + signal ram_din_reg : std_logic_vector(31 downto 0); + +begin + + ram_dout_en <= dout_ena; + + sc_mem_in.rdy_cnt <= cnt; + +-- +-- Register memory address, write data and read data +-- +process(clk, reset) +begin + if reset='1' then + + ram_addr <= (others => '0'); + ram_dout <= (others => '0'); + ram_dout_low <= (others => '0'); + + elsif rising_edge(clk) then + + if sc_mem_out.rd='1' or sc_mem_out.wr='1' then + ram_addr <= sc_mem_out.address(addr_bits-2 downto 0) & "0"; + end if; + if inc_addr='1' then + ram_addr(0) <= '1'; + end if; + if sc_mem_out.wr='1' then + ram_dout <= sc_mem_out.wr_data(31 downto 16); + ram_dout_low <= sc_mem_out.wr_data(15 downto 0); + end if; + if wr_low='1' then + ram_dout <= ram_dout_low; + end if; + -- use an addtional input register to adhire the SimpCon spec + -- to not change rd_data untill the full new word is available + -- results in input MUX at RAM data input + if rd_data_ena_h='1' then + ram_din_high <= ram_din; + end if; + if rd_data_ena_l='1' then + -- move first word to higher half + ram_din_reg(31 downto 16) <= ram_din_high; + -- read second word + ram_din_reg(15 downto 0) <= ram_din; + end if; + + end if; +end process; + + sc_mem_in.rd_data <= ram_din_reg; + +-- +-- 'delay' nwe 1/2 cycle -> change on falling edge +-- +process(clk, reset) + +begin + if (reset='1') then + ram_nwe <= '1'; + elsif falling_edge(clk) then + ram_nwe <= nwr_int; + end if; + +end process; + + +-- +-- next state logic +-- +process(state, sc_mem_out.rd, sc_mem_out.wr, wait_state) + +begin + + next_state <= state; + + case state is + + when idl => + if sc_mem_out.rd='1' then + if ram_ws=0 then + -- then we omit state rd1! + next_state <= rd2_h; + else + next_state <= rd1_h; + end if; + elsif sc_mem_out.wr='1' then + next_state <= wr_h; + end if; + + -- the WS state + when rd1_h => + if wait_state=2 then + next_state <= rd2_h; + end if; + + when rd2_h => + -- go to read low word + if ram_ws=0 then + -- then we omit state rd1! + next_state <= rd2_l; + else + next_state <= rd1_l; + end if; + + -- the WS state + when rd1_l => + if wait_state=2 then + next_state <= rd2_l; + end if; + + -- last read state + when rd2_l => + next_state <= idl; + -- This should do to give us a pipeline + -- level of 2 for read + if sc_mem_out.rd='1' then + if ram_ws=0 then + -- then we omit state rd1! + next_state <= rd2_h; + else + next_state <= rd1_h; + end if; + elsif sc_mem_out.wr='1' then + next_state <= wr_h; + end if; + + -- the WS state + when wr_h => +-- TODO: check what happens on ram_ws=0 +-- TODO: do we need a write pipelining? +-- not at the moment, but parhaps later when +-- we write the stack content to main memory + if wait_state=1 then + next_state <= wr_idl; + end if; + + -- one idle state for nwr to go high + when wr_idl => + next_state <= wr_l; + + -- the WS state + when wr_l => + if wait_state=1 then + next_state <= idl; + end if; + + end case; + +end process; + +-- +-- state machine register +-- output register +-- +process(clk, reset) + +begin + if (reset='1') then + state <= idl; + dout_ena <= '0'; + ram_ncs <= '1'; + ram_noe <= '1'; + rd_data_ena_h <= '0'; + rd_data_ena_l <= '0'; + inc_addr <= '0'; + wr_low <= '0'; + elsif rising_edge(clk) then + + state <= next_state; + dout_ena <= '0'; + ram_ncs <= '1'; + ram_noe <= '1'; + rd_data_ena_h <= '0'; + rd_data_ena_l <= '0'; + inc_addr <= '0'; + wr_low <= '0'; + + case next_state is + + when idl => + + -- the wait state + when rd1_h => + ram_ncs <= '0'; + ram_noe <= '0'; + + -- high word last read state + when rd2_h => + ram_ncs <= '0'; + ram_noe <= '0'; + rd_data_ena_h <= '1'; + inc_addr <= '1'; + + -- the wait state + when rd1_l => + ram_ncs <= '0'; + ram_noe <= '0'; + + -- low word last read state + when rd2_l => + ram_ncs <= '0'; + ram_noe <= '0'; + rd_data_ena_l <= '1'; + + -- the WS state + when wr_h => + ram_ncs <= '0'; + dout_ena <= '1'; + + -- high word last write state + when wr_idl => + ram_ncs <= '1'; + dout_ena <= '1'; + inc_addr <= '1'; + wr_low <= '1'; + + -- the WS state + when wr_l => + ram_ncs <= '0'; + dout_ena <= '1'; + + end case; + + end if; +end process; + +-- +-- nwr combinatorial processing +-- for the negativ edge +-- +process(next_state, state) +begin + + nwr_int <= '1'; + -- this is the 'correct' version wich needs + -- at minimum 2 cycles for the RAM access +-- if (state=wr_l and next_state=wr_l) or +-- (state=wr_h and next_state=wr_h) then + -- Slightly out of the SRAM spec. nwr goes + -- low befor ncs to allow single cycle + -- access + if next_state=wr_l or next_state=wr_h then + + nwr_int <= '0'; + end if; + +end process; + +-- +-- wait_state processing +-- +process(clk, reset) +begin + if (reset='1') then + wait_state <= (others => '1'); + cnt <= "00"; + elsif rising_edge(clk) then + + wait_state <= wait_state-1; + + cnt <= "11"; + if next_state=idl then + cnt <= "00"; + end if; + + if sc_mem_out.rd='1' or sc_mem_out.wr='1' then + wait_state <= to_unsigned(ram_ws+1, 4); + end if; + + if state=rd2_h or state=wr_idl then + wait_state <= to_unsigned(ram_ws+1, 4); + if ram_ws<3 then + cnt <= to_unsigned(ram_ws+1, 2); + else + cnt <= "11"; + end if; + end if; + + if state=rd1_l or state=rd2_l or state=wr_l then + -- take care for pipelined cach transfer + -- there is no idl state and cnt should + -- go back to "11" + if sc_mem_out.rd='0' and sc_mem_out.wr='0' then + -- if wait_state<4 then + if wait_state(3 downto 2)="00" then + cnt <= wait_state(1 downto 0)-1; + end if; + end if; + end if; + + end if; +end process; + +end rtl; Index: simpcon/trunk/vhdl/scio_min.vhd =================================================================== --- simpcon/trunk/vhdl/scio_min.vhd (nonexistent) +++ simpcon/trunk/vhdl/scio_min.vhd (revision 26) @@ -0,0 +1,199 @@ +-- +-- scio_min.vhd +-- +-- io devices for minimal configuration +-- only counter, wd and serial line, alle io pins are tri statet +-- +-- +-- io address mapping: +-- +-- IO Base is 0xffffff80 for 'fast' constants (bipush) +-- +-- 0x00 0-3 system clock counter, us counter, timer int, wd bit +-- 0x10 0-1 uart (download) +-- +-- status word in uarts: +-- 0 uart transmit data register empty +-- 1 uart read data register full +-- +-- +-- todo: +-- +-- +-- 2003-07-09 created +-- 2005-08-27 ignore ncts on uart +-- 2005-11-30 changed to SimpCon +-- 2007-03-17 use records +-- +-- + + +Library IEEE; +use IEEE.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.jop_types.all; +use work.sc_pack.all; +use work.jop_config.all; + +entity scio is +generic (cpu_id : integer := 0); +port ( + clk : in std_logic; + reset : in std_logic; + +-- +-- SimpCon IO interface +-- + sc_io_out : in sc_io_out_type; + sc_io_in : out sc_in_type; + +-- +-- Interrupts from IO devices +-- + 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; + rxd : in std_logic; + ncts : in std_logic; + nrts : out std_logic; + +-- watch dog + + wd : out std_logic; + +-- core i/o pins + l : inout std_logic_vector(20 downto 1); + r : inout std_logic_vector(20 downto 1); + t : inout std_logic_vector(6 downto 1); + b : inout std_logic_vector(10 downto 1) +); +end scio; + + +architecture rtl of scio is + + constant SLAVE_CNT : integer := 3; + -- SLAVE_CNT <= 2**DECODE_BITS + -- take care of USB address 0x20! + constant DECODE_BITS : integer := 2; + -- number of bits that can be used inside the slave + constant SLAVE_ADDR_BITS : integer := 4; + + type slave_bit is array(0 to SLAVE_CNT-1) of std_logic; + signal sc_rd, sc_wr : slave_bit; + + type slave_dout is array(0 to SLAVE_CNT-1) of std_logic_vector(31 downto 0); + signal sc_dout : slave_dout; + + type slave_rdy_cnt is array(0 to SLAVE_CNT-1) of unsigned(1 downto 0); + signal sc_rdy_cnt : slave_rdy_cnt; + + signal sel, sel_reg : integer range 0 to 2**DECODE_BITS-1; + +begin + +-- +-- unused and input pins tri state +-- + l <= (others => 'Z'); + r <= (others => 'Z'); + t <= (others => 'Z'); + b <= (others => 'Z'); + + assert SLAVE_CNT <= 2**DECODE_BITS report "Wrong constant in scio"; + + sel <= to_integer(unsigned(sc_io_out.address(SLAVE_ADDR_BITS+DECODE_BITS-1 downto SLAVE_ADDR_BITS))); + + -- What happens when sel_reg > SLAVE_CNT-1?? + 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 + -- + gsl: for i in 0 to SLAVE_CNT-1 generate + + sc_rd(i) <= sc_io_out.rd when i=sel else '0'; + sc_wr(i) <= sc_io_out.wr when i=sel else '0'; + + end generate; + + -- + -- Register read mux selector + -- + process(clk, reset) + begin + if (reset='1') then + sel_reg <= 0; + elsif rising_edge(clk) then + if sc_io_out.rd='1' then + sel_reg <= sel; + end if; + end if; + end process; + + cmp_sys: entity work.sc_sys generic map ( + addr_bits => SLAVE_ADDR_BITS, + clk_freq => clk_freq, + cpu_id => cpu_id + ) + port map( + clk => clk, + reset => reset, + + address => sc_io_out.address(SLAVE_ADDR_BITS-1 downto 0), + wr_data => sc_io_out.wr_data, + rd => sc_rd(0), + wr => sc_wr(0), + rd_data => sc_dout(0), + rdy_cnt => sc_rdy_cnt(0), + + irq_in => irq_in, + exc_req => exc_req, + + sync_out => sync_out, + sync_in => sync_in, + + wd => wd + ); + + cmp_ua: entity work.sc_uart generic map ( + addr_bits => SLAVE_ADDR_BITS, + clk_freq => clk_freq, + baud_rate => 115200, + txf_depth => 2, + txf_thres => 1, + rxf_depth => 2, + rxf_thres => 1 + ) + port map( + clk => clk, + reset => reset, + + address => sc_io_out.address(SLAVE_ADDR_BITS-1 downto 0), + wr_data => sc_io_out.wr_data, + rd => sc_rd(1), + wr => sc_wr(1), + rd_data => sc_dout(1), + rdy_cnt => sc_rdy_cnt(1), + + txd => txd, + rxd => rxd, + ncts => '0', + nrts => nrts + ); + +end rtl; Index: simpcon/trunk/vhdl/sc_pack.vhd =================================================================== --- simpcon/trunk/vhdl/sc_pack.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc_pack.vhd (revision 26) @@ -0,0 +1,45 @@ +-- +-- sc_pack.vhd +-- +-- Package for SimpCon defines +-- +-- Author: Martin Schoeberl (martin@jopdesign.com) +-- +-- +-- 2007-03-16 first version +-- +-- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package sc_pack is + + constant MEM_ADDR_SIZE : integer := 21; + constant IO_ADDR_SIZE : integer := 7; + constant RDY_CNT_SIZE : integer := 2; + + type sc_mem_out_type is record + address : std_logic_vector(MEM_ADDR_SIZE-1 downto 0); + wr_data : std_logic_vector(31 downto 0); + rd : std_logic; + wr : std_logic; + end record; + + type sc_io_out_type is record + address : std_logic_vector(IO_ADDR_SIZE-1 downto 0); + wr_data : std_logic_vector(31 downto 0); + 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; Index: simpcon/trunk/vhdl/sc_cnt.vhd =================================================================== --- simpcon/trunk/vhdl/sc_cnt.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc_cnt.vhd (revision 26) @@ -0,0 +1,235 @@ +-- +-- sc_cnt.vhd +-- +-- counter, interrrupt handling and watchdog bit +-- +-- Author: Martin Schoeberl martin@good-ear.com +-- +-- address map: +-- +-- 0 read clk counter, write irq ena +-- 1 read 1 MHz counter, write timer val (us) + irq ack +-- 2 write generates sw-int (for yield()) +-- 3 write wd port +-- 4 write generates SW exception, read exception reason +-- +-- todo: +-- +-- +-- 2003-07-05 new IO standard +-- 2003-08-15 us counter, irq added +-- 2005-11-30 change interface to SimpCon +-- 2006-01-11 added exception +-- 2007-03-17 changed interrupts to records +-- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.jop_types.all; + +entity sc_cnt 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); + +-- +-- Interrupts from IO devices +-- + irq_in : out irq_in_type; + exc_req : in exception_type; + + wd : out std_logic +); +end sc_cnt ; + +architecture rtl of sc_cnt is + + signal clock_cnt : std_logic_vector(31 downto 0); + signal pre_scale : std_logic_vector(7 downto 0); + signal us_cnt : std_logic_vector(31 downto 0); + + constant div_val : integer := clk_freq/1000000-1; + + signal timer_int : std_logic; + signal yield_int : std_logic; + signal int_ack : std_logic; + + signal timer : std_logic; + signal yield : std_logic; + + signal irq_cnt : std_logic_vector(31 downto 0); + signal timer_equ : std_logic; + signal timer_dly : std_logic; + + signal exc_type : std_logic_vector(7 downto 0); + +begin + + rdy_cnt <= "00"; -- no wait states +-- +-- read cnt values +-- +process(clk, reset) +begin + + if (reset='1') then + rd_data <= (others => '0'); + elsif rising_edge(clk) then + + if rd='1' then + case address(2 downto 0) is + when "000" => + rd_data <= clock_cnt; + when "001" => + rd_data <= us_cnt; + when others => + rd_data(7 downto 0) <= exc_type; + rd_data(31 downto 8) <= (others => '0'); + end case; + end if; + end if; + +end process; + +-- +-- compare timer value and us counter +-- and generate single shot +-- +process(us_cnt, irq_cnt) begin + timer_equ <= '0'; + if us_cnt = irq_cnt then + timer_equ <= '1'; + end if; +end process; + +process(clk, reset, timer_equ) begin + if (reset='1') then + timer_dly <= '0'; + elsif rising_edge(clk) then + timer_dly <= timer_equ; + end if; +end process; + + timer_int <= timer_equ and not timer_dly; + +-- +-- int processing from timer and yield request +-- +process(clk, reset, timer_int, yield_int) begin + + if (reset='1') then + timer <= '0'; + yield <= '0'; + elsif rising_edge(clk) then + if int_ack='1' then + timer <= '0'; + yield <= '0'; + else + if timer_int='1' then + timer <= '1'; + end if; + if yield_int='1' then + yield <= '1'; + end if; + end if; + end if; + +end process; + + irq_in.irq <= timer or yield; + + +-- +-- counters +-- pre_scale is 8 bit => fmax = 255 MHz +-- +process(clk, reset) begin + + if (reset='1') then + + clock_cnt <= (others => '0'); + us_cnt <= (others => '0'); + pre_scale <= std_logic_vector(to_unsigned(div_val, pre_scale'length)); + + elsif rising_edge(clk) then + + clock_cnt <= std_logic_vector(unsigned(clock_cnt) + 1); + pre_scale <= std_logic_vector(unsigned(pre_scale) - 1); + if pre_scale = "00000000" then + pre_scale <= std_logic_vector(to_unsigned(div_val, pre_scale'length)); + us_cnt <= std_logic_vector(unsigned(us_cnt) + 1); + end if; + + end if; +end process; + +-- +-- io write processing and exception processing +-- +process(clk, reset) + +begin + if (reset='1') then + + irq_in.irq_ena <= '0'; + irq_cnt <= (others => '0'); + int_ack <= '0'; + wd <= '0'; + + exc_type <= (others => '0'); + irq_in.exc_int <= '0'; + + elsif rising_edge(clk) then + + int_ack <= '0'; + yield_int <= '0'; + + irq_in.exc_int <= '0'; + + if exc_req.spov='1' then + 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 + when "000" => + irq_in.irq_ena <= wr_data(0); + when "001" => + irq_cnt <= wr_data; + int_ack <= '1'; + when "010" => + yield_int <= '1'; + when "011" => + wd <= wr_data(0); + when others => + exc_type <= wr_data(7 downto 0); + irq_in.exc_int <= '1'; + end case; + end if; + + end if; +end process; + +end rtl; Index: simpcon/trunk/vhdl/sc_lego.vhd =================================================================== --- simpcon/trunk/vhdl/sc_lego.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc_lego.vhd (revision 26) @@ -0,0 +1,444 @@ +-- +-- sc_lego.vhd +-- +-- 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: +-- see read and write processes +-- +-- +-- 2005-12-22 adapted for SimpCon interface +-- 2007-03-13 extended for Lego PCB +-- +-- todo: +-- +-- + + +-- +-- lego io +-- + +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 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); + + -- speaker + + speaker : out std_logic; + + -- motor stuff + + 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; + + 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; + + m2en : out std_logic; + m2dir : out std_logic; + m2break : out std_logic; + + -- 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; + + mic1do : out std_logic; + mic1 : in std_logic; + + + -- pld + pld_strobe : out std_logic; + pld_data : inout std_logic; + pld_clk : out std_logic + + ); +end sc_lego; + +architecture rtl of sc_lego is + -- settings for components + constant adc_width : integer := 9; + + -- 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; + + + constant audio_input_width : integer := 8; + + + -- pld + + signal pld_out_pins : FORWARDED_PINS; + signal pld_in_pins : FORWARDED_PINS; + + -- 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); + + -- motors + + signal motor0_state: lego_motor_state; + signal motor0_duty_cycle: unsigned(duty_cycle_width-1 downto 0); + signal motor0_measure: std_logic; + + 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; + + 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; + + signal motor1_buf_bemf: std_logic_vector(motor_dout_width*2-1 downto 0); + + -- microphone + + 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 + +-- +-- The registered MUX is all we need for a SimpCon read. +-- The read data is stored in registered rd_data. +-- + read: process(clk, reset) + begin + + if (reset='1') then + rd_data <= (others => '0'); + elsif rising_edge(clk) then + + 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; + + +-- +-- SimpCon write is very simple +-- + write: process(clk, reset) + + begin + + if (reset='1') then + pld_out_pins <= (others => '0'); + + motor0_state <= LEGO_MOTOR_STATE_OFF; + motor0_duty_cycle <= (others => '0'); + motor0_measure <= '0'; + + motor1_state <= LEGO_MOTOR_STATE_OFF; + motor1_duty_cycle <= (others => '0'); + motor1_measure <= '0'; + + motor2_state <= LEGO_MOTOR_STATE_OFF; + motor2_duty_cycle <= (others => '0'); + motor2_measure <= '0'; + + elsif rising_edge(clk) then + + if wr='1' then + + 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; + + end if; + + 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, + dout => sensor0_dout, + sp => s0pi, + sdi => s0di, + sdo => s0do); + + 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); + + 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; Index: simpcon/trunk/vhdl/sc_fpu.vhd =================================================================== --- simpcon/trunk/vhdl/sc_fpu.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc_fpu.vhd (revision 26) @@ -0,0 +1,148 @@ +-- This is the SimpCon interface to the FPU +-- + +Library IEEE; +use IEEE.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; + +entity sc_fpu is +generic (ADDR_WIDTH : integer); + +port ( + clk_i : in std_logic; + reset_i : in std_logic; + +-- SimpCon interface + + address_i : in std_logic_vector(ADDR_WIDTH-1 downto 0); + wr_data_i : in std_logic_vector(31 downto 0); + rd_i, wr_i : in std_logic; + rd_data_o : out std_logic_vector(31 downto 0); + rdy_cnt_o : out unsigned(1 downto 0) + +); +end sc_fpu; + +architecture rtl of sc_fpu is + + component fpu + port ( + clk_i : in std_logic; + opa_i : in std_logic_vector(31 downto 0); + opb_i : in std_logic_vector(31 downto 0); + fpu_op_i : in std_logic_vector(2 downto 0); + rmode_i : in std_logic_vector(1 downto 0); + + output_o : out std_logic_vector(31 downto 0); + ine_o : out std_logic; + overflow_o : out std_logic; + underflow_o : out std_logic; + div_zero_o : out std_logic; + inf_o : out std_logic; + zero_o : out std_logic; + qnan_o : out std_logic; + snan_o : out std_logic; + + start_i : in std_logic; + ready_o : out std_logic + ); + end component; + + signal opa_i, opb_i : std_logic_vector(31 downto 0); + signal fpu_op_i : std_logic_vector(2 downto 0); + signal rmode_i : std_logic_vector(1 downto 0); + signal output_o : std_logic_vector(31 downto 0); + signal start_i, ready_o : std_logic ; + --signal ine_o, overflow_o, underflow_o, div_zero_o, inf_o, zero_o, qnan_o, snan_o: std_logic; + +begin + + + -- instantiate the fpu + i_fpu: fpu port map ( + clk_i => clk_i, + opa_i => opa_i, + opb_i => opb_i, + fpu_op_i => fpu_op_i, + rmode_i => rmode_i, + output_o => output_o, + ine_o => open, + overflow_o => open, + underflow_o => open, + div_zero_o => open, + inf_o => open, + zero_o => open, + qnan_o => open, + snan_o => open, + start_i => start_i, + ready_o => ready_o); + +rmode_i <= "00"; -- default rounding mode= round-to-nearest-even + +-- master reads from FPU +process(clk_i, reset_i) +begin + + if (reset_i='1') then +-- 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; + end if; + +end process; + +-- set rdy_cnt +process(clk_i) +begin + if (reset_i='1') then + rdy_cnt_o <= "11"; + elsif rising_edge(clk_i) then + if start_i='1' then + rdy_cnt_o <= "11"; + elsif ready_o = '1' then + rdy_cnt_o <= "00"; + rd_data_o <= output_o; + end if; + end if; +end process; + + +-- master writes to FPU +process(clk_i, reset_i) + +begin + + if (reset_i='1') then + 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 + opa_i <= wr_data_i; + elsif address_i="0001" then + 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; + + end if; + +end process; + + +end rtl; Index: simpcon/trunk/vhdl/sc_uart_tal.vhd =================================================================== --- simpcon/trunk/vhdl/sc_uart_tal.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc_uart_tal.vhd (revision 26) @@ -0,0 +1,404 @@ +-- +-- sc_uart_tal.vhd +-- +-- 8-N-1 serial interface +-- conf_reg: baud_rate and 2400, HW hs on/off, DTR +-- default: 101 => baud_rate, no HW hs, DTR on +-- +-- wr, rd should be one cycle long => trde, rdrf goes 0 one cycle later +-- +-- Author: Martin Schoeberl martin@jopdesign.com +-- +-- +-- resources on ACEX1K30-3 +-- +-- 100 LCs, max 90 MHz +-- +-- resetting rts with fifo_full-1 works with C program on pc +-- but not with javax.comm: sends some more bytes after deassert +-- of rts (16 byte blocks regardless of rts). +-- Try to stop with half full fifo. +-- +-- todo: +-- +-- +-- 2000-12-02 first working version +-- 2002-01-06 changed tdr and rdr to fifos. +-- 2002-05-15 changed clkdiv calculation +-- 2002-11-01 don't wait if read fifo is full, just drop the byte +-- 2002-11-03 use threshold in fifo to reset rts +-- don't send if cts is '0' +-- 2002-11-08 rx fifo to 20 characters and stop after 4 +-- 2003-07-05 new IO standard, change cts/rts to neg logic +-- 2003-09-19 sync ncts in! +-- 2004-03-23 two stop bits +-- 2004-04-23 Version for TAL +-- 2004-04-26 DTR is inverted conf_reg(0) => '1' means set DTR! +-- 2005-02-28 Changed default conf_reg to no hand shake (ignore ncts) +-- 2005-12-27 change interface to SimpCon +-- 2006-08-13 use 3 FFs for the rxd input at clk +-- + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity sc_uart_tal is + +generic (addr_bits : integer; + clk_freq : integer; + baud_rate : integer; + txf_depth : integer; txf_thres : integer; + rxf_depth : integer; rxf_thres : 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); + + txd : out std_logic; + rxd : in std_logic; + ncts : in std_logic; + nrts : out std_logic; + dtr : out std_logic +); +end sc_uart_tal; + +architecture rtl of sc_uart_tal is + +component fifo is + +generic (width : integer; depth : integer; thres : integer); +port ( + clk : in std_logic; + reset : in std_logic; + + din : in std_logic_vector(width-1 downto 0); + dout : out std_logic_vector(width-1 downto 0); + + rd : in std_logic; + wr : in std_logic; + + empty : out std_logic; + full : out std_logic; + half : out std_logic +); +end component; + +-- +-- signals for uart connection +-- + signal ua_dout : std_logic_vector(7 downto 0); + signal ua_wr, tdre : std_logic; + signal ua_rd, rdrf : std_logic; + + signal conf_reg : std_logic_vector(2 downto 0); + + type uart_tx_state_type is (s0, s1); + signal uart_tx_state : uart_tx_state_type; + + signal tf_dout : std_logic_vector(7 downto 0); -- fifo out + signal tf_rd : std_logic; + signal tf_empty : std_logic; + signal tf_full : std_logic; + signal tf_half : std_logic; + + signal ncts_buf : std_logic_vector(2 downto 0); -- sync in + signal ncts_in : std_logic; + + signal tsr : std_logic_vector(9 downto 0); -- tx shift register + + signal tx_clk : std_logic; + + + type uart_rx_state_type is (s0, s1, s2); + signal uart_rx_state : uart_rx_state_type; + + signal rf_wr : std_logic; + signal rf_empty : std_logic; + signal rf_full : std_logic; + signal rf_half : std_logic; + + signal rxd_reg : std_logic_vector(2 downto 0); + signal rx_buf : std_logic_vector(2 downto 0); -- sync in, filter + signal rx_d : std_logic; -- rx serial data + + signal rsr : std_logic_vector(9 downto 0); -- rx shift register + + signal rx_clk : std_logic; + signal rx_clk_ena : std_logic; + + constant clk16_fast_cnt : integer := (clk_freq/baud_rate+8)/16-1; + constant clk16_slow_cnt : integer := (clk_freq/2400+8)/16-1; + + signal clk16_cnt : integer range 0 to clk16_slow_cnt; + + +begin + + rdy_cnt <= "00"; -- no wait states + rd_data(31 downto 8) <= std_logic_vector(to_unsigned(0, 24)); +-- +-- The registered MUX is all we need for a SimpCon read. +-- The read data is stored in registered rd_data. +-- +process(clk, reset) +begin + + if (reset='1') then + rd_data(7 downto 0) <= (others => '0'); + elsif rising_edge(clk) then + + ua_rd <= '0'; + if rd='1' then + -- that's our very simple address decoder + if address(0)='0' then + rd_data(7 downto 0) <= "000000" & rdrf & tdre; + else + rd_data(7 downto 0) <= ua_dout; + ua_rd <= rd; + end if; + end if; + end if; + +end process; + + -- write is on address offest 1 + ua_wr <= wr and address(0); + +-- +-- SimpCon write is very simple +-- +process(clk, reset) + +begin + + if (reset='1') then + conf_reg <= "101"; + elsif rising_edge(clk) then + -- config register is at offset 0 + if wr='1' and address(0)='0' then + conf_reg <= wr_data(2 downto 0); + end if; + + if conf_reg(2)='1' then + clk16_cnt <= clk16_fast_cnt; + else + clk16_cnt <= clk16_slow_cnt; + end if; + end if; +end process; + + dtr <= not conf_reg(0); + +-- +-- serial clock +-- +process(clk, reset) + + variable clk16 : integer range 0 to clk16_slow_cnt; + variable clktx : unsigned(3 downto 0); + variable clkrx : unsigned(3 downto 0); + +begin + if (reset='1') then + clk16 := 0; + clktx := "0000"; + clkrx := "0000"; + tx_clk <= '0'; + rx_clk <= '0'; + rx_buf <= "111"; + + elsif rising_edge(clk) then + + rxd_reg(0) <= rxd; -- to avoid setup timing error in Quartus + rxd_reg(1) <= rxd_reg(0); + rxd_reg(2) <= rxd_reg(1); + + if (clk16=clk16_cnt) then -- 16 x serial clock + clk16 := 0; +-- +-- tx clock +-- + clktx := clktx + 1; + if (clktx="0000") then + tx_clk <= '1'; + else + tx_clk <= '0'; + end if; +-- +-- rx clock +-- + if (rx_clk_ena='1') then + clkrx := clkrx + 1; + if (clkrx="1000") then + rx_clk <= '1'; + else + rx_clk <= '0'; + end if; + else + clkrx := "0000"; + end if; +-- +-- sync in filter buffer +-- + rx_buf(0) <= rxd_reg(2); + rx_buf(2 downto 1) <= rx_buf(1 downto 0); + else + clk16 := clk16 + 1; + tx_clk <= '0'; + rx_clk <= '0'; + end if; + + + end if; + +end process; + +-- +-- transmit fifo +-- + cmp_tf: fifo generic map (8, txf_depth, txf_thres) + port map (clk, reset, wr_data(7 downto 0), tf_dout, tf_rd, ua_wr, tf_empty, tf_full, tf_half); + +-- +-- state machine for actual shift out +-- +process(clk, reset) + + variable i : integer range 0 to 11; + +begin + + if (reset='1') then + uart_tx_state <= s0; + tsr <= "1111111111"; + tf_rd <= '0'; + ncts_buf <= "111"; + ncts_in <= '1'; + + elsif rising_edge(clk) then + + ncts_buf(0) <= ncts; + ncts_buf(2 downto 1) <= ncts_buf(1 downto 0); + if conf_reg(1)='1' then + ncts_in <= ncts_buf(2); + else + ncts_in <= '0'; + end if; + + case uart_tx_state is + + when s0 => + i := 0; + if (tf_empty='0' and ncts_in='0') then + uart_tx_state <= s1; + tsr <= tf_dout & '0' & '1'; + tf_rd <= '1'; + end if; + + when s1 => + tf_rd <= '0'; + if (tx_clk='1') then + tsr(9) <= '1'; + tsr(8 downto 0) <= tsr(9 downto 1); + i := i+1; + if (i=11) then -- two stop bits + uart_tx_state <= s0; + end if; + end if; + + end case; + end if; + +end process; + + txd <= tsr(0); + tdre <= not tf_full; + + +-- +-- receive fifo +-- + cmp_rf: fifo generic map (8, rxf_depth, rxf_thres) + port map (clk, reset, rsr(8 downto 1), ua_dout, ua_rd, rf_wr, rf_empty, rf_full, rf_half); + + rdrf <= not rf_empty; + nrts <= rf_half; -- glitches even on empty fifo! + +-- +-- filter rxd +-- + with rx_buf 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; + +-- +-- state machine for actual shift in +-- +process(clk, reset) + + variable i : integer range 0 to 10; + +begin + + if (reset='1') then + uart_rx_state <= s0; + rsr <= "0000000000"; + rf_wr <= '0'; + rx_clk_ena <= '0'; + + elsif rising_edge(clk) then + + case uart_rx_state is + + + when s0 => + i := 0; + rf_wr <= '0'; + if (rx_d='0') then + rx_clk_ena <= '1'; + uart_rx_state <= s1; + else + rx_clk_ena <= '0'; + end if; + + when s1 => + if (rx_clk='1') then + rsr(9) <= rx_d; + rsr(8 downto 0) <= rsr(9 downto 1); + i := i+1; + if (i=10) then + uart_rx_state <= s2; + end if; + end if; + + when s2 => + rx_clk_ena <= '0'; + if rsr(0)='0' and rsr(9)='1' then + if rf_full='0' then -- if full just drop it + rf_wr <= '1'; + end if; + end if; + uart_rx_state <= s0; + + end case; + end if; + +end process; + +end rtl; Index: simpcon/trunk/vhdl/sc_uart.vhd =================================================================== --- simpcon/trunk/vhdl/sc_uart.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc_uart.vhd (revision 26) @@ -0,0 +1,362 @@ +-- +-- sc_uart.vhd +-- +-- 8-N-1 serial interface +-- +-- wr, rd should be one cycle long => trde, rdrf goes 0 one cycle later +-- +-- Author: Martin Schoeberl martin@jopdesign.com +-- +-- +-- resources on ACEX1K30-3 +-- +-- 100 LCs, max 90 MHz +-- +-- resetting rts with fifo_full-1 works with C program on pc +-- but not with javax.comm: sends some more bytes after deassert +-- of rts (16 byte blocks regardless of rts). +-- Try to stop with half full fifo. +-- +-- todo: +-- +-- +-- 2000-12-02 first working version +-- 2002-01-06 changed tdr and rdr to fifos. +-- 2002-05-15 changed clkdiv calculation +-- 2002-11-01 don't wait if read fifo is full, just drop the byte +-- 2002-11-03 use threshold in fifo to reset rts +-- don't send if cts is '0' +-- 2002-11-08 rx fifo to 20 characters and stop after 4 +-- 2003-07-05 new IO standard, change cts/rts to neg logic +-- 2003-09-19 sync ncts in! +-- 2004-03-23 two stop bits +-- 2005-11-30 change interface to SimpCon +-- 2006-08-07 rxd input register with clk to avoid Quartus tsu violation +-- 2006-08-13 use 3 FFs for the rxd input at clk +-- + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity sc_uart is + +generic (addr_bits : integer; + clk_freq : integer; + baud_rate : integer; + txf_depth : integer; txf_thres : integer; + rxf_depth : integer; rxf_thres : 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); + + txd : out std_logic; + rxd : in std_logic; + ncts : in std_logic; + nrts : out std_logic +); +end sc_uart; + +architecture rtl of sc_uart is + +component fifo is + +generic (width : integer; depth : integer; thres : integer); +port ( + clk : in std_logic; + reset : in std_logic; + + din : in std_logic_vector(width-1 downto 0); + dout : out std_logic_vector(width-1 downto 0); + + rd : in std_logic; + wr : in std_logic; + + empty : out std_logic; + full : out std_logic; + half : out std_logic +); +end component; + +-- +-- signals for uart connection +-- + signal ua_dout : std_logic_vector(7 downto 0); + signal ua_wr, tdre : std_logic; + signal ua_rd, rdrf : std_logic; + + type uart_tx_state_type is (s0, s1); + signal uart_tx_state : uart_tx_state_type; + + signal tf_dout : std_logic_vector(7 downto 0); -- fifo out + signal tf_rd : std_logic; + signal tf_empty : std_logic; + signal tf_full : std_logic; + signal tf_half : std_logic; + + signal ncts_buf : std_logic_vector(2 downto 0); -- sync in + + signal tsr : std_logic_vector(9 downto 0); -- tx shift register + + signal tx_clk : std_logic; + + + type uart_rx_state_type is (s0, s1, s2); + signal uart_rx_state : uart_rx_state_type; + + signal rf_wr : std_logic; + signal rf_empty : std_logic; + signal rf_full : std_logic; + signal rf_half : std_logic; + + signal rxd_reg : std_logic_vector(2 downto 0); + signal rx_buf : std_logic_vector(2 downto 0); -- sync in, filter + signal rx_d : std_logic; -- rx serial data + + signal rsr : std_logic_vector(9 downto 0); -- rx shift register + + signal rx_clk : std_logic; + signal rx_clk_ena : std_logic; + + constant clk16_cnt : integer := (clk_freq/baud_rate+8)/16-1; + + +begin + + rdy_cnt <= "00"; -- no wait states + rd_data(31 downto 8) <= std_logic_vector(to_unsigned(0, 24)); +-- +-- The registered MUX is all we need for a SimpCon read. +-- The read data is stored in registered rd_data. +-- +process(clk, reset) +begin + + if (reset='1') then + rd_data(7 downto 0) <= (others => '0'); + elsif rising_edge(clk) then + + ua_rd <= '0'; + if rd='1' then + -- that's our very simple address decoder + if address(0)='0' then + rd_data(7 downto 0) <= "000000" & rdrf & tdre; + else + rd_data(7 downto 0) <= ua_dout; + ua_rd <= rd; + end if; + end if; + end if; + +end process; + + -- write is on address offest 1 + ua_wr <= wr and address(0); + +-- +-- serial clock +-- +process(clk, reset) + + variable clk16 : integer range 0 to clk16_cnt; + variable clktx : unsigned(3 downto 0); + variable clkrx : unsigned(3 downto 0); + +begin + if (reset='1') then + clk16 := 0; + clktx := "0000"; + clkrx := "0000"; + tx_clk <= '0'; + rx_clk <= '0'; + rx_buf <= "111"; + + elsif rising_edge(clk) then + + rxd_reg(0) <= rxd; -- to avoid setup timing error in Quartus + rxd_reg(1) <= rxd_reg(0); + rxd_reg(2) <= rxd_reg(1); + + if (clk16=clk16_cnt) then -- 16 x serial clock + clk16 := 0; +-- +-- tx clock +-- + clktx := clktx + 1; + if (clktx="0000") then + tx_clk <= '1'; + else + tx_clk <= '0'; + end if; +-- +-- rx clock +-- + if (rx_clk_ena='1') then + clkrx := clkrx + 1; + if (clkrx="1000") then + rx_clk <= '1'; + else + rx_clk <= '0'; + end if; + else + clkrx := "0000"; + end if; +-- +-- sync in filter buffer +-- + rx_buf(0) <= rxd_reg(2); + rx_buf(2 downto 1) <= rx_buf(1 downto 0); + else + clk16 := clk16 + 1; + tx_clk <= '0'; + rx_clk <= '0'; + end if; + + + end if; + +end process; + +-- +-- transmit fifo +-- + cmp_tf: fifo generic map (8, txf_depth, txf_thres) + port map (clk, reset, wr_data(7 downto 0), tf_dout, tf_rd, ua_wr, tf_empty, tf_full, tf_half); + +-- +-- state machine for actual shift out +-- +process(clk, reset) + + variable i : integer range 0 to 11; + +begin + + if (reset='1') then + uart_tx_state <= s0; + tsr <= "1111111111"; + tf_rd <= '0'; + ncts_buf <= "111"; + + elsif rising_edge(clk) then + + ncts_buf(0) <= ncts; + ncts_buf(2 downto 1) <= ncts_buf(1 downto 0); + + case uart_tx_state is + + when s0 => + i := 0; + if (tf_empty='0' and ncts_buf(2)='0') then + uart_tx_state <= s1; + tsr <= tf_dout & '0' & '1'; + tf_rd <= '1'; + end if; + + when s1 => + tf_rd <= '0'; + if (tx_clk='1') then + tsr(9) <= '1'; + tsr(8 downto 0) <= tsr(9 downto 1); + i := i+1; + if (i=11) then -- two stop bits + uart_tx_state <= s0; + end if; + end if; + + end case; + end if; + +end process; + + txd <= tsr(0); + tdre <= not tf_full; + + +-- +-- receive fifo +-- + cmp_rf: fifo generic map (8, rxf_depth, rxf_thres) + port map (clk, reset, rsr(8 downto 1), ua_dout, ua_rd, rf_wr, rf_empty, rf_full, rf_half); + + rdrf <= not rf_empty; + nrts <= rf_half; -- glitches even on empty fifo! + +-- +-- filter rxd +-- + with rx_buf 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; + +-- +-- state machine for actual shift in +-- +process(clk, reset) + + variable i : integer range 0 to 10; + +begin + + if (reset='1') then + uart_rx_state <= s0; + rsr <= "0000000000"; + rf_wr <= '0'; + rx_clk_ena <= '0'; + + elsif rising_edge(clk) then + + case uart_rx_state is + + + when s0 => + i := 0; + rf_wr <= '0'; + if (rx_d='0') then + rx_clk_ena <= '1'; + uart_rx_state <= s1; + else + rx_clk_ena <= '0'; + end if; + + when s1 => + if (rx_clk='1') then + rsr(9) <= rx_d; + rsr(8 downto 0) <= rsr(9 downto 1); + i := i+1; + if (i=10) then + uart_rx_state <= s2; + end if; + end if; + + when s2 => + rx_clk_ena <= '0'; + if rsr(0)='0' and rsr(9)='1' then + if rf_full='0' then -- if full just drop it + rf_wr <= '1'; + end if; + end if; + uart_rx_state <= s0; + + end case; + end if; + +end process; + +end rtl; Index: simpcon/trunk/vhdl/sigdel.vhd =================================================================== --- simpcon/trunk/vhdl/sigdel.vhd (nonexistent) +++ simpcon/trunk/vhdl/sigdel.vhd (revision 26) @@ -0,0 +1,146 @@ +-- +-- sigdel.vhd +-- +-- sigma delta AD converter +-- +-- without external comperator: +-- input threshhold of Acex is used as comperator +-- (not very exact but only 3 external components) +-- +-- +-- 100k +-- ___ +-- sdo o--|___|--+ +-- | +-- 100k | +-- ___ | +-- uin o--|___|--o----------o sdi +-- | +-- --- +-- --- 100n +-- | +-- | +-- --- +-- - +-- +-- +-- Author: Martin Schoeberl martin@jopdesign.com +-- +-- +-- resources on ACEX1K30-3 +-- +-- xx LCs, max xx MHz +-- +-- +-- todo: +-- use clk_freq, make it configurable +-- use a 'real' LP +-- +-- +-- 2002-02-23 first working version +-- 2002-08-08 free running 16 bit counter -> 16 bit ADC +-- 2003-09-23 new IO standard +-- 2005-12-28 just a simple data port +-- + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity sigdel is + +generic (clk_freq : integer); +port ( + clk : in std_logic; + reset : in std_logic; + dout : out std_logic_vector(15 downto 0); + + sdi : in std_logic; + sdo : out std_logic +); +end sigdel ; + +architecture rtl of sigdel is + + signal clksd : unsigned(4 downto 0); + + signal clkint : unsigned(15 downto 0); + signal val : unsigned(15 downto 0); + signal sd_dout : std_logic_vector(15 downto 0); + + signal rx_d : std_logic; + signal serdata : std_logic; + + signal spike : std_logic_vector(2 downto 0); -- sync in, filter + +begin + + sdo <= serdata; + dout <= sd_dout; + +-- +-- sigma delta converter +-- +process(clk, reset) + +begin + if (reset='1') then + clksd <= "00000"; + spike <= "000"; + sd_dout <= (others => '0'); + val <= (others => '0'); + clkint <= (others => '0'); + serdata <= '0'; + + elsif rising_edge(clk) then + + clksd <= clksd+1; + + if clksd="00000" then -- with 20 MHz => 625 kHz + +-- +-- delay +-- + spike(0) <= sdi; + spike(2 downto 1) <= spike(1 downto 0); + serdata <= rx_d; -- no inverter, using an invert. comperator +-- serdata <= not rx_d; -- without comperator + +-- +-- integrate +-- + + if serdata='0' then -- 'invert' value + val <= val+1; + end if; + + if clkint=0 then -- some time... (9.5 Hz) + sd_dout <= std_logic_vector(val); + val <= (others => '0'); + 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; Index: simpcon/trunk/vhdl/sc_usb.vhd =================================================================== --- simpcon/trunk/vhdl/sc_usb.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc_usb.vhd (revision 26) @@ -0,0 +1,266 @@ +-- +-- sc_usb.vhd +-- +-- Interface to FTDI FT2232C parallel port B +-- +-- Author: Martin Schoeberl martin@jopdesign.com +-- +-- +-- resources on Cyclone +-- +-- xx LCs, max xx MHz +-- +-- +-- 2005-08-23 first version +-- +-- todo: +-- +-- + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.jop_types.all; + +entity sc_usb 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); + +-- FTDI 2232 connection + + data : inout std_logic_vector(7 downto 0); + nrxf : in std_logic; + ntxe : in std_logic; + nrd : out std_logic; + ft_wr : out std_logic; + nsi : out std_logic +); +end sc_usb; + +architecture rtl of sc_usb is + + signal usb_out : std_logic_vector(7 downto 0); + signal usb_in : std_logic_vector(7 downto 0); + + signal read_ack : std_logic; + signal fifo_wr : std_logic; + +-- +-- + constant WS : integer := (clk_freq/20000000)+1; + signal cnt : integer range 0 to WS; + +-- +-- FIFO signals +-- + signal tf_dout : std_logic_vector(7 downto 0); -- fifo out + signal tf_rd : std_logic; + signal tf_empty : std_logic; + signal tf_full : std_logic; + + signal rf_din : std_logic_vector(7 downto 0); -- fifo input + signal rf_wr : std_logic; + signal rf_empty : std_logic; + signal rf_full : std_logic; + + +-- +-- USB interface signals +-- + type state_type is (idle, inact, rx1, rx2, tx1, tx2); + signal state : state_type; + + signal usb_dout : std_logic_vector(7 downto 0); + signal usb_din : std_logic_vector(7 downto 0); + + signal nrxf_buf : std_logic_vector(1 downto 0); + signal ntxe_buf : std_logic_vector(1 downto 0); + signal rdr, wrr : std_logic_vector(7 downto 0); + signal data_oe : std_logic; + +begin + + rdy_cnt <= "00"; -- no wait states + rd_data(31 downto 8) <= std_logic_vector(to_unsigned(0, 24)); +-- +-- The registered MUX is all we need for a SimpCon read. +-- The read data is stored in registered rd_data. +-- +process(clk, reset) +begin + + if (reset='1') then + rd_data(7 downto 0) <= (others => '0'); + elsif rising_edge(clk) then + + read_ack <= '0'; + if rd='1' then + -- that's our very simple address decoder + if address(0)='0' then + rd_data(7 downto 0) <= "000000" & not rf_empty & not tf_full; + else + rd_data(7 downto 0) <= usb_dout; + read_ack <= rd; + end if; + end if; + end if; + +end process; + + -- write is on address offest 1 + fifo_wr <= wr and address(0); + + -- we don't use the send immediate + nsi <= '1'; + + +-- +-- receive fifo +-- + rxfifo: entity work.fifo generic map ( + width => 8, + depth => 4, + thres => 2 -- we don't care about the half signal + ) port map ( + clk => clk, + reset => reset, + din => rf_din, + dout => usb_dout, + rd => read_ack, + wr => rf_wr, + empty => rf_empty, + full => rf_full, + half => open + ); + +-- +-- transmit fifo +-- + txfifo: entity work.fifo generic map ( + width => 8, + depth => 4, + thres => 2 -- we don't care about the half signal + ) port map ( + clk => clk, + reset => reset, + din => wr_data(7 downto 0), + dout => tf_dout, + rd => tf_rd, + wr => fifo_wr, + empty => tf_empty, + full => tf_full, + half => open + ); + + +-- +-- state machine for the usb bus +-- +process(clk, reset) + +begin + + if (reset='1') then + state <= idle; + nrxf_buf <= "11"; + ntxe_buf <= "11"; + cnt <= WS; + + rdr <= (others => '0'); + wrr <= (others => '0'); + + tf_rd <= '0'; + rf_wr <= '0'; + + nrd <= '1'; + ft_wr <= '0'; + + elsif rising_edge(clk) then + + -- input register + nrxf_buf(0) <= nrxf; + nrxf_buf(1) <= nrxf_buf(0); + ntxe_buf(0) <= ntxe; + ntxe_buf(1) <= ntxe_buf(0); + + case state is + + when idle => + cnt <= WS; + tf_rd <= '0'; + rf_wr <= '0'; + nrd <= '1'; + ft_wr <= '0'; + data_oe <= '0'; + if rf_full='0' and nrxf_buf(1)='0' then + nrd <= '0'; + state <= rx1; + elsif tf_empty='0' and ntxe_buf(1)='0' then + ft_wr <= '1'; + wrr <= tf_dout; + tf_rd <= '1'; + state <= tx1; + end if; + + when inact => + tf_rd <= '0'; + rf_wr <= '0'; + nrd <= '1'; + ft_wr <= '0'; + data_oe <= '0'; + cnt <= cnt-1; + if cnt=0 then + state <= idle; + end if; + + + when rx1 => + cnt <= cnt-1; + if cnt=0 then + state <= rx2; + rdr <= data; + end if; + + when rx2 => + nrd <= '1'; + rf_wr <= '1'; + cnt <= WS; + state <= inact; + + when tx1 => + tf_rd <= '0'; + data_oe <= '1'; + cnt <= cnt-1; + if cnt=0 then + state <= tx2; + ft_wr <= '0'; + end if; + + when tx2 => + data_oe <= '0'; + cnt <= WS; + state <= inact; + + end case; + end if; + +end process; + + data <= wrr when data_oe='1' else (others => 'Z'); + rf_din <= data; + +end rtl; Index: simpcon/trunk/vhdl/sc_mac.vhd =================================================================== --- simpcon/trunk/vhdl/sc_mac.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc_mac.vhd (revision 26) @@ -0,0 +1,222 @@ +-- +-- sc_mac.vhd +-- +-- A simple MAC unit with a SimpCon interface +-- +-- Author: Martin Schoeberl martin@jopdesign.com +-- +-- +-- resources on Cyclone +-- +-- xx LCs, max xx MHz +-- +-- +-- 2006-02-12 first version +-- +-- todo: +-- +-- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +LIBRARY lpm; +USE lpm.lpm_components.all; + +entity mac is + +port ( + clk : in std_logic; + reset : in std_logic; + +-- SimpCon interface + + opa, opb : in std_logic_vector(31 downto 0); + start : in std_logic; + clear : in std_logic; + result : out std_logic_vector(63 downto 0) +); +end mac; + +architecture rtl of mac is + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (63 DOWNTO 0); + + COMPONENT lpm_mult + GENERIC ( + lpm_hint : STRING; + lpm_pipeline : NATURAL; + lpm_representation : STRING; + lpm_type : STRING; + lpm_widtha : NATURAL; + lpm_widthb : NATURAL; + lpm_widthp : NATURAL; + lpm_widths : NATURAL + ); + PORT ( + dataa : IN STD_LOGIC_VECTOR (31 DOWNTO 0); + datab : IN STD_LOGIC_VECTOR (31 DOWNTO 0); + clock : IN STD_LOGIC ; + result : OUT STD_LOGIC_VECTOR (63 DOWNTO 0) + ); + END COMPONENT; + + type state_type is (idle, mul, add); + signal state : state_type; + + signal cnt : unsigned(5 downto 0); + + signal mul_res : unsigned(63 downto 0); + signal acc : unsigned(63 downto 0); + +begin + + + lpm_mult_component : lpm_mult + GENERIC MAP ( + lpm_hint => "MAXIMIZE_SPEED=5", + lpm_pipeline => 16, + lpm_representation => "SIGNED", + lpm_type => "LPM_MULT", + lpm_widtha => 32, + lpm_widthb => 32, + lpm_widthp => 64, + lpm_widths => 1 + ) + PORT MAP ( + dataa => opa, + datab => opb, + clock => clk, + result => sub_wire0 + ); + + mul_res <= unsigned(sub_wire0); + + + +process(clk, reset) + +begin + if reset='1' then + acc <= (others => '0'); + + elsif rising_edge(clk) then + + case state is + + when idle => + if start='1' then + state <= mul; + cnt <= "010010"; -- for shure + end if; + + when mul => + cnt <= cnt-1; + if cnt=0 then + state <= add; + end if; + + when add => + acc <= acc + mul_res; + state <= idle; + + end case; + + if clear='1' then + acc <= (others => '0'); + end if; + + end if; + + result <= std_logic_vector(acc); + +end process; + +end rtl; + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity sc_mac is +generic (addr_bits : integer; scale : integer := 16); + +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) + +); +end sc_mac; + +architecture rtl of sc_mac is + + signal opa, opb : std_logic_vector(31 downto 0); + signal result : std_logic_vector(63 downto 0); + + signal start : std_logic; + signal clear : std_logic; + +begin + + rdy_cnt <= "00"; -- no wait states, we are hopefully fast enough + + cm: entity work.mac + port map( + clk => clk, + reset => reset, + + opa => opa, + opb => opb, + start => start, + clear => clear, + result => result + ); + +-- +-- SimpCon read and write +-- +process(clk, reset) + +begin + + if reset='1' then + rd_data <= (others => '0'); + + elsif rising_edge(clk) then + + start <= '0'; + if wr='1' then + if address(0)='0' then + opa <= wr_data; + else + opb <= wr_data; + start <= '1'; + end if; + end if; + + -- get MAC result scaled by 'scale' and clear the accumulator + clear <= '0'; + if rd='1' then +-- if address(0)='0' then + rd_data <= result(31+scale downto scale); + clear <= '1'; +-- else +-- rd_data <= result(63 downto 32); +-- end if; + end if; + + end if; +end process; + + +end rtl; Index: simpcon/trunk/vhdl/sc2avalon.vhd =================================================================== --- simpcon/trunk/vhdl/sc2avalon.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc2avalon.vhd (revision 26) @@ -0,0 +1,215 @@ +-- +-- sc2avalon.vhd +-- +-- SimpCon to Avalon bridge +-- +-- Author: Martin Schoeberl martin@jopdesign.com +-- +-- 2006-08-10 first version +-- + +Library IEEE; +use IEEE.std_logic_1164.all; +use ieee.numeric_std.all; + +entity sc2avalon is +generic (addr_bits : integer); + +port ( + + clk, reset : in std_logic; + +-- SimpCon interface + + sc_address : in std_logic_vector(addr_bits-1 downto 0); + sc_wr_data : in std_logic_vector(31 downto 0); + sc_rd, sc_wr : in std_logic; + sc_rd_data : out std_logic_vector(31 downto 0); + sc_rdy_cnt : out unsigned(1 downto 0); + +-- Avalon interface + + av_address : out std_logic_vector(addr_bits-1+2 downto 0); + av_writedata : out std_logic_vector(31 downto 0); + av_byteenable : out std_logic_vector(3 downto 0); + av_readdata : in std_logic_vector(31 downto 0); + av_read : out std_logic; + av_write : out std_logic; + av_waitrequest : in std_logic + +); +end sc2avalon; + +architecture rtl of sc2avalon is + + type state_type is (idl, rd, rdw, wr, wrw); + signal state : state_type; + signal next_state : state_type; + + signal reg_addr : std_logic_vector(addr_bits-1 downto 0); + signal reg_wr_data : std_logic_vector(31 downto 0); + signal reg_rd_data : std_logic_vector(31 downto 0); + + signal reg_rd : std_logic; + signal reg_wr : std_logic; + +begin + + av_byteenable <= "1111"; -- we use only 32 bit transfers + av_address(1 downto 0) <= "00"; + + sc_rd_data <= reg_rd_data; + + +-- +-- Register memory address, write data and read data +-- +process(clk, reset) +begin + if reset='1' then + + reg_addr <= (others => '0'); + reg_wr_data <= (others => '0'); + + elsif rising_edge(clk) then + + if sc_rd='1' or sc_wr='1' then + reg_addr <= sc_address; + end if; + if sc_wr='1' then + reg_wr_data <= sc_wr_data; + end if; + + end if; +end process; + + +-- +-- The address MUX slightly violates the Avalon +-- specification. The address changes from the sc_address +-- to the registerd address in the second cycle. However, +-- as both registers contain the same value there should be +-- no real glitch. For synchronous peripherals this is not +-- an issue. For asynchronous peripherals (SRAM) the possible +-- glitch should be short enough to be not seen on the output +-- pins. +-- +process(sc_rd, sc_wr, sc_address, reg_addr) +begin + if sc_rd='1' or sc_wr='1' then + av_address(addr_bits-1+2 downto 2) <= sc_address; + else + av_address(addr_bits-1+2 downto 2) <= reg_addr; + end if; +end process; + +-- Same game for the write data and write/read control +process(sc_wr, sc_wr_data, reg_wr_data) +begin + if sc_wr='1' then + av_writedata <= sc_wr_data; + else + av_writedata <= reg_wr_data; + end if; +end process; + + av_write <= sc_wr or reg_wr; + av_read <= sc_rd or reg_rd; + + + +-- +-- next state logic +-- +-- At the moment we do not support back to back read +-- or write. We don't need it for JOP, right? +-- If needed just copy the idl code to rd and wr. +-- +process(state, sc_rd, sc_wr, av_waitrequest) + +begin + + next_state <= state; + + case state is + + when idl => + if sc_rd='1' then + if av_waitrequest='0' then + next_state <= rd; + else + next_state <= rdw; + end if; + elsif sc_wr='1' then + if av_waitrequest='0' then + next_state <= wr; + else + next_state <= wrw; + end if; + end if; + + when rdw => + if av_waitrequest='0' then + next_state <= rd; + end if; + + when rd => + next_state <= idl; + + when wrw => + if av_waitrequest='0' then + next_state <= wr; + end if; + + when wr => + next_state <= idl; + + + end case; + +end process; + +-- +-- state machine register +-- and output register +-- +process(clk, reset) + +begin + if (reset='1') then + state <= idl; + reg_rd_data <= (others => '0'); + sc_rdy_cnt <= "00"; + reg_rd <= '0'; + reg_wr <= '0'; + + elsif rising_edge(clk) then + + state <= next_state; + sc_rdy_cnt <= "00"; + reg_rd <= '0'; + reg_wr <= '0'; + + case next_state is + + when idl => + + when rdw => + sc_rdy_cnt <= "11"; + reg_rd <= '1'; + + when rd => + reg_rd_data <= av_readdata; + + when wrw => + sc_rdy_cnt <= "11"; + reg_wr <= '1'; + + when wr => + + end case; + + end if; +end process; + +end rtl; Index: simpcon/trunk/vhdl/sc_sigdel.vhd =================================================================== --- simpcon/trunk/vhdl/sc_sigdel.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc_sigdel.vhd (revision 26) @@ -0,0 +1,216 @@ +-- +-- sc_sigdel.vhd +-- +-- A simple sigma-delta ADC and PWM DAC for the SimpCon interface +-- +-- Author: Martin Schoeberl martin@jopdesign.com +-- +-- +-- resources on Cyclone +-- +-- xx LCs, max xx MHz +-- +-- +-- 2006-04-16 first version +-- +-- todo: +-- +-- + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.jop_config.all; + +entity sc_sigdel is +generic (addr_bits : integer; fsamp : 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); + +-- io ports + sdi : in std_logic; -- input of the sigma-delta ADC + sdo : out std_logic; -- output of the sigma-delta ADC + dac : out std_logic -- output of the PWM DAC +); +end sc_sigdel; + +architecture rtl of sc_sigdel is + + -- we use a 10MHz sigma-delta clock + constant SDF : integer := 10000000; + constant SDTICK : integer := (clk_freq+SDF/2)/SDF; + signal clksd : integer range 0 to SDTICK; + constant CNT_MAX : integer := (SDF+fsamp/2)/fsamp; + signal cnt : integer range 0 to CNT_MAX; + signal dac_cnt : integer range 0 to CNT_MAX; + + signal rx_d : std_logic; + signal serdata : std_logic; + signal spike : std_logic_vector(2 downto 0); -- sync in, filter + signal sum : unsigned(15 downto 0); + signal delta : unsigned(15 downto 0); + + signal audio_in : std_logic_vector(15 downto 0); + signal audio_out : std_logic_vector(15 downto 0); + + signal sample_rdy : std_logic; + signal sample_rd : std_logic; + signal sample_wr : std_logic; + +begin + + rdy_cnt <= "00"; -- no wait states + -- we use only 16 bits + -- bit 31 is the ready bit + rd_data(30 downto 16) <= (others => '0'); + +-- +-- The registered MUX is all we need for a SimpCon read. +-- The read data is stored in registered rd_data. +-- +process(clk, reset) +begin + + if (reset='1') then + rd_data(15 downto 0) <= (others => '0'); + rd_data(31) <= '0'; + sample_rd <= '0'; + elsif rising_edge(clk) then + + sample_rd <= '0'; + if rd='1' then + rd_data(15 downto 0) <= audio_in; + rd_data(31) <= sample_rdy; + sample_rd <= '1'; + end if; + end if; + +end process; + + +-- +-- SimpCon write is very simple +-- +process(clk, reset) + +begin + + if (reset='1') then + audio_out <= (others => '0'); + sample_wr <= '0'; + elsif rising_edge(clk) then + sample_wr <= '0'; + if wr='1' then + audio_out <= wr_data(15 downto 0); + sample_wr <= '1'; + end if; + end if; +end process; + + +-- +-- Here we go with the simple sigma-delta converter: +-- +process(clk, reset) + +begin + + if reset='1' then + + spike <= "000"; + clksd <= 0; + cnt <= 0; + sum <= (others => '0'); + sample_rdy <= '0'; + + elsif rising_edge(clk) then + + if clksd=0 then + clksd <= SDTICK-1; + spike(0) <= sdi; + spike(2 downto 1) <= spike(1 downto 0); + sdo <= not rx_d; + serdata <= rx_d; + + if cnt=0 then + cnt <= CNT_MAX-1; + audio_in <= std_logic_vector(sum); + sample_rdy <= '1'; + sum <= (others => '0'); + -- BTW: we miss one sigma-delta sample here... + else + cnt <= cnt-1; + if serdata='1' then + sum <= sum+1; + end if; + end if; + else + clksd <= clksd-1; + end if; + + -- reset ready flag after read + if sample_rd='1' then + sample_rdy <= '0'; + end if; + + end if; + +end process; + +-- +-- filter input (majority voting) +-- + 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; + +-- +-- and here comes the primitive version of the +-- digital delta part - not really delta... +-- it's just a simple PWM... +-- now do it with the main clock... +-- +process(clk, reset) + +begin + if reset='1' then + delta <= (others => '0'); + dac <= '0'; + dac_cnt <= 0; + elsif rising_edge(clk) then + + if dac_cnt=0 then + dac_cnt <= CNT_MAX-1; + delta <= unsigned(audio_out); + else + dac_cnt <= dac_cnt-1; + dac <= '0'; + if delta /= 0 then + delta <= delta-1; + dac <= '1'; + end if; + end if; + + end if; +end process; + +end rtl; Index: simpcon/trunk/vhdl/sc_sram32.vhd =================================================================== --- simpcon/trunk/vhdl/sc_sram32.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc_sram32.vhd (revision 26) @@ -0,0 +1,274 @@ +-- +-- sc_sram32.vhd +-- +-- SimpCon compliant external memory interface +-- for 32-bit SRAM (e.g. Cyclone board, Spartan-3 Starter Kit) +-- +-- Connection between mem_sc and the external memory bus +-- +-- memory mapping +-- +-- 000000-x7ffff external SRAM (w mirror) max. 512 kW (4*4 MBit) +-- +-- RAM: 32 bit word +-- +-- +-- 2005-11-22 first version +-- 2007-03-17 changed SimpCon to records +-- + +Library IEEE; +use IEEE.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.jop_types.all; +use work.sc_pack.all; + +entity sc_mem_if is +generic (ram_ws : integer; addr_bits : integer); + +port ( + + clk, reset : in std_logic; + +-- +-- SimpCon memory interface +-- + sc_mem_out : in sc_mem_out_type; + sc_mem_in : out sc_in_type; + +-- memory interface + + ram_addr : out std_logic_vector(addr_bits-1 downto 0); + ram_dout : out std_logic_vector(31 downto 0); + ram_din : in std_logic_vector(31 downto 0); + ram_dout_en : out std_logic; + ram_ncs : out std_logic; + ram_noe : out std_logic; + ram_nwe : out std_logic + +); +end sc_mem_if; + +architecture rtl of sc_mem_if is + +-- +-- signals for mem interface +-- + type state_type is ( + idl, rd1, rd2, + wr1 + ); + signal state : state_type; + signal next_state : state_type; + + signal nwr_int : std_logic; + signal wait_state : unsigned(3 downto 0); + signal cnt : unsigned(1 downto 0); + + signal dout_ena : std_logic; + signal rd_data_ena : std_logic; + +begin + + assert MEM_ADDR_SIZE>=addr_bits report "Too less address bits"; + ram_dout_en <= dout_ena; + + sc_mem_in.rdy_cnt <= cnt; + +-- +-- Register memory address, write data and read data +-- +process(clk, reset) +begin + if reset='1' then + + ram_addr <= (others => '0'); + ram_dout <= (others => '0'); + sc_mem_in.rd_data <= (others => '0'); + + elsif rising_edge(clk) then + + if sc_mem_out.rd='1' or sc_mem_out.wr='1' then + ram_addr <= sc_mem_out.address(addr_bits-1 downto 0); + end if; + if sc_mem_out.wr='1' then + ram_dout <= sc_mem_out.wr_data; + end if; + if rd_data_ena='1' then + sc_mem_in.rd_data <= ram_din; + end if; + + end if; +end process; + +-- +-- 'delay' nwe 1/2 cycle -> change on falling edge +-- +process(clk, reset) + +begin + if (reset='1') then + ram_nwe <= '1'; + elsif falling_edge(clk) then + ram_nwe <= nwr_int; + end if; + +end process; + + +-- +-- next state logic +-- +process(state, sc_mem_out.rd, sc_mem_out.wr, wait_state) + +begin + + next_state <= state; + + + case state is + + when idl => + if sc_mem_out.rd='1' then + if ram_ws=0 then + -- then we omit state rd1! + next_state <= rd2; + else + next_state <= rd1; + end if; + elsif sc_mem_out.wr='1' then + next_state <= wr1; + end if; + + -- the WS state + when rd1 => + if wait_state=2 then + next_state <= rd2; + end if; + + -- last read state + when rd2 => + next_state <= idl; + -- This should do to give us a pipeline + -- level of 2 for read + if sc_mem_out.rd='1' then + if ram_ws=0 then + -- then we omit state rd1! + next_state <= rd2; + else + next_state <= rd1; + end if; + elsif sc_mem_out.wr='1' then + next_state <= wr1; + end if; + + -- the WS state + when wr1 => +-- TODO: check what happens on ram_ws=0 +-- TODO: do we need a write pipelining? +-- not at the moment, but parhaps later when +-- we write the stack content to main memory + if wait_state=1 then + next_state <= idl; + end if; + + end case; + +end process; + +-- +-- state machine register +-- output register +-- +process(clk, reset) + +begin + if (reset='1') then + state <= idl; + dout_ena <= '0'; + ram_ncs <= '1'; + ram_noe <= '1'; + rd_data_ena <= '0'; + elsif rising_edge(clk) then + + state <= next_state; + dout_ena <= '0'; + ram_ncs <= '1'; + ram_noe <= '1'; + rd_data_ena <= '0'; + + case next_state is + + when idl => + + -- the wait state + when rd1 => + ram_ncs <= '0'; + ram_noe <= '0'; + + -- last read state + when rd2 => + ram_ncs <= '0'; + ram_noe <= '0'; + rd_data_ena <= '1'; + + + -- the WS state + when wr1 => + ram_ncs <= '0'; + dout_ena <= '1'; + + end case; + + end if; +end process; + +-- +-- nwr combinatorial processing +-- for the negativ edge +-- +process(next_state, state) +begin + + nwr_int <= '1'; + if next_state=wr1 then + nwr_int <= '0'; + end if; + +end process; + +-- +-- wait_state processing +-- cs delay, dout enable +-- +process(clk, reset) +begin + if (reset='1') then + wait_state <= (others => '1'); + cnt <= "00"; + elsif rising_edge(clk) then + + wait_state <= wait_state-1; + + cnt <= "11"; + if next_state=idl then + cnt <= "00"; + -- if wait_state<4 then + elsif wait_state(3 downto 2)="00" then + cnt <= wait_state(1 downto 0)-1; + end if; + + if sc_mem_out.rd='1' or sc_mem_out.wr='1' then + wait_state <= to_unsigned(ram_ws+1, 4); + if ram_ws<3 then + cnt <= to_unsigned(ram_ws+1, 2); + else + cnt <= "11"; + end if; + end if; + + end if; +end process; + +end rtl; Index: simpcon/trunk/vhdl/sc_isa.vhd =================================================================== --- simpcon/trunk/vhdl/sc_isa.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc_isa.vhd (revision 26) @@ -0,0 +1,119 @@ +-- +-- sc_isa.vhd +-- +-- ISA bus for ethernet chip +-- +-- Author: Martin Schoeberl martin@jopdesign.com +-- +-- +-- resources on Cyclone +-- +-- xx LCs, max xx MHz +-- +-- +-- 2005-12-28 changed for SimpCon +-- +-- todo: +-- +-- + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity sc_isa is +generic (addr_bits : 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); + +-- ISA bus + + isa_d : inout std_logic_vector(7 downto 0); + isa_a : out std_logic_vector(4 downto 0); + isa_reset : out std_logic; + isa_nior : out std_logic; + isa_niow : out std_logic +); +end sc_isa; + +architecture rtl of sc_isa is + +-- +-- signal for isa data bus +-- + signal isa_data : std_logic_vector(7 downto 0); + signal isa_dir : std_logic; -- direction of isa_d ('1' means driving out) + +begin + + rdy_cnt <= "00"; -- no wait states + +-- +-- The registered MUX is all we need for a SimpCon read. +-- +process(clk, reset) +begin + + if (reset='1') then + rd_data <= (others => '0'); + elsif rising_edge(clk) then + + if rd='1' then + -- no address decoding + rd_data <= std_logic_vector(to_unsigned(0, 24)) & isa_d; + end if; + end if; + +end process; + + +-- +-- SimpCon write is very simple +-- +process(clk, reset) + +begin + + if (reset='1') then + + isa_data <= (others => '0'); + isa_a <= (others => '0'); + isa_reset <= '0'; + isa_nior <= '1'; + isa_niow <= '1'; + isa_dir <= '0'; + + elsif rising_edge(clk) then + + if wr='1' then + if address(0)='0' then + isa_a <= wr_data(4 downto 0); + isa_reset <= wr_data(5); + isa_nior <= not wr_data(6); + isa_niow <= not wr_data(7); + isa_dir <= wr_data(8); + else + isa_data <= wr_data(7 downto 0); + end if; + end if; + + end if; +end process; + +-- +-- isa data bus +-- + isa_d <= isa_data when isa_dir='1' else "ZZZZZZZZ"; + +end rtl; Index: simpcon/trunk/vhdl/fifo.vhd =================================================================== --- simpcon/trunk/vhdl/fifo.vhd (nonexistent) +++ simpcon/trunk/vhdl/fifo.vhd (revision 26) @@ -0,0 +1,158 @@ +-- +-- fifo.vhd +-- +-- simple fifo +-- +-- uses FF and every rd or wr has to 'bubble' through the hole fifo. +-- +-- Author: Martin Schoeberl martin.schoeberl@chello.at +-- +-- +-- resources on ACEX1K +-- +-- (width+2)*depth-1 LCs +-- +-- +-- 2002-01-06 first working version +-- 2002-11-03 a signal for reaching threshold +-- 2005-02-20 change entity order for modelsim vcom +-- + +library ieee; +use ieee.std_logic_1164.all; + +entity fifo_elem is + +generic (width : integer); +port ( + clk : in std_logic; + reset : in std_logic; + + din : in std_logic_vector(width-1 downto 0); + dout : out std_logic_vector(width-1 downto 0); + + rd : in std_logic; + wr : in std_logic; + + rd_prev : out std_logic; + full : out std_logic +); +end fifo_elem; + +architecture rtl of fifo_elem is + + signal buf : std_logic_vector(width-1 downto 0); + signal f : std_logic; + +begin + + dout <= buf; + +process(clk, reset, f) + +begin + + full <= f; + + if (reset='1') then + + buf <= (others => '0'); + f <= '0'; + rd_prev <= '0'; + + elsif rising_edge(clk) then + + rd_prev <= '0'; + if f='0' then + if wr='1' then + rd_prev <= '1'; + buf <= din; + f <= '1'; + end if; + else + if rd='1' then + f <= '0'; + end if; + end if; + + end if; + +end process; + +end rtl; + +library ieee; +use ieee.std_logic_1164.all; + +entity fifo is + +generic (width : integer := 8; depth : integer := 4; thres : integer := 2); +port ( + clk : in std_logic; + reset : in std_logic; + + din : in std_logic_vector(width-1 downto 0); + dout : out std_logic_vector(width-1 downto 0); + + rd : in std_logic; + wr : in std_logic; + + empty : out std_logic; + full : out std_logic; + half : out std_logic +); +end fifo ; + +architecture rtl of fifo is + +component fifo_elem is + +generic (width : integer); +port ( + clk : in std_logic; + reset : in std_logic; + + din : in std_logic_vector(width-1 downto 0); + dout : out std_logic_vector(width-1 downto 0); + + rd : in std_logic; + wr : in std_logic; + + rd_prev : out std_logic; + full : out std_logic +); +end component; + + signal r, w, rp, f : std_logic_vector(depth-1 downto 0); + type d_array is array (0 to depth-1) of std_logic_vector(width-1 downto 0); + signal di, do : d_array; + + + +begin + + + g1: for i in 0 to depth-1 generate + + f1: fifo_elem generic map (width) + port map (clk, reset, di(i), do(i), r(i), w(i), rp(i), f(i)); + + x: if i SLAVE_CNT-1?? + rd_data <= sc_dout(sel_reg); + rdy_cnt <= sc_rdy_cnt(sel_reg); + + -- + -- Connect SLAVE_CNT simple test slaves + -- + gsl: for i in 0 to SLAVE_CNT-1 generate + + sc_rd(i) <= rd when i=sel else '0'; + sc_wr(i) <= wr when i=sel else '0'; + + scsl: entity work.sc_test_slave + generic map ( + -- shall we use less address bits inside the slaves? + addr_bits => SLAVE_ADDR_BITS + ) + port map ( + clk => clk, + reset => reset, + + address => address(SLAVE_ADDR_BITS-1 downto 0), + wr_data => wr_data, + rd => sc_rd(i), + wr => sc_wr(i), + rd_data => sc_dout(i), + rdy_cnt => sc_rdy_cnt(i) + ); + end generate; + + -- + -- Register read mux selector + -- + process(clk, reset) + begin + if (reset='1') then + sel_reg <= 0; + elsif rising_edge(clk) then + if rd='1' then + sel_reg <= sel; + end if; + end if; + end process; + + +end rtl; Index: simpcon/trunk/vhdl/sc_test_slave.vhd =================================================================== --- simpcon/trunk/vhdl/sc_test_slave.vhd (nonexistent) +++ simpcon/trunk/vhdl/sc_test_slave.vhd (revision 26) @@ -0,0 +1,100 @@ +-- +-- sc_test_slave.vhd +-- +-- A simple test slave for the SimpCon interface +-- +-- Author: Martin Schoeberl martin@jopdesign.com +-- +-- +-- resources on Cyclone +-- +-- xx LCs, max xx MHz +-- +-- +-- 2005-11-29 first version +-- +-- todo: +-- +-- + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity sc_test_slave is +generic (addr_bits : 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) + +); +end sc_test_slave; + +architecture rtl of sc_test_slave is + + signal xyz : std_logic_vector(31 downto 0); + signal cnt : unsigned(31 downto 0); + +begin + + 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 + + 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 <= std_logic_vector(cnt); + else + rd_data <= xyz; + end if; + end if; + end if; + +end process; + + +-- +-- SimpCon write is very simple +-- +process(clk, reset) + +begin + + if (reset='1') then + xyz <= (others => '0'); + cnt <= (others => '0'); + + elsif rising_edge(clk) then + + if wr='1' then + xyz <= wr_data; + end if; + + cnt <= cnt+1; + + end if; + +end process; + + +end rtl; Index: simpcon/trunk =================================================================== --- simpcon/trunk (nonexistent) +++ simpcon/trunk (revision 26)
simpcon/trunk Property changes : Added: svn:mergeinfo ## -0,0 +0,0 ## Index: simpcon/web_uploads =================================================================== --- simpcon/web_uploads (nonexistent) +++ simpcon/web_uploads (revision 26)
simpcon/web_uploads Property changes : Added: svn:mergeinfo ## -0,0 +0,0 ## Index: simpcon/branches =================================================================== --- simpcon/branches (nonexistent) +++ simpcon/branches (revision 26)
simpcon/branches Property changes : Added: svn:mergeinfo ## -0,0 +0,0 ## Index: simpcon/tags/arelease/doc/simpcon.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: simpcon/tags/arelease/doc/simpcon.pdf =================================================================== --- simpcon/tags/arelease/doc/simpcon.pdf (nonexistent) +++ simpcon/tags/arelease/doc/simpcon.pdf (revision 26)
simpcon/tags/arelease/doc/simpcon.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: simpcon/tags =================================================================== --- simpcon/tags (nonexistent) +++ simpcon/tags (revision 26)
simpcon/tags Property changes : Added: svn:mergeinfo ## -0,0 +0,0 ##

powered by: WebSVN 2.1.0

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