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 ##