URL
https://opencores.org/ocsvn/simpcon/simpcon/trunk
Subversion Repositories simpcon
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 11 to Rev 12
- ↔ Reverse comparison
Rev 11 → Rev 12
/trunk/vhdl/sc_uart.vhd
0,0 → 1,357
-- |
-- 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 |
-- |
|
|
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; |
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 |
|
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 |
-- |
rxd_reg <= rxd; -- to avoid setup timing error in Quartus |
rx_buf(0) <= rxd_reg; |
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; |
/trunk/vhdl/fifo.vhd
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<depth-1 generate |
r(i) <= rp(i+1); |
w(i+1) <= f(i); |
di(i+1) <= do(i); |
end generate; |
|
end generate; |
|
di(0) <= din; |
dout <= do(depth-1); |
w(0) <= wr; |
r(depth-1) <= rd; |
|
full <= f(0); |
half <= f(depth-thres); |
empty <= not f(depth-1); |
|
end rtl; |
|
/trunk/vhdl/iomin.vhd
0,0 → 1,183
-- |
-- iomin.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 |
-- |
-- |
|
|
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); |
|
-- interrupt |
|
irq : out std_logic; |
irq_ena : out std_logic; |
|
-- 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 := 2; |
-- SLAVE_CNT <= 2**DECODE_BITS |
constant DECODE_BITS : integer := 1; |
-- 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(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'; |
|
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; |
|
cmp_cnt: entity work.sc_cnt generic map ( |
addr_bits => SLAVE_ADDR_BITS, |
clk_freq => clk_freq |
) |
port map( |
clk => clk, |
reset => reset, |
|
address => address(SLAVE_ADDR_BITS-1 downto 0), |
wr_data => wr_data, |
rd => sc_rd(0), |
wr => sc_wr(0), |
rd_data => sc_dout(0), |
rdy_cnt => sc_rdy_cnt(0), |
|
irq => irq, |
irq_ena => irq_ena, |
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 => address(SLAVE_ADDR_BITS-1 downto 0), |
wr_data => 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; |