|
Message
From: cvs at opencores.org<cvs@o...>
Date: Sun Mar 25 03:09:54 CEST 2007
Subject: [cvs-checkins] MODIFIED: simpcon ...
Date: 00/07/03 25:03:09 Added: simpcon/vhdl sc2ahbsl.vhd sc2avalon.vhd sc_cnt.vhd sc_fpu.vhd sc_lego.vhd sc_mac.vhd sc_pack.vhd sc_sigdel.vhd sc_sram16.vhd sc_sram32_flash.vhd sc_uart_tal.vhd sc_usb.vhd sigdel.vhd Log: update from JOP Revision Changes Path 1.1 simpcon/vhdl/sc2ahbsl.vhd http://www.opencores.org/cvsweb.shtml/simpcon/vhdl/sc2ahbsl.vhd?rev=1.1&content-type=text/x-cvsweb-markup Index: sc2ahbsl.vhd =================================================================== -- -- sc2ahbsl.vhd -- -- SimpCon to AMBA bridge -- -- Author: Martin Schoeberl martin@j... -- -- 2007-03-16 first version -- 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; 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;
1.1 simpcon/vhdl/sc2avalon.vhd
http://www.opencores.org/cvsweb.shtml/simpcon/vhdl/sc2avalon.vhd?rev=1.1&content-type=text/x-cvsweb-markup
Index: sc2avalon.vhd
===================================================================
--
-- sc2avalon.vhd
--
-- SimpCon to Avalon bridge
--
-- Author: Martin Schoeberl martin@j...
--
-- 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;
1.1 simpcon/vhdl/sc_cnt.vhd
http://www.opencores.org/cvsweb.shtml/simpcon/vhdl/sc_cnt.vhd?rev=1.1&content-type=text/x-cvsweb-markup
Index: sc_cnt.vhd
===================================================================
--
-- sc_cnt.vhd
--
-- counter, interrrupt handling and watchdog bit
--
-- Author: Martin Schoeberl martin@g...
--
-- 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(0) <= '1';
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;
1.1 simpcon/vhdl/sc_fpu.vhd
http://www.opencores.org/cvsweb.shtml/simpcon/vhdl/sc_fpu.vhd?rev=1.1&content-type=text/x-cvsweb-markup
Index: sc_fpu.vhd
===================================================================
-- 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');
elsif rising_edge(clk_i) then
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);
end if;
end if;
end if;
end process;
end rtl;
1.1 simpcon/vhdl/sc_lego.vhd
http://www.opencores.org/cvsweb.shtml/simpcon/vhdl/sc_lego.vhd?rev=1.1&content-type=text/x-cvsweb-markup
Index: sc_lego.vhd
===================================================================
--
-- sc_lego.vhd
--
-- Motor and sensor interface for LEGO MindStorms
--
-- Author: Martin Schoeberl martin@j...
--
-- address map:
--
-- 0 motor output, sensor input
-- 1 not used
-- 2 not used
-- 3 not used
--
-- 2005-12-22 adapted for SimpCon interface
--
-- todo:
--
--
--
-- lesens
--
-- sigma delta AD converter and power switch
-- for the LEGO sensor.
--
-- TODO: write a general sigma delta ADC
-- But this one is special as the senso gets powered!
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity lesens is
generic (clk_freq : integer);
port (
clk : in std_logic;
reset : in std_logic;
dout : out std_logic_vector(8 downto 0);
sp : out std_logic;
sdi : in std_logic;
sdo : out std_logic
);
end lesens ;
architecture rtl of lesens is
signal clkint : unsigned(8 downto 0); -- 9 bit ADC
signal val : unsigned(8 downto 0);
signal rx_d : std_logic;
signal serdata : std_logic;
signal spike : std_logic_vector(2 downto 0); -- sync in, filter
signal pow_cnt : unsigned(2 downto 0);
signal clksd : std_logic;
signal prescale : unsigned(7 downto 0);
constant sd_clk_cnt : integer := ((clk_freq+1000000)/2000000)-1;
begin
--
-- power switch for sensor
--
process(pow_cnt)
begin
sp <= '1';
if pow_cnt=0 or pow_cnt=1 then
sp <= '0';
end if;
end process;
sdo <= serdata;
--
-- prescaler (2 MHz clock)
--
process(clk, reset)
begin
if (reset='1') then
prescale <= (others => '0');
clksd <= '0';
elsif rising_edge(clk) then
clksd <= '0';
prescale <= prescale + 1;
if prescale = sd_clk_cnt then
prescale <= (others => '0');
clksd <= '1';
end if;
end if;
end process;
--
-- sigma delta converter
--
process(clk, reset)
begin
if (reset='1') then
spike <= "000";
dout <= (others => '0');
val <= (others => '0');
clkint <= (others => '0');
serdata <= '0';
pow_cnt <= (others => '0');
elsif rising_edge(clk) then
if clksd='1' then
--
-- delay
--
spike(0) <= sdi;
spike(2 downto 1) <= spike(1 downto 0);
serdata <= rx_d; -- no inverter, using an invert. comperator
--
-- integrate
--
if serdata='0' then -- 'invert' value
val <= val+1;
end if;
if clkint=0 then -- 256 us
if pow_cnt=1 then
dout <= std_logic_vector(val);
end if;
val <= (others => '0');
pow_cnt <= pow_cnt + 1;
end if;
clkint <= clkint+1; -- free running counter
end if;
end if;
end process;
--
-- filter input
--
with spike select
rx_d <= '0' when "000",
'0' when "001",
'0' when "010",
'1' when "011",
'0' when "100",
'1' when "101",
'1' when "110",
'1' when "111",
'X' when others;
end rtl;
--
-- lego io
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity sc_lego is
generic (addr_bits : integer;
clk_freq : integer);
port (
clk : in std_logic;
reset : in std_logic;
-- SimpCon interface
address : in std_logic_vector(addr_bits-1 downto 0);
wr_data : in std_logic_vector(31 downto 0);
rd, wr : in std_logic;
rd_data : out std_logic_vector(31 downto 0);
rdy_cnt : out unsigned(1 downto 0);
-- motor stuff
ma_en : out std_logic;
ma_l1 : out std_logic;
ma_l2 : out std_logic;
ma_l1_sdi : in std_logic;
ma_l1_sdo : out std_logic;
ma_l2_sdi : in std_logic;
ma_l2_sdo : out std_logic;
mb_en : out std_logic;
mb_l1 : out std_logic;
mb_l2 : out std_logic;
-- sensor stuff
s1_pow : out std_logic;
s1_sdi : in std_logic;
s1_sdo : out std_logic
);
end sc_lego;
architecture rtl of sc_lego is
signal m_out : std_logic_vector(5 downto 0);
signal sensor : std_logic_vector(8 downto 0);
signal xyz : std_logic_vector(31 downto 0);
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(8 downto 0) <= sensor;
rd_data(31 downto 9) <= (others => '0');
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');
m_out <= (others => '0');
elsif rising_edge(clk) then
if wr='1' then
xyz <= wr_data;
m_out <= wr_data(5 downto 0);
end if;
end if;
end process;
-- simple motor out
mb_en <= m_out(5);
mb_l1 <= m_out(4);
mb_l2 <= m_out(3);
ma_en <= m_out(2);
ma_l1 <= m_out(1);
ma_l2 <= m_out(0);
ma_l1_sdo <= '0';
ma_l2_sdo <= '0';
-- sensor adc
cmp_sens: entity work.lesens generic map (
clk_freq => clk_freq
)
port map(
clk => clk,
reset => reset,
dout => sensor,
sp => s1_pow,
sdi => s1_sdi,
sdo => s1_sdo
);
end rtl;
1.1 simpcon/vhdl/sc_mac.vhd
http://www.opencores.org/cvsweb.shtml/simpcon/vhdl/sc_mac.vhd?rev=1.1&content-type=text/x-cvsweb-markup
Index: sc_mac.vhd
===================================================================
--
-- sc_mac.vhd
--
-- A simple MAC unit with a SimpCon interface
--
-- Author: Martin Schoeberl martin@j...
--
--
-- 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;
1.1 simpcon/vhdl/sc_pack.vhd
http://www.opencores.org/cvsweb.shtml/simpcon/vhdl/sc_pack.vhd?rev=1.1&content-type=text/x-cvsweb-markup
Index: sc_pack.vhd
===================================================================
--
-- sc_pack.vhd
--
-- Package for SimpCon defines
--
-- Author: Martin Schoeberl (martin@j...)
--
--
-- 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;
end sc_pack;
1.1 simpcon/vhdl/sc_sigdel.vhd
http://www.opencores.org/cvsweb.shtml/simpcon/vhdl/sc_sigdel.vhd?rev=1.1&content-type=text/x-cvsweb-markup
Index: sc_sigdel.vhd
===================================================================
--
-- sc_sigdel.vhd
--
-- A simple sigma-delta ADC and PWM DAC for the SimpCon interface
--
-- Author: Martin Schoeberl martin@j...
--
--
-- 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;
1.1 simpcon/vhdl/sc_sram16.vhd
http://www.opencores.org/cvsweb.shtml/simpcon/vhdl/sc_sram16.vhd?rev=1.1&content-type=text/x-cvsweb-markup
Index: sc_sram16.vhd
===================================================================
--
-- 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
--
Library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;
use work.jop_types.all;
entity sc_mem_if is
generic (ram_ws : integer; addr_bits : integer);
port (
clk, 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);
-- 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_low : std_logic_vector(15 downto 0);
signal ram_din_reg : std_logic_vector(31 downto 0);
begin
ram_dout_en <= dout_ena;
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 rd='1' or wr='1' then
ram_addr <= address(addr_bits-2 downto 0) & "0";
end if;
if inc_addr='1' then
ram_addr(0) <= '1';
end if;
if wr='1' then
ram_dout <= wr_data(31 downto 16);
ram_dout_low <= wr_data(15 downto 0);
end if;
if wr_low='1' then
ram_dout <= ram_dout_low;
end if;
if rd_data_ena_h='1' then
ram_din_reg(15 downto 0) <= 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_reg(15 downto 0);
-- read second word
ram_din_reg(15 downto 0) <= ram_din;
end if;
end if;
end process;
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, rd, wr, wait_state)
begin
next_state <= state;
case state is
when idl =>
if 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 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 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 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 rd='1' or 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 rd='0' and 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;
1.1 simpcon/vhdl/sc_sram32_flash.vhd
http://www.opencores.org/cvsweb.shtml/simpcon/vhdl/sc_sram32_flash.vhd?rev=1.1&content-type=text/x-cvsweb-markup
Index: sc_sram32_flash.vhd
===================================================================
--
-- 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.rd, sc_mem_out.wr, 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;
1.1 simpcon/vhdl/sc_uart_tal.vhd
http://www.opencores.org/cvsweb.shtml/simpcon/vhdl/sc_uart_tal.vhd?rev=1.1&content-type=text/x-cvsweb-markup
Index: sc_uart_tal.vhd
===================================================================
--
-- 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@j...
--
--
-- 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;
1.1 simpcon/vhdl/sc_usb.vhd
http://www.opencores.org/cvsweb.shtml/simpcon/vhdl/sc_usb.vhd?rev=1.1&content-type=text/x-cvsweb-markup
Index: sc_usb.vhd
===================================================================
--
-- sc_usb.vhd
--
-- Interface to FTDI FT2232C parallel port B
--
-- Author: Martin Schoeberl martin@j...
--
--
-- 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;
1.1 simpcon/vhdl/sigdel.vhd
http://www.opencores.org/cvsweb.shtml/simpcon/vhdl/sigdel.vhd?rev=1.1&content-type=text/x-cvsweb-markup
Index: sigdel.vhd
===================================================================
--
-- 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@j...
--
--
-- 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;
|
 |