diff --git a/Manifest.py b/Manifest.py index 58df8902b20384964c895941f7ae3580fc47db57..03239d0ddb8fd05c40f53ee11217a0e977a87d37 100644 --- a/Manifest.py +++ b/Manifest.py @@ -2,6 +2,6 @@ modules = { "local" : [ "modules/common", "modules/genrams" -# "modules/wishbone" + "modules/wishbone" ] } \ No newline at end of file diff --git a/modules/wishbone/Manifest.py b/modules/wishbone/Manifest.py new file mode 100644 index 0000000000000000000000000000000000000000..d2b7a2ab5fe01fe497fbcb1f709a7977bb1dbc87 --- /dev/null +++ b/modules/wishbone/Manifest.py @@ -0,0 +1,13 @@ +modules = { "local" : + + [ "wb_async_bridge", + "wb_conmax", + "wb_gpio_port", + "wb_simple_timer", + "wb_uart", + "wb_vic", + "wb_virtual_uart", + "wbgen2", + ]}; + +files = ["wishbone_pkg.vhd"]; diff --git a/modules/wishbone/wb_async_bridge/manifest.py b/modules/wishbone/wb_async_bridge/manifest.py new file mode 100644 index 0000000000000000000000000000000000000000..da4fbcbdba01c4543c6301efe16a1c76d39da6a6 --- /dev/null +++ b/modules/wishbone/wb_async_bridge/manifest.py @@ -0,0 +1 @@ +files = ["wb_cpu_bridge.vhd"] diff --git a/modules/wishbone/wb_async_bridge/wb_cpu_bridge.vhd b/modules/wishbone/wb_async_bridge/wb_cpu_bridge.vhd new file mode 100644 index 0000000000000000000000000000000000000000..9062e13942a5d40a4a1f0dd007546e716498c654 --- /dev/null +++ b/modules/wishbone/wb_async_bridge/wb_cpu_bridge.vhd @@ -0,0 +1,286 @@ +------------------------------------------------------------------------------ +-- Title : Atmel EBI asynchronous bus <-> Wishbone bridge +-- Project : White Rabbit Switch +------------------------------------------------------------------------------ +-- Author : Tomasz Wlostowski +-- Company : CERN BE-Co-HT +-- Created : 2010-05-18 +-- Last update: 2011-03-16 +-- Platform : FPGA-generic +-- Standard : VHDL'87 +------------------------------------------------------------------------------- +-- Description: An interface between AT91SAM9x-series ARM CPU External Bus Interface +-- and FPGA-internal Wishbone bus: +-- - does clock domain synchronisation +-- - provides configurable number of independent WB master ports at fixed base addresses +-- TODO: +-- - implement write queueing and read prefetching (for speed improvement) +------------------------------------------------------------------------------- +-- Copyright (c) 2010 Tomasz Wlostowski +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2010-05-18 1.0 twlostow Created +------------------------------------------------------------------------------- + + +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.math_real.log2; +use ieee.math_real.ceil; + +use work.wishbone_pkg.all; +use work.common_components.all; + +entity wb_cpu_bridge is + generic ( + g_simulation : integer := 0; + g_wishbone_num_masters : integer); + + port( + sys_rst_n_i : in std_logic; -- global reset + +------------------------------------------------------------------------------- +-- Atmel EBI bus +------------------------------------------------------------------------------- + + cpu_clk_i : in std_logic; -- clock (not used now) +-- async chip select, active LOW + cpu_cs_n_i : in std_logic; +-- async write, active LOW + cpu_wr_n_i : in std_logic; +-- async read, active LOW + cpu_rd_n_i : in std_logic; +-- byte select, active LOW (not used due to weird CPU pin layout - NBS2 line is +-- shared with 100 Mbps Ethernet PHY) + cpu_bs_n_i : in std_logic_vector(3 downto 0); + +-- address input + cpu_addr_i : in std_logic_vector(c_cpu_addr_width-1 downto 0); + +-- data bus (bidirectional) + cpu_data_b : inout std_logic_vector(31 downto 0); + +-- async wait, active LOW + cpu_nwait_o : out std_logic; + +------------------------------------------------------------------------------- +-- Wishbone master I/F +------------------------------------------------------------------------------- + +-- wishbone clock input (refclk/2) + wb_clk_i : in std_logic; +-- wishbone master address output (m->s, common for all slaves) + wb_addr_o : out std_logic_vector(c_wishbone_addr_width - 1 downto 0); +-- wishbone master data output (m->s, common for all slaves) + wb_data_o : out std_logic_vector(31 downto 0); +-- wishbone cycle strobe (m->s, common for all slaves) + wb_stb_o : out std_logic; +-- wishbone write enable (m->s, common for all slaves) + wb_we_o : out std_logic; +-- wishbone byte select output (m->s, common for all slaves) + wb_sel_o : out std_logic_vector(3 downto 0); + + +-- wishbone cycle select (m->s, individual) + wb_cyc_o : out std_logic_vector (g_wishbone_num_masters - 1 downto 0); +-- wishbone master data input (s->m, individual) + wb_data_i : in std_logic_vector (32 * g_wishbone_num_masters-1 downto 0); +-- wishbone ACK input (s->m, individual) + wb_ack_i : in std_logic_vector(g_wishbone_num_masters-1 downto 0) + + ); + +end wb_cpu_bridge; + +architecture behavioral of wb_cpu_bridge is + + constant c_periph_addr_bits : integer := c_cpu_addr_width - c_wishbone_addr_width; + + signal periph_addr : std_logic_vector(c_periph_addr_bits - 1 downto 0); + signal periph_addr_reg : std_logic_vector(c_periph_addr_bits - 1 downto 0); + + signal periph_sel : std_logic_vector(g_wishbone_num_masters - 1 downto 0); + signal periph_sel_reg : std_logic_vector(g_wishbone_num_masters - 1 downto 0); + + + signal rw_sel, cycle_in_progress, cs_synced, rd_pulse, wr_pulse : std_logic; + signal cpu_data_reg : std_logic_vector(31 downto 0); + signal ack_muxed : std_logic; + signal data_in_muxed : std_logic_vector(31 downto 0); + signal long_cycle : std_logic; + signal wb_cyc_int : std_logic; + +begin + + gen_sync_chains_nosim : if(g_simulation = 0) generate + + sync_ffs_cs : sync_ffs + generic map ( + g_sync_edge => "positive") + port map + (rst_n_i => sys_rst_n_i, + clk_i => wb_clk_i, + data_i => cpu_cs_n_i, + synced_o => cs_synced, + npulse_o => open + ); + + sync_ffs_wr : sync_ffs + generic map ( + g_sync_edge => "positive") + port map ( + rst_n_i => sys_rst_n_i, + clk_i => wb_clk_i, + data_i => cpu_wr_n_i, + synced_o => open, + npulse_o => wr_pulse + ); + + sync_ffs_rd : sync_ffs + generic map ( + g_sync_edge => "positive") + port map ( + rst_n_i => sys_rst_n_i, + clk_i => wb_clk_i, + data_i => cpu_rd_n_i, + synced_o => open, + npulse_o => rd_pulse + ); + + end generate gen_sync_chains_nosim; + + gen_sim : if(g_simulation = 1) generate + wr_pulse <= not cpu_wr_n_i; + rd_pulse <= not cpu_rd_n_i; + cs_synced <= cpu_cs_n_i; + end generate gen_sim; + + + + periph_addr <= cpu_addr_i (c_cpu_addr_width - 1 downto c_wishbone_addr_width); + + onehot_decode : process (periph_addr) -- periph_sel <= onehot_decode(periph_addr) + variable temp1 : std_logic_vector (periph_sel'high downto 0); + variable temp2 : integer range 0 to periph_sel'high; + begin + temp1 := (others => '0'); + temp2 := 0; + for i in periph_addr'range loop + if (periph_addr(i) = '1') then + temp2 := 2*temp2+1; + else + temp2 := 2*temp2; + end if; + end loop; + temp1(temp2) := '1'; + periph_sel <= temp1; + end process; + + + ACK_MUX : process (periph_addr_reg, wb_ack_i) + begin + if(to_integer(unsigned(periph_addr_reg)) < g_wishbone_num_masters) then + ack_muxed <= wb_ack_i(to_integer(unsigned(periph_addr_reg))); + else + ack_muxed <= '0'; + end if; + end process; + + + DIN_MUX : process (periph_addr_reg, wb_data_i) + begin + if(to_integer(unsigned(periph_addr_reg)) < g_wishbone_num_masters) then + data_in_muxed <= wb_data_i(32*to_integer(unsigned(periph_addr_reg)) + 31 downto 32 * to_integer(unsigned(periph_addr_reg))); + else + data_in_muxed <= (others => 'X'); + end if; + end process; + + process(wb_clk_i) + begin + if(rising_edge(wb_clk_i)) then + if(sys_rst_n_i = '0') then + cpu_data_reg <= (others => '0'); + cycle_in_progress <= '0'; + rw_sel <= '0'; + cpu_nwait_o <= '1'; + long_cycle <= '0'; + + wb_addr_o <= (others => '0'); + wb_data_o <= (others => '0'); + wb_sel_o <= (others => '1'); + wb_stb_o <= '0'; + wb_we_o <= '0'; + wb_cyc_int <= '0'; + + periph_sel_reg <= (others => '0'); + periph_addr_reg <= (others => '0'); + else + + + if(cs_synced = '0') then + + wb_addr_o <= cpu_addr_i(c_wishbone_addr_width-1 downto 0); + + if(cycle_in_progress = '1') then + if(ack_muxed = '1') then + + if(rw_sel = '0') then + cpu_data_reg <= data_in_muxed; + end if; + + cycle_in_progress <= '0'; + wb_cyc_int <= '0'; + wb_sel_o <= (others => '1'); + wb_stb_o <= '0'; + wb_we_o <= '0'; + cpu_nwait_o <= '1'; + long_cycle <= '0'; + + else + cpu_nwait_o <= not long_cycle; + long_cycle <= '1'; + end if; + + elsif(rd_pulse = '1' or wr_pulse = '1') then + wb_we_o <= wr_pulse; + rw_sel <= wr_pulse; + + wb_cyc_int <= '1'; + wb_stb_o <= '1'; + wb_addr_o <= cpu_addr_i(c_wishbone_addr_width-1 downto 0); + long_cycle <= '0'; + + periph_addr_reg <= cpu_addr_i (c_cpu_addr_width-1 downto c_wishbone_addr_width); + periph_sel_reg <= periph_sel; + + if(wr_pulse = '1') then + wb_data_o <= cpu_data_b; + end if; + + cycle_in_progress <= '1'; + end if; + end if; + end if; + end if; + end process; + + process(cpu_cs_n_i, cpu_rd_n_i, cpu_data_reg) + begin + if(cpu_cs_n_i = '0' and cpu_rd_n_i = '0') then + cpu_data_b <= cpu_data_reg; + else + cpu_data_b <= (others => 'Z'); + end if; + end process; + + gen_cyc_outputs : for i in 0 to g_wishbone_num_masters-1 generate + wb_cyc_o(i) <= wb_cyc_int and periph_sel_reg(i); + end generate gen_cyc_outputs; + + + +end behavioral; diff --git a/modules/wishbone/wb_conmax/Manifest.py b/modules/wishbone/wb_conmax/Manifest.py new file mode 100644 index 0000000000000000000000000000000000000000..b4dc1c435ece1df8b3596c8bd9ba1b904b45bf5f --- /dev/null +++ b/modules/wishbone/wb_conmax/Manifest.py @@ -0,0 +1,3 @@ +files = ["wb_conmax_pri_dec.vhd", "wb_conmax_pri_enc.vhd", "wb_conmax_arb.vhd", "wb_conmax_msel.vhd", + "wbconmax_pkg.vhd", "wb_conmax_slave_if.vhd", "wb_conmax_master_if.vhd", "wb_conmax_rf.vhd", + "wb_conmax_top.vhd" ]; diff --git a/modules/wishbone/wb_conmax/wb_conmax_arb.vhd b/modules/wishbone/wb_conmax/wb_conmax_arb.vhd new file mode 100644 index 0000000000000000000000000000000000000000..6ab431fbe4466448a5b37048ce28eb8bac1c4cb6 --- /dev/null +++ b/modules/wishbone/wb_conmax/wb_conmax_arb.vhd @@ -0,0 +1,238 @@ +------------------------------------------------------------------------------- +-- Title : Wishbone interconnect matrix for WR Core +-- Project : WhiteRabbit +------------------------------------------------------------------------------- +-- File : wb_conmax_arb.vhd +-- Author : Grzegorz Daniluk +-- Company : Elproma +-- Created : 2011-02-12 +-- Last update: 2011-02-16 +-- Platform : FPGA-generics +-- Standard : VHDL +------------------------------------------------------------------------------- +-- Description: +-- Simple arbiter with round robin. It does not use any prioritization for +-- WB Masters. +-- +------------------------------------------------------------------------------- +-- Copyright (C) 2000-2002 Rudolf Usselmann +-- Copyright (c) 2011 Grzegorz Daniluk (VHDL port) +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2011-02-12 1.0 greg.d Created +------------------------------------------------------------------------------- +-- TODO: +-- Code optimization. (now it is more like dummy translation from Verilog) +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity wb_conmax_arb is + port( + clk_i : in std_logic; + rst_i : in std_logic; + + --req_i(n) <- wb_cyc from n-th Master + req_i : in std_logic_vector(7 downto 0); + next_i : in std_logic; + --which master (0 to 7) is granted + gnt_o : out std_logic_vector(2 downto 0) + ); +end wb_conmax_arb; + +architecture behaviour of wb_conmax_arb is + type t_arb_states is (GRANT0, GRANT1, GRANT2, GRANT3, GRANT4, GRANT5, + GRANT6, GRANT7); + + signal s_state : t_arb_states; +begin + + --state transitions + process(clk_i) + begin + if(clk_i'event and clk_i='1') then + if(rst_i = '1') then + s_state <= GRANT0; + else + + case s_state is + when GRANT0 => + --if this req is dropped or next is asserted, check for other req's + if(req_i(0)='0' or next_i='1') then + if ( req_i(1)='1' ) then + s_state <= GRANT1; + elsif( req_i(2)='1' ) then + s_state <= GRANT2; + elsif( req_i(3)='1' ) then + s_state <= GRANT3; + elsif( req_i(4)='1' ) then + s_state <= GRANT4; + elsif( req_i(5)='1' ) then + s_state <= GRANT5; + elsif( req_i(6)='1' ) then + s_state <= GRANT6; + elsif( req_i(7)='1' ) then + s_state <= GRANT7; + end if; + end if; + + when GRANT1 => + if(req_i(1)='0' or next_i='1') then + if ( req_i(2)='1' ) then + s_state <= GRANT2; + elsif( req_i(3)='1' ) then + s_state <= GRANT3; + elsif( req_i(4)='1' ) then + s_state <= GRANT4; + elsif( req_i(5)='1' ) then + s_state <= GRANT5; + elsif( req_i(6)='1' ) then + s_state <= GRANT6; + elsif( req_i(7)='1' ) then + s_state <= GRANT7; + elsif( req_i(0)='1' ) then + s_state <= GRANT0; + end if; + end if; + + when GRANT2 => + if(req_i(2)='0' or next_i='1') then + if ( req_i(3)='1' ) then + s_state <= GRANT3; + elsif( req_i(4)='1' ) then + s_state <= GRANT4; + elsif( req_i(5)='1' ) then + s_state <= GRANT5; + elsif( req_i(6)='1' ) then + s_state <= GRANT6; + elsif( req_i(7)='1' ) then + s_state <= GRANT7; + elsif( req_i(0)='1' ) then + s_state <= GRANT0; + elsif( req_i(1)='1' ) then + s_state <= GRANT1; + end if; + end if; + + when GRANT3 => + if(req_i(3)='0' or next_i='1') then + if ( req_i(4)='1' ) then + s_state <= GRANT4; + elsif( req_i(5)='1' ) then + s_state <= GRANT5; + elsif( req_i(6)='1' ) then + s_state <= GRANT6; + elsif( req_i(7)='1' ) then + s_state <= GRANT7; + elsif( req_i(0)='1' ) then + s_state <= GRANT0; + elsif( req_i(1)='1' ) then + s_state <= GRANT1; + elsif( req_i(2)='1' ) then + s_state <= GRANT2; + end if; + end if; + + when GRANT4 => + if(req_i(4)='0' or next_i='1') then + if ( req_i(5)='1' ) then + s_state <= GRANT5; + elsif( req_i(6)='1' ) then + s_state <= GRANT6; + elsif( req_i(7)='1' ) then + s_state <= GRANT7; + elsif( req_i(0)='1' ) then + s_state <= GRANT0; + elsif( req_i(1)='1' ) then + s_state <= GRANT1; + elsif( req_i(2)='1' ) then + s_state <= GRANT2; + elsif( req_i(3)='1' ) then + s_state <= GRANT3; + end if; + end if; + + when GRANT5 => + if(req_i(5)='0' or next_i='1') then + if ( req_i(6)='1' ) then + s_state <= GRANT6; + elsif( req_i(7)='1' ) then + s_state <= GRANT7; + elsif( req_i(0)='1' ) then + s_state <= GRANT0; + elsif( req_i(1)='1' ) then + s_state <= GRANT1; + elsif( req_i(2)='1' ) then + s_state <= GRANT2; + elsif( req_i(3)='1' ) then + s_state <= GRANT3; + elsif( req_i(4)='1' ) then + s_state <= GRANT4; + end if; + end if; + + when GRANT6 => + if(req_i(6)='0' or next_i='1') then + if ( req_i(7)='1' ) then + s_state <= GRANT7; + elsif( req_i(0)='1' ) then + s_state <= GRANT0; + elsif( req_i(1)='1' ) then + s_state <= GRANT1; + elsif( req_i(2)='1' ) then + s_state <= GRANT2; + elsif( req_i(3)='1' ) then + s_state <= GRANT3; + elsif( req_i(4)='1' ) then + s_state <= GRANT4; + elsif( req_i(5)='1' ) then + s_state <= GRANT5; + end if; + end if; + + when GRANT7 => + if(req_i(7)='0' or next_i='1') then + if ( req_i(0)='1' ) then + s_state <= GRANT0; + elsif( req_i(1)='1' ) then + s_state <= GRANT1; + elsif( req_i(2)='1' ) then + s_state <= GRANT2; + elsif( req_i(3)='1' ) then + s_state <= GRANT3; + elsif( req_i(4)='1' ) then + s_state <= GRANT4; + elsif( req_i(5)='1' ) then + s_state <= GRANT5; + elsif( req_i(6)='1' ) then + s_state <= GRANT6; + end if; + end if; + + when others => + s_state <= GRANT0; + end case; + + end if; + end if; + end process; + + process(s_state) + begin + case(s_state) is + when GRANT0 => gnt_o <= "000"; + when GRANT1 => gnt_o <= "001"; + when GRANT2 => gnt_o <= "010"; + when GRANT3 => gnt_o <= "011"; + when GRANT4 => gnt_o <= "100"; + when GRANT5 => gnt_o <= "101"; + when GRANT6 => gnt_o <= "110"; + when GRANT7 => gnt_o <= "111"; + when others => gnt_o <= "000"; + end case; + end process; + +end behaviour; diff --git a/modules/wishbone/wb_conmax/wb_conmax_master_if.vhd b/modules/wishbone/wb_conmax/wb_conmax_master_if.vhd new file mode 100644 index 0000000000000000000000000000000000000000..1862520f0b07fbb612c331b9c12c73f54aa187cc --- /dev/null +++ b/modules/wishbone/wb_conmax/wb_conmax_master_if.vhd @@ -0,0 +1,168 @@ +------------------------------------------------------------------------------- +-- Title : Wishbone interconnect matrix for WR Core +-- Project : WhiteRabbit +------------------------------------------------------------------------------- +-- File : wb_conmax_master_if.vhd +-- Author : Grzegorz Daniluk +-- Company : Elproma +-- Created : 2011-02-12 +-- Last update: 2010-02-16 +-- Platform : FPGA-generics +-- Standard : VHDL +------------------------------------------------------------------------------- +-- Description: +-- Wishbone interface to connect WB master from outside. Decodes 4 most +-- significant bits of Address bus. Using the selection it multiplexes the +-- Master's WB interface to appropriate Slave interface. +-- +------------------------------------------------------------------------------- +-- Copyright (C) 2000-2002 Rudolf Usselmann +-- Copyright (c) 2011 Grzegorz Daniluk (VHDL port) +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2011-02-12 1.0 greg.d Created +-- 2011-02-16 1.1 greg.d Using generates and types +------------------------------------------------------------------------------- +-- TODO: +-- Code optimization. (now it is more like dummy translation from Verilog) +-- +------------------------------------------------------------------------------- + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.wbconmax_pkg.all; + +entity wb_conmax_master_if is + port( + clk_i : in std_logic; + rst_i : in std_logic; + + --Master interface + wb_master_i : in t_wb_i; + wb_master_o : out t_wb_o; + + --Slaves(0 to 15) interface + wb_slaves_i : in t_conmax_slaves_i; + wb_slaves_o : out t_conmax_slaves_o + ); +end wb_conmax_master_if; + +architecture behaviour of wb_conmax_master_if is + + signal s_slv_sel : std_logic_vector(3 downto 0); + signal s_cyc_o_next : std_logic_vector(15 downto 0); + signal s_cyc_o : std_logic_vector(15 downto 0); + +begin + + --Select logic + s_slv_sel <= wb_master_i.addr(c_aw-1 downto c_aw-4); + + --Address & Data Pass + GEN_OUTS: + for I in 0 to 15 generate + wb_slaves_o(I).addr <= wb_master_i.addr; + wb_slaves_o(I).sel <= wb_master_i.sel; + wb_slaves_o(I).data <= wb_master_i.data; + wb_slaves_o(I).we <= wb_master_i.we; + wb_slaves_o(I).cyc <= s_cyc_o(I); + wb_slaves_o(I).stb <= wb_master_i.stb when(s_slv_sel=std_logic_vector( + to_unsigned(I, 4)) ) else '0'; + end generate; + + wb_master_o.data <= wb_slaves_i( 0).data when(s_slv_sel="0000") else + wb_slaves_i( 1).data when(s_slv_sel="0001") else + wb_slaves_i( 2).data when(s_slv_sel="0010") else + wb_slaves_i( 3).data when(s_slv_sel="0011") else + wb_slaves_i( 4).data when(s_slv_sel="0100") else + wb_slaves_i( 5).data when(s_slv_sel="0101") else + wb_slaves_i( 6).data when(s_slv_sel="0110") else + wb_slaves_i( 7).data when(s_slv_sel="0111") else + wb_slaves_i( 8).data when(s_slv_sel="1000") else + wb_slaves_i( 9).data when(s_slv_sel="1001") else + wb_slaves_i(10).data when(s_slv_sel="1010") else + wb_slaves_i(11).data when(s_slv_sel="1011") else + wb_slaves_i(12).data when(s_slv_sel="1100") else + wb_slaves_i(13).data when(s_slv_sel="1101") else + wb_slaves_i(14).data when(s_slv_sel="1110") else + wb_slaves_i(15).data when(s_slv_sel="1111") else + (others=>'0'); + + --Control Signal Pass + G1: for I in 0 to 15 generate + s_cyc_o_next(I) <= s_cyc_o(I) when ( wb_master_i.cyc='1' and wb_master_i.stb='0') else + wb_master_i.cyc when ( s_slv_sel=std_logic_vector(to_unsigned(I, 4)) ) else + '0'; + end generate; + + process(clk_i) + begin + if( clk_i'event and clk_i='1') then + if(rst_i='1') then + s_cyc_o(15 downto 0) <= (others => '0'); + else + s_cyc_o(15 downto 0) <= s_cyc_o_next(15 downto 0); + end if; + end if; + end process; + + wb_master_o.ack <= wb_slaves_i( 0).ack when(s_slv_sel="0000") else + wb_slaves_i( 1).ack when(s_slv_sel="0001") else + wb_slaves_i( 2).ack when(s_slv_sel="0010") else + wb_slaves_i( 3).ack when(s_slv_sel="0011") else + wb_slaves_i( 4).ack when(s_slv_sel="0100") else + wb_slaves_i( 5).ack when(s_slv_sel="0101") else + wb_slaves_i( 6).ack when(s_slv_sel="0110") else + wb_slaves_i( 7).ack when(s_slv_sel="0111") else + wb_slaves_i( 8).ack when(s_slv_sel="1000") else + wb_slaves_i( 9).ack when(s_slv_sel="1001") else + wb_slaves_i(10).ack when(s_slv_sel="1010") else + wb_slaves_i(11).ack when(s_slv_sel="1011") else + wb_slaves_i(12).ack when(s_slv_sel="1100") else + wb_slaves_i(13).ack when(s_slv_sel="1101") else + wb_slaves_i(14).ack when(s_slv_sel="1110") else + wb_slaves_i(15).ack when(s_slv_sel="1111") else + '0'; + + wb_master_o.err <= wb_slaves_i( 0).err when(s_slv_sel="0000") else + wb_slaves_i( 1).err when(s_slv_sel="0001") else + wb_slaves_i( 2).err when(s_slv_sel="0010") else + wb_slaves_i( 3).err when(s_slv_sel="0011") else + wb_slaves_i( 4).err when(s_slv_sel="0100") else + wb_slaves_i( 5).err when(s_slv_sel="0101") else + wb_slaves_i( 6).err when(s_slv_sel="0110") else + wb_slaves_i( 7).err when(s_slv_sel="0111") else + wb_slaves_i( 8).err when(s_slv_sel="1000") else + wb_slaves_i( 9).err when(s_slv_sel="1001") else + wb_slaves_i(10).err when(s_slv_sel="1010") else + wb_slaves_i(11).err when(s_slv_sel="1011") else + wb_slaves_i(12).err when(s_slv_sel="1100") else + wb_slaves_i(13).err when(s_slv_sel="1101") else + wb_slaves_i(14).err when(s_slv_sel="1110") else + wb_slaves_i(15).err when(s_slv_sel="1111") else + '0'; + + wb_master_o.rty <= wb_slaves_i( 0).rty when(s_slv_sel="0000") else + wb_slaves_i( 1).rty when(s_slv_sel="0001") else + wb_slaves_i( 2).rty when(s_slv_sel="0010") else + wb_slaves_i( 3).rty when(s_slv_sel="0011") else + wb_slaves_i( 4).rty when(s_slv_sel="0100") else + wb_slaves_i( 5).rty when(s_slv_sel="0101") else + wb_slaves_i( 6).rty when(s_slv_sel="0110") else + wb_slaves_i( 7).rty when(s_slv_sel="0111") else + wb_slaves_i( 8).rty when(s_slv_sel="1000") else + wb_slaves_i( 9).rty when(s_slv_sel="1001") else + wb_slaves_i(10).rty when(s_slv_sel="1010") else + wb_slaves_i(11).rty when(s_slv_sel="1011") else + wb_slaves_i(12).rty when(s_slv_sel="1100") else + wb_slaves_i(13).rty when(s_slv_sel="1101") else + wb_slaves_i(14).rty when(s_slv_sel="1110") else + wb_slaves_i(15).rty when(s_slv_sel="1111") else + '0'; + +end behaviour; diff --git a/modules/wishbone/wb_conmax/wb_conmax_msel.vhd b/modules/wishbone/wb_conmax/wb_conmax_msel.vhd new file mode 100644 index 0000000000000000000000000000000000000000..3631498b5b15c6ddd4bdc47984d7a9686e6702c0 --- /dev/null +++ b/modules/wishbone/wb_conmax/wb_conmax_msel.vhd @@ -0,0 +1,267 @@ +------------------------------------------------------------------------------- +-- Title : Wishbone interconnect matrix for WR Core +-- Project : WhiteRabbit +------------------------------------------------------------------------------- +-- File : wb_conmax_msel.vhd +-- Author : Grzegorz Daniluk +-- Company : Elproma +-- Created : 2011-02-12 +-- Last update: 2010-02-12 +-- Platform : FPGA-generics +-- Standard : VHDL +------------------------------------------------------------------------------- +-- Description: +-- Prioritizing arbiter for Slave interface. Uses simple arbitrer +-- (wb_conmax_arb) and takes Master's priorities into account. +-- +------------------------------------------------------------------------------- +-- Copyright (C) 2000-2002 Rudolf Usselmann +-- Copyright (c) 2011 Grzegorz Daniluk (VHDL port) +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2011-02-12 1.0 greg.d Created +------------------------------------------------------------------------------- +-- TODO: +-- Code optimization. (now it is more like dummy translation from Verilog) +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity wb_conmax_msel is + generic( + g_pri_sel : integer := 0 + ); + port( + clk_i : in std_logic; + rst_i : in std_logic; + + conf_i : in std_logic_vector(15 downto 0); + req_i : in std_logic_vector(7 downto 0); + next_i : in std_logic; + + sel : out std_logic_vector(2 downto 0) + ); +end wb_conmax_msel; + +architecture behavioral of wb_conmax_msel is + + component wb_conmax_pri_enc is + generic( + -- :=1 means 2 priority levels, :=2 means 4 priority levels + g_pri_sel : integer := 0 + ); + port( + valid_i : in std_logic_vector(7 downto 0); + + pri0_i : in std_logic_vector(1 downto 0); + pri1_i : in std_logic_vector(1 downto 0); + pri2_i : in std_logic_vector(1 downto 0); + pri3_i : in std_logic_vector(1 downto 0); + pri4_i : in std_logic_vector(1 downto 0); + pri5_i : in std_logic_vector(1 downto 0); + pri6_i : in std_logic_vector(1 downto 0); + pri7_i : in std_logic_vector(1 downto 0); + + pri_o : out std_logic_vector(1 downto 0) + ); + end component; + + component wb_conmax_arb is + port( + clk_i : in std_logic; + rst_i : in std_logic; + + req_i : in std_logic_vector(7 downto 0); + gnt_o : out std_logic_vector(2 downto 0); + + next_i : in std_logic + ); + end component; + + + signal s_pri0, s_pri1, s_pri2, s_pri3, s_pri4, + s_pri5, s_pri6, s_pri7 : std_logic_vector(1 downto 0); + + signal s_pri_out_d, s_pri_out : std_logic_vector(1 downto 0); + signal s_req_p0, s_req_p1, s_req_p2, s_req_p3 : std_logic_vector(7 downto 0); + signal s_gnt_p0, s_gnt_p1, s_gnt_p2, s_gnt_p3 : std_logic_vector(2 downto 0); + signal s_sel1, s_sel2 : std_logic_vector(2 downto 0); + +begin + + -------------------------------------- + --Priority Select logic + G1: if(g_pri_sel=0) generate + s_pri0 <= "00"; + s_pri1 <= "00"; + s_pri2 <= "00"; + s_pri3 <= "00"; + s_pri4 <= "00"; + s_pri5 <= "00"; + s_pri6 <= "00"; + s_pri7 <= "00"; + end generate; + + G2: if(g_pri_sel=2) generate + s_pri0 <= conf_i(1 downto 0); + s_pri1 <= conf_i(3 downto 2); + s_pri2 <= conf_i(5 downto 4); + s_pri3 <= conf_i(7 downto 6); + s_pri4 <= conf_i(9 downto 8); + s_pri5 <= conf_i(11 downto 10); + s_pri6 <= conf_i(13 downto 12); + s_pri7 <= conf_i(15 downto 14); + end generate; + + G3: if(g_pri_sel/=0 and g_pri_sel/=2) generate + s_pri0 <= '0' & conf_i(0); + s_pri1 <= '0' & conf_i(2); + s_pri2 <= '0' & conf_i(4); + s_pri3 <= '0' & conf_i(6); + s_pri4 <= '0' & conf_i(8); + s_pri5 <= '0' & conf_i(10); + s_pri6 <= '0' & conf_i(12); + s_pri7 <= '0' & conf_i(14); + end generate; + + PRI_ENC: wb_conmax_pri_enc + generic map( + -- :=1 means 2 priority levels, :=2 means 4 priority levels + g_pri_sel => g_pri_sel + ) + port map( + valid_i => req_i, + + pri0_i => s_pri0, + pri1_i => s_pri1, + pri2_i => s_pri2, + pri3_i => s_pri3, + pri4_i => s_pri4, + pri5_i => s_pri5, + pri6_i => s_pri6, + pri7_i => s_pri7, + + pri_o => s_pri_out_d + ); + + + process(clk_i) + begin + if(clk_i'event and clk_i='1') then + if(rst_i = '1') then + s_pri_out <= "00"; + elsif(next_i = '1') then + s_pri_out <= s_pri_out_d; + end if; + end if; + end process; + + + ----------------------------------------------- + --Arbiters + s_req_p0(0) <= req_i(0) when(s_pri0 = "00") else '0'; + s_req_p0(1) <= req_i(1) when(s_pri1 = "00") else '0'; + s_req_p0(2) <= req_i(2) when(s_pri2 = "00") else '0'; + s_req_p0(3) <= req_i(3) when(s_pri3 = "00") else '0'; + s_req_p0(4) <= req_i(4) when(s_pri4 = "00") else '0'; + s_req_p0(5) <= req_i(5) when(s_pri5 = "00") else '0'; + s_req_p0(6) <= req_i(6) when(s_pri6 = "00") else '0'; + s_req_p0(7) <= req_i(7) when(s_pri7 = "00") else '0'; + + s_req_p1(0) <= req_i(0) when(s_pri0 = "01") else '0'; + s_req_p1(1) <= req_i(1) when(s_pri1 = "01") else '0'; + s_req_p1(2) <= req_i(2) when(s_pri2 = "01") else '0'; + s_req_p1(3) <= req_i(3) when(s_pri3 = "01") else '0'; + s_req_p1(4) <= req_i(4) when(s_pri4 = "01") else '0'; + s_req_p1(5) <= req_i(5) when(s_pri5 = "01") else '0'; + s_req_p1(6) <= req_i(6) when(s_pri6 = "01") else '0'; + s_req_p1(7) <= req_i(7) when(s_pri7 = "01") else '0'; + + s_req_p2(0) <= req_i(0) when(s_pri0 = "10") else '0'; + s_req_p2(1) <= req_i(1) when(s_pri1 = "10") else '0'; + s_req_p2(2) <= req_i(2) when(s_pri2 = "10") else '0'; + s_req_p2(3) <= req_i(3) when(s_pri3 = "10") else '0'; + s_req_p2(4) <= req_i(4) when(s_pri4 = "10") else '0'; + s_req_p2(5) <= req_i(5) when(s_pri5 = "10") else '0'; + s_req_p2(6) <= req_i(6) when(s_pri6 = "10") else '0'; + s_req_p2(7) <= req_i(7) when(s_pri7 = "10") else '0'; + + s_req_p3(0) <= req_i(0) when(s_pri0 = "11") else '0'; + s_req_p3(1) <= req_i(1) when(s_pri1 = "11") else '0'; + s_req_p3(2) <= req_i(2) when(s_pri2 = "11") else '0'; + s_req_p3(3) <= req_i(3) when(s_pri3 = "11") else '0'; + s_req_p3(4) <= req_i(4) when(s_pri4 = "11") else '0'; + s_req_p3(5) <= req_i(5) when(s_pri5 = "11") else '0'; + s_req_p3(6) <= req_i(6) when(s_pri6 = "11") else '0'; + s_req_p3(7) <= req_i(7) when(s_pri7 = "11") else '0'; + + ARB0: wb_conmax_arb + port map( + clk_i => clk_i, + rst_i => rst_i, + + req_i => s_req_p0, + gnt_o => s_gnt_p0, + + next_i => '0' + ); + + ARB1: wb_conmax_arb + port map( + clk_i => clk_i, + rst_i => rst_i, + + req_i => s_req_p1, + gnt_o => s_gnt_p1, + + next_i => '0' + ); + + ARB2: wb_conmax_arb + port map( + clk_i => clk_i, + rst_i => rst_i, + + req_i => s_req_p2, + gnt_o => s_gnt_p2, + + next_i => '0' + ); + + ARB3: wb_conmax_arb + port map( + clk_i => clk_i, + rst_i => rst_i, + + req_i => s_req_p3, + gnt_o => s_gnt_p3, + + next_i => '0' + ); + + ----------------------------------------------- + --Final Master Select + s_sel1 <= s_gnt_p1 when( s_pri_out(0)='1' ) else + s_gnt_p0; + + s_sel2 <= s_gnt_p0 when( s_pri_out="00" ) else + s_gnt_p1 when( s_pri_out="01" ) else + s_gnt_p2 when( s_pri_out="10" ) else + s_gnt_p3; + + G4: if(g_pri_sel=0) generate + sel <= s_gnt_p0; + end generate; + + G5: if(g_pri_sel=1) generate + sel <= s_sel1; + end generate; + + G6: if(g_pri_sel/=0 and g_pri_sel/=1) generate + sel <= s_sel2; + end generate; + +end behavioral; diff --git a/modules/wishbone/wb_conmax/wb_conmax_pri_dec.vhd b/modules/wishbone/wb_conmax/wb_conmax_pri_dec.vhd new file mode 100644 index 0000000000000000000000000000000000000000..c16c9be10555b608eb9459c59288cdca6d56a6e0 --- /dev/null +++ b/modules/wishbone/wb_conmax/wb_conmax_pri_dec.vhd @@ -0,0 +1,91 @@ +------------------------------------------------------------------------------- +-- Title : Wishbone interconnect matrix for WR Core +-- Project : WhiteRabbit +------------------------------------------------------------------------------- +-- File : wb_conmax_pri_dec.vhd +-- Author : Grzegorz Daniluk +-- Company : Elproma +-- Created : 2011-02-12 +-- Last update: 2010-02-12 +-- Platform : FPGA-generics +-- Standard : VHDL +------------------------------------------------------------------------------- +-- Description: +-- Simple Master's priority encoder +-- +------------------------------------------------------------------------------- +-- Copyright (C) 2000-2002 Rudolf Usselmann +-- Copyright (c) 2011 Grzegorz Daniluk (VHDL port) +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2011-02-12 1.0 greg.d Created +------------------------------------------------------------------------------- +-- TODO: +-- Code optimization. (now it is more like dummy translation from Verilog) +-- (eg. <if..generate> instead of pri_out_d0 and pri_out_d1) +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity wb_conmax_pri_dec is + generic( + -- :=1 means 2 priority levels, :=2 means 4 priority levels + g_pri_sel : integer := 0 + ); + port( + valid_i : in std_logic; + pri_i : in std_logic_vector(1 downto 0); + pri_o : out std_logic_vector(3 downto 0) + ); +end wb_conmax_pri_dec; + +architecture behaviour of wb_conmax_pri_dec is + + signal pri_out_d0 : std_logic_vector(3 downto 0); + signal pri_out_d1 : std_logic_vector(3 downto 0); + +begin + + --4 priority levels + process(valid_i,pri_i) + begin + if( valid_i='0' ) then + pri_out_d1 <= "0001"; + elsif( pri_i="00" ) then + pri_out_d1 <= "0001"; + elsif( pri_i="01" ) then + pri_out_d1 <= "0010"; + elsif( pri_i="10" ) then + pri_out_d1 <= "0100"; + else + pri_out_d1 <= "1000"; + end if; + end process; + + --2 priority levels + process(valid_i, pri_i) + begin + if( valid_i='0' ) then + pri_out_d0 <= "0001"; + elsif( pri_i="00" ) then + pri_out_d0 <= "0001"; + else + pri_out_d0 <= "0010"; + end if; + end process; + + --select how many pririty levels + G1: if(g_pri_sel=0) generate + pri_o <= "0000"; + end generate; + G2: if(g_pri_sel=1) generate + pri_o <= pri_out_d0; + end generate; + G3: if(g_pri_sel/=0 and g_pri_sel/=1) generate + pri_o <= pri_out_d1; + end generate; + +end behaviour; diff --git a/modules/wishbone/wb_conmax/wb_conmax_pri_enc.vhd b/modules/wishbone/wb_conmax/wb_conmax_pri_enc.vhd new file mode 100644 index 0000000000000000000000000000000000000000..193c6b579668fdb39a669519b0f67e50ea0713d6 --- /dev/null +++ b/modules/wishbone/wb_conmax/wb_conmax_pri_enc.vhd @@ -0,0 +1,193 @@ +------------------------------------------------------------------------------- +-- Title : Wishbone interconnect matrix for WR Core +-- Project : WhiteRabbit +------------------------------------------------------------------------------- +-- File : wb_conmax_pri_enc.vhd +-- Author : Grzegorz Daniluk +-- Company : Elproma +-- Created : 2011-02-12 +-- Last update: 2010-02-12 +-- Platform : FPGA-generics +-- Standard : VHDL +------------------------------------------------------------------------------- +-- Description: +-- The set of priority encoders for all Master interfaces. +-- +------------------------------------------------------------------------------- +-- Copyright (C) 2000-2002 Rudolf Usselmann +-- Copyright (c) 2011 Grzegorz Daniluk (VHDL port) +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2011-02-12 1.0 greg.d Created +------------------------------------------------------------------------------- +-- TODO: +-- Code optimization. (now it is more like dummy translation from Verilog) +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity wb_conmax_pri_enc is + generic( + -- :=1 means 2 priority levels, :=2 means 4 priority levels + g_pri_sel : integer := 0 + ); + port( + valid_i : in std_logic_vector(7 downto 0); + + pri0_i : in std_logic_vector(1 downto 0); + pri1_i : in std_logic_vector(1 downto 0); + pri2_i : in std_logic_vector(1 downto 0); + pri3_i : in std_logic_vector(1 downto 0); + pri4_i : in std_logic_vector(1 downto 0); + pri5_i : in std_logic_vector(1 downto 0); + pri6_i : in std_logic_vector(1 downto 0); + pri7_i : in std_logic_vector(1 downto 0); + + pri_o : out std_logic_vector(1 downto 0) + ); +end wb_conmax_pri_enc; + +architecture behaviour of wb_conmax_pri_enc is + + component wb_conmax_pri_dec is + generic( + -- :=1 means 2 priority levels, :=2 means 4 priority levels + g_pri_sel : integer := 0 + ); + port( + valid_i : in std_logic; + pri_i : in std_logic_vector(1 downto 0); + pri_o : out std_logic_vector(3 downto 0) + ); + end component; + + signal s_pri0_o : std_logic_vector(3 downto 0); + signal s_pri1_o : std_logic_vector(3 downto 0); + signal s_pri2_o : std_logic_vector(3 downto 0); + signal s_pri3_o : std_logic_vector(3 downto 0); + signal s_pri4_o : std_logic_vector(3 downto 0); + signal s_pri5_o : std_logic_vector(3 downto 0); + signal s_pri6_o : std_logic_vector(3 downto 0); + signal s_pri7_o : std_logic_vector(3 downto 0); + + signal s_pritmp_o : std_logic_vector(3 downto 0); + + signal s_pri_out0 : std_logic_vector(1 downto 0); + signal s_pri_out1 : std_logic_vector(1 downto 0); + + +begin + + PD0: wb_conmax_pri_dec + generic map( + g_pri_sel => g_pri_sel + ) + port map( + valid_i => valid_i(0), + pri_i => pri0_i, + pri_o => s_pri0_o + ); + + PD1: wb_conmax_pri_dec + generic map( + g_pri_sel => g_pri_sel + ) + port map( + valid_i => valid_i(1), + pri_i => pri1_i, + pri_o => s_pri1_o + ); + + PD2: wb_conmax_pri_dec + generic map( + g_pri_sel => g_pri_sel + ) + port map( + valid_i => valid_i(2), + pri_i => pri2_i, + pri_o => s_pri2_o + ); + + PD3: wb_conmax_pri_dec + generic map( + g_pri_sel => g_pri_sel + ) + port map( + valid_i => valid_i(3), + pri_i => pri3_i, + pri_o => s_pri3_o + ); + + PD4: wb_conmax_pri_dec + generic map( + g_pri_sel => g_pri_sel + ) + port map( + valid_i => valid_i(4), + pri_i => pri4_i, + pri_o => s_pri4_o + ); + + PD5: wb_conmax_pri_dec + generic map( + g_pri_sel => g_pri_sel + ) + port map( + valid_i => valid_i(5), + pri_i => pri5_i, + pri_o => s_pri5_o + ); + + PD6: wb_conmax_pri_dec + generic map( + g_pri_sel => g_pri_sel + ) + port map( + valid_i => valid_i(6), + pri_i => pri6_i, + pri_o => s_pri6_o + ); + + PD7: wb_conmax_pri_dec + generic map( + g_pri_sel => g_pri_sel + ) + port map( + valid_i => valid_i(7), + pri_i => pri7_i, + pri_o => s_pri7_o + ); + + + s_pritmp_o <= s_pri0_o or s_pri1_o or s_pri2_o or s_pri3_o or s_pri4_o or + s_pri5_o or s_pri6_o or s_pri7_o; + + --4 priority levels + s_pri_out1 <= "11" when ( s_pritmp_o(3)='1' ) else + "10" when ( s_pritmp_o(2)='1' ) else + "01" when ( s_pritmp_o(1)='1' ) else + "00"; + + --2 priority levels + s_pri_out0 <= "01" when ( s_pritmp_o(1)='1' ) else + "00"; + + + + G1: if (g_pri_sel=0) generate + pri_o <= "00"; + end generate; + G2: if (g_pri_sel=1) generate + pri_o <= s_pri_out0; + end generate; + G3: if (g_pri_sel/=0 and g_pri_sel/=1) generate + pri_o <= s_pri_out1; + end generate; + + +end behaviour; + + diff --git a/modules/wishbone/wb_conmax/wb_conmax_rf.vhd b/modules/wishbone/wb_conmax/wb_conmax_rf.vhd new file mode 100644 index 0000000000000000000000000000000000000000..430b17e0b1fe8ea92740910aef28957efeb133b7 --- /dev/null +++ b/modules/wishbone/wb_conmax/wb_conmax_rf.vhd @@ -0,0 +1,167 @@ +------------------------------------------------------------------------------- +-- Title : Wishbone interconnect matrix for WR Core +-- Project : WhiteRabbit +------------------------------------------------------------------------------- +-- File : wb_conmax_rf.vhd +-- Author : Grzegorz Daniluk +-- Company : Elproma +-- Created : 2011-02-12 +-- Last update: 2010-02-16 +-- Platform : FPGA-generics +-- Standard : VHDL +------------------------------------------------------------------------------- +-- Description: +-- Register File - consists of 16 registers. Each stores configuration for +-- different Slave. +-- Each of those 16 registers is the Slave's personal priority register, +-- where the priorities for each Master are stored. The Register File is +-- accessible from Master through Slave 15th interface. +-- +------------------------------------------------------------------------------- +-- Copyright (C) 2000-2002 Rudolf Usselmann +-- Copyright (c) 2011 Grzegorz Daniluk (VHDL port) +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2011-02-12 1.0 greg.d Created +-- 2011-02-16 1.1 greg.d Using generates and types +------------------------------------------------------------------------------- +-- TODO: +-- Code optimization. (now it is more like dummy translation from Verilog) +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.wbconmax_pkg.all; + +entity wb_conmax_rf is + generic( + g_rf_addr : integer range 0 to 15 := 15 --0xF + ); + port( + clk_i : in std_logic; + rst_i : in std_logic; + + --Internal WB interface + int_wb_i : in t_wb_i; + int_wb_o : out t_wb_o; + --External WB interface + ext_wb_i : in t_wb_o; + ext_wb_o : out t_wb_i; + + --Configuration regs + conf_o : out t_rf_conf + ); +end wb_conmax_rf; + +architecture behaviour of wb_conmax_rf is + + signal s_rf_sel : std_logic; + signal s_rf_dout : std_logic_vector(15 downto 0); + signal s_rf_ack : std_logic; + signal s_rf_we : std_logic; + + signal s_conf : t_rf_conf; + + signal s_rf_addr : std_logic_vector(3 downto 0); +begin + + --Register File select logic + s_rf_addr <= std_logic_vector(to_unsigned(g_rf_addr, 4)); + s_rf_sel <= int_wb_i.cyc and int_wb_i.stb when(int_wb_i.addr(c_aw-5 downto c_aw-8) = s_rf_addr ) + else '0'; + + + --Register File logic + process(clk_i) + begin + if(clk_i'event and clk_i='1') then + s_rf_we <= s_rf_sel and int_wb_i.we and not(s_rf_we); + s_rf_ack <= s_rf_sel and not(s_rf_ack); + end if; + end process; + + + --Write logic + process(clk_i) + begin + if(clk_i'event and clk_i='1') then + if(rst_i = '1') then + s_conf <= (others=> (others=>'0')); + elsif(s_rf_we='1') then + + if (int_wb_i.addr(5 downto 2)=x"0") then s_conf(0) <= int_wb_i.data(15 downto 0); + elsif(int_wb_i.addr(5 downto 2)=x"1") then s_conf(1) <= int_wb_i.data(15 downto 0); + elsif(int_wb_i.addr(5 downto 2)=x"2") then s_conf(2) <= int_wb_i.data(15 downto 0); + elsif(int_wb_i.addr(5 downto 2)=x"3") then s_conf(3) <= int_wb_i.data(15 downto 0); + elsif(int_wb_i.addr(5 downto 2)=x"4") then s_conf(4) <= int_wb_i.data(15 downto 0); + elsif(int_wb_i.addr(5 downto 2)=x"5") then s_conf(5) <= int_wb_i.data(15 downto 0); + elsif(int_wb_i.addr(5 downto 2)=x"6") then s_conf(6) <= int_wb_i.data(15 downto 0); + elsif(int_wb_i.addr(5 downto 2)=x"7") then s_conf(7) <= int_wb_i.data(15 downto 0); + elsif(int_wb_i.addr(5 downto 2)=x"8") then s_conf(8) <= int_wb_i.data(15 downto 0); + elsif(int_wb_i.addr(5 downto 2)=x"9") then s_conf(9) <= int_wb_i.data(15 downto 0); + elsif(int_wb_i.addr(5 downto 2)=x"a") then s_conf(10) <= int_wb_i.data(15 downto 0); + elsif(int_wb_i.addr(5 downto 2)=x"b") then s_conf(11) <= int_wb_i.data(15 downto 0); + elsif(int_wb_i.addr(5 downto 2)=x"c") then s_conf(12) <= int_wb_i.data(15 downto 0); + elsif(int_wb_i.addr(5 downto 2)=x"d") then s_conf(13) <= int_wb_i.data(15 downto 0); + elsif(int_wb_i.addr(5 downto 2)=x"e") then s_conf(14) <= int_wb_i.data(15 downto 0); + elsif(int_wb_i.addr(5 downto 2)=x"f") then s_conf(15) <= int_wb_i.data(15 downto 0); + end if; + + end if; + end if; + end process; + + + --Read logic + process(clk_i) + begin + if(clk_i'event and clk_i='1') then + if(s_rf_sel='0') then + s_rf_dout <= x"0000"; + else + + if ( int_wb_i.addr(5 downto 2)=x"0" ) then s_rf_dout <= s_conf(0); + elsif( int_wb_i.addr(5 downto 2)=x"1" ) then s_rf_dout <= s_conf(1); + elsif( int_wb_i.addr(5 downto 2)=x"2" ) then s_rf_dout <= s_conf(2); + elsif( int_wb_i.addr(5 downto 2)=x"3" ) then s_rf_dout <= s_conf(3); + elsif( int_wb_i.addr(5 downto 2)=x"4" ) then s_rf_dout <= s_conf(4); + elsif( int_wb_i.addr(5 downto 2)=x"5" ) then s_rf_dout <= s_conf(5); + elsif( int_wb_i.addr(5 downto 2)=x"6" ) then s_rf_dout <= s_conf(6); + elsif( int_wb_i.addr(5 downto 2)=x"7" ) then s_rf_dout <= s_conf(7); + elsif( int_wb_i.addr(5 downto 2)=x"8" ) then s_rf_dout <= s_conf(8); + elsif( int_wb_i.addr(5 downto 2)=x"9" ) then s_rf_dout <= s_conf(9); + elsif( int_wb_i.addr(5 downto 2)=x"A" ) then s_rf_dout <= s_conf(10); + elsif( int_wb_i.addr(5 downto 2)=x"B" ) then s_rf_dout <= s_conf(11); + elsif( int_wb_i.addr(5 downto 2)=x"C" ) then s_rf_dout <= s_conf(12); + elsif( int_wb_i.addr(5 downto 2)=x"D" ) then s_rf_dout <= s_conf(13); + elsif( int_wb_i.addr(5 downto 2)=x"E" ) then s_rf_dout <= s_conf(14); + elsif( int_wb_i.addr(5 downto 2)=x"F" ) then s_rf_dout <= s_conf(15); + end if; + + end if; + end if; + end process; + + + --Register File bypass logic + ext_wb_o.addr <= int_wb_i.addr; + ext_wb_o.sel <= int_wb_i.sel; + ext_wb_o.data <= int_wb_i.data; + ext_wb_o.cyc <= int_wb_i.cyc when(s_rf_sel='0') else '0'; + ext_wb_o.stb <= int_wb_i.stb; + ext_wb_o.we <= int_wb_i.we; + + int_wb_o.data <= ( (c_dw-1 downto 16 => '0') & s_rf_dout ) when(s_rf_sel='1') + else ext_wb_i.data; + int_wb_o.ack <= s_rf_ack when(s_rf_sel='1') else ext_wb_i.ack; + int_wb_o.err <= '0' when(s_rf_sel='1') else ext_wb_i.err; + int_wb_o.rty <= '0' when(s_rf_sel='1') else ext_wb_i.rty; + + conf_o <= s_conf; + +end behaviour; diff --git a/modules/wishbone/wb_conmax/wb_conmax_slave_if.vhd b/modules/wishbone/wb_conmax/wb_conmax_slave_if.vhd new file mode 100644 index 0000000000000000000000000000000000000000..945f85aefde0759b01d41a1a3bfbcb46e6e3a79e --- /dev/null +++ b/modules/wishbone/wb_conmax/wb_conmax_slave_if.vhd @@ -0,0 +1,226 @@ +------------------------------------------------------------------------------- +-- Title : Wishbone interconnect matrix for WR Core +-- Project : WhiteRabbit +------------------------------------------------------------------------------- +-- File : wb_conmax_slave_if.vhd +-- Author : Grzegorz Daniluk +-- Company : Elproma +-- Created : 2011-02-12 +-- Last update: 2010-02-16 +-- Platform : FPGA-generics +-- Standard : VHDL +------------------------------------------------------------------------------- +-- Description: +-- Full interface for a single Wishbone Slave. Consists of WB Master interface, +-- Prioritizing Arbiter and multiplexer for selecting appropriate Master. +-- +------------------------------------------------------------------------------- +-- Copyright (C) 2000-2002 Rudolf Usselmann +-- Copyright (c) 2011 Grzegorz Daniluk (VHDL port) +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2011-02-12 1.0 greg.d Created +-- 2011-02-16 1.1 greg.d Using generates and types +------------------------------------------------------------------------------- +-- TODO: +-- Code optimization. (now it is more like dummy translation from Verilog) +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.wbconmax_pkg.all; + +entity wb_conmax_slave_if is + generic( + g_pri_sel : integer := 2 + ); + port( + clk_i : in std_logic; + rst_i : in std_logic; + conf_i : in std_logic_vector(15 downto 0); + + --Slave interface + wb_slave_i : in t_wb_o; + wb_slave_o : out t_wb_i; + + --Master (0 to 7) interfaces + wb_masters_i : in t_conmax_masters_i; + wb_masters_o : out t_conmax_masters_o + ); +end wb_conmax_slave_if; + +architecture bahaviour of wb_conmax_slave_if is + + component wb_conmax_arb is + port( + clk_i : in std_logic; + rst_i : in std_logic; + + req_i : in std_logic_vector(7 downto 0); + gnt_o : out std_logic_vector(2 downto 0); + + next_i : in std_logic + ); + end component; + + component wb_conmax_msel is + generic( + g_pri_sel : integer := 0 + ); + port( + clk_i : in std_logic; + rst_i : in std_logic; + + conf_i : in std_logic_vector(15 downto 0); + req_i : in std_logic_vector(7 downto 0); + next_i : in std_logic; + + sel : out std_logic_vector(2 downto 0) + ); + end component; + + + + signal s_wb_cyc_o : std_logic; + signal s_msel_simple, s_msel_pe, s_msel : std_logic_vector(2 downto 0); + signal s_next : std_logic; + signal s_mcyc : std_logic_vector(7 downto 0); + signal s_arb_req_i : std_logic_vector(7 downto 0); + +begin + + wb_slave_o.cyc <= s_wb_cyc_o; + + process(clk_i) + begin + if(clk_i'event and clk_i='1') then + s_next <= not(s_wb_cyc_o); + end if; + end process; + + s_arb_req_i <= wb_masters_i(7).cyc & wb_masters_i(6).cyc & wb_masters_i(5).cyc & + wb_masters_i(4).cyc & wb_masters_i(3).cyc & wb_masters_i(2).cyc & + wb_masters_i(1).cyc & wb_masters_i(0).cyc; + --Prioritizing Arbiter + ARB: wb_conmax_arb + port map( + clk_i => clk_i, + rst_i => rst_i, + + req_i => s_arb_req_i, + gnt_o => s_msel_simple, + next_i=> '0' --no round robin + ); + + MSEL: wb_conmax_msel + generic map( + g_pri_sel => g_pri_sel + ) + port map( + clk_i => clk_i, + rst_i => rst_i, + + conf_i => conf_i, + req_i => s_arb_req_i, + next_i => s_next, + sel => s_msel_pe + ); + + G1: if(g_pri_sel=0) generate + s_msel <= s_msel_simple; + end generate; + G2: if(g_pri_sel/=0) generate + s_msel <= s_msel_pe; + end generate; + + + ------------------------------------- + --Address & Data Pass + wb_slave_o.addr <= wb_masters_i(0).addr when(s_msel="000") else + wb_masters_i(1).addr when(s_msel="001") else + wb_masters_i(2).addr when(s_msel="010") else + wb_masters_i(3).addr when(s_msel="011") else + wb_masters_i(4).addr when(s_msel="100") else + wb_masters_i(5).addr when(s_msel="101") else + wb_masters_i(6).addr when(s_msel="110") else + wb_masters_i(7).addr when(s_msel="111") else + (others=>'0'); + + wb_slave_o.sel <= wb_masters_i(0).sel when(s_msel="000") else + wb_masters_i(1).sel when(s_msel="001") else + wb_masters_i(2).sel when(s_msel="010") else + wb_masters_i(3).sel when(s_msel="011") else + wb_masters_i(4).sel when(s_msel="100") else + wb_masters_i(5).sel when(s_msel="101") else + wb_masters_i(6).sel when(s_msel="110") else + wb_masters_i(7).sel when(s_msel="111") else + (others=>'0'); + + wb_slave_o.data <= wb_masters_i(0).data when(s_msel="000") else + wb_masters_i(1).data when(s_msel="001") else + wb_masters_i(2).data when(s_msel="010") else + wb_masters_i(3).data when(s_msel="011") else + wb_masters_i(4).data when(s_msel="100") else + wb_masters_i(5).data when(s_msel="101") else + wb_masters_i(6).data when(s_msel="110") else + wb_masters_i(7).data when(s_msel="111") else + (others=>'0'); + + G_OUT: for I in 0 to 7 generate + wb_masters_o(I).data <= wb_slave_i.data; + wb_masters_o(I).ack <= wb_slave_i.ack when(s_msel= std_logic_vector( + to_unsigned(I, 3)) ) else '0'; + wb_masters_o(I).err <= wb_slave_i.err when(s_msel= std_logic_vector( + to_unsigned(I, 3)) ) else '0'; + wb_masters_o(I).rty <= wb_slave_i.rty when(s_msel= std_logic_vector( + to_unsigned(I, 3)) ) else '0'; + end generate; + + ------------------------------------ + --Control Signal Pass + wb_slave_o.we <= wb_masters_i(0).we when(s_msel="000") else + wb_masters_i(1).we when(s_msel="001") else + wb_masters_i(2).we when(s_msel="010") else + wb_masters_i(3).we when(s_msel="011") else + wb_masters_i(4).we when(s_msel="100") else + wb_masters_i(5).we when(s_msel="101") else + wb_masters_i(6).we when(s_msel="110") else + wb_masters_i(7).we when(s_msel="111") else + '0'; + + process(clk_i) + begin + if(clk_i'event and clk_i='1') then + s_mcyc(7 downto 0) <= wb_masters_i(7).cyc & wb_masters_i(6).cyc & + wb_masters_i(5).cyc & wb_masters_i(4).cyc & wb_masters_i(3).cyc & + wb_masters_i(2).cyc & wb_masters_i(1).cyc & wb_masters_i(0).cyc; + + end if; + end process; + + s_wb_cyc_o <= wb_masters_i(0).cyc and s_mcyc(0) when(s_msel="000") else + wb_masters_i(1).cyc and s_mcyc(1) when(s_msel="001") else + wb_masters_i(2).cyc and s_mcyc(2) when(s_msel="010") else + wb_masters_i(3).cyc and s_mcyc(3) when(s_msel="011") else + wb_masters_i(4).cyc and s_mcyc(4) when(s_msel="100") else + wb_masters_i(5).cyc and s_mcyc(5) when(s_msel="101") else + wb_masters_i(6).cyc and s_mcyc(6) when(s_msel="110") else + wb_masters_i(7).cyc and s_mcyc(7) when(s_msel="111") else + '0'; + + wb_slave_o.stb <= wb_masters_i(0).stb when(s_msel="000") else + wb_masters_i(1).stb when(s_msel="001") else + wb_masters_i(2).stb when(s_msel="010") else + wb_masters_i(3).stb when(s_msel="011") else + wb_masters_i(4).stb when(s_msel="100") else + wb_masters_i(5).stb when(s_msel="101") else + wb_masters_i(6).stb when(s_msel="110") else + wb_masters_i(7).stb when(s_msel="111") else + '0'; + +end bahaviour; diff --git a/modules/wishbone/wb_conmax/wb_conmax_top.vhd b/modules/wishbone/wb_conmax/wb_conmax_top.vhd new file mode 100644 index 0000000000000000000000000000000000000000..377485eb8f71e61afdb550748e09e0e698330af2 --- /dev/null +++ b/modules/wishbone/wb_conmax/wb_conmax_top.vhd @@ -0,0 +1,323 @@ +------------------------------------------------------------------------------- +-- Title : Wishbone interconnect matrix for WR Core +-- Project : WhiteRabbit +------------------------------------------------------------------------------- +-- File : wb_conmax_top.vhd +-- Author : Grzegorz Daniluk +-- Company : Elproma +-- Created : 2011-02-12 +-- Last update: 2010-02-16 +-- Platform : FPGA-generics +-- Standard : VHDL +------------------------------------------------------------------------------- +-- Description: +-- Wishbone Interconnect Matrix, up to 8 Masters and 16 Slaves. Features +-- prioritized arbiter inside each Slave Interface (1, 2 of 4 priority levels). +-- Allows the parallel communication between masters and slaves on +-- different interfaces. +-- It is the WISHBONE Conmax IP Core from opencores.org rewritten in VHDL (from +-- Verilog) with some code optimalization. +-- +------------------------------------------------------------------------------- +-- Copyright (C) 2000-2002 Rudolf Usselmann +-- Copyright (c) 2011 Grzegorz Daniluk (VHDL port) +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2011-02-12 1.0 greg.d Created +-- 2011-02-16 1.1 greg.d Using generates and types +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +library work; +use work.wbconmax_pkg.all; + +entity wb_conmax_top is + generic( + g_rf_addr : integer range 0 to 15 := 15 --0xf + ); + port( + clk_i : std_logic; + rst_i : std_logic; + + wb_masters_i : in t_conmax_masters_i; + wb_masters_o : out t_conmax_masters_o; + wb_slaves_i : in t_conmax_slaves_i; + wb_slaves_o : out t_conmax_slaves_o + ); +end wb_conmax_top; + +architecture struct of wb_conmax_top is + + component wb_conmax_master_if is + port( + clk_i : in std_logic; + rst_i : in std_logic; + + --Master interface + wb_master_i : in t_wb_i; + wb_master_o : out t_wb_o; + + --Slaves(0 to 15) interface + wb_slaves_i : in t_conmax_slaves_i; + wb_slaves_o : out t_conmax_slaves_o + ); + end component; + + component wb_conmax_slave_if is + generic( + g_pri_sel : integer := 2 + ); + port( + clk_i : in std_logic; + rst_i : in std_logic; + conf_i : in std_logic_vector(15 downto 0); + + --Slave interface + wb_slave_i : in t_wb_o; + wb_slave_o : out t_wb_i; + + --Master (0 to 7) interfaces + wb_masters_i : in t_conmax_masters_i; + wb_masters_o : out t_conmax_masters_o + ); + end component; + + component wb_conmax_rf is + generic( + g_rf_addr : integer range 0 to 15 := 15 --0xF + ); + port( + clk_i : in std_logic; + rst_i : in std_logic; + + --Internal WB interface + int_wb_i : in t_wb_i; + int_wb_o : out t_wb_o; + --External WB interface + ext_wb_i : in t_wb_o; + ext_wb_o : out t_wb_i; + + --Configuration regs + conf_o : out t_rf_conf + ); + end component; + + + signal intwb_s15_i : t_wb_o; + signal intwb_s15_o : t_wb_i; + + --M0Sx + signal m0_slaves_i : t_conmax_slaves_i; + signal m0_slaves_o : t_conmax_slaves_o; + signal m1_slaves_i : t_conmax_slaves_i; + signal m1_slaves_o : t_conmax_slaves_o; + signal m2_slaves_i : t_conmax_slaves_i; + signal m2_slaves_o : t_conmax_slaves_o; + signal m3_slaves_i : t_conmax_slaves_i; + signal m3_slaves_o : t_conmax_slaves_o; + signal m4_slaves_i : t_conmax_slaves_i; + signal m4_slaves_o : t_conmax_slaves_o; + signal m5_slaves_i : t_conmax_slaves_i; + signal m5_slaves_o : t_conmax_slaves_o; + signal m6_slaves_i : t_conmax_slaves_i; + signal m6_slaves_o : t_conmax_slaves_o; + signal m7_slaves_i : t_conmax_slaves_i; + signal m7_slaves_o : t_conmax_slaves_o; + + + signal s_conf : t_rf_conf; + + signal s15_wb_masters_i : t_conmax_masters_i; + signal s15_wb_masters_o : t_conmax_masters_o; + +begin + + --Master interfaces + M0: wb_conmax_master_if + port map( + clk_i => clk_i, + rst_i => rst_i, + + --Master interface + wb_master_i => wb_masters_i(0), + wb_master_o => wb_masters_o(0), + --Slaves(0 to 15) interface + wb_slaves_i => m0_slaves_i, + wb_slaves_o => m0_slaves_o + ); + + M1: wb_conmax_master_if + port map( + clk_i => clk_i, + rst_i => rst_i, + + wb_master_i => wb_masters_i(1), + wb_master_o => wb_masters_o(1), + wb_slaves_i => m1_slaves_i, + wb_slaves_o => m1_slaves_o + ); + + M2: wb_conmax_master_if + port map( + clk_i => clk_i, + rst_i => rst_i, + + wb_master_i => wb_masters_i(2), + wb_master_o => wb_masters_o(2), + wb_slaves_i => m2_slaves_i, + wb_slaves_o => m2_slaves_o + ); + + M3: wb_conmax_master_if + port map( + clk_i => clk_i, + rst_i => rst_i, + + wb_master_i => wb_masters_i(3), + wb_master_o => wb_masters_o(3), + wb_slaves_i => m3_slaves_i, + wb_slaves_o => m3_slaves_o + ); + + M4: wb_conmax_master_if + port map( + clk_i => clk_i, + rst_i => rst_i, + + wb_master_i => wb_masters_i(4), + wb_master_o => wb_masters_o(4), + wb_slaves_i => m4_slaves_i, + wb_slaves_o => m4_slaves_o + ); + + M5: wb_conmax_master_if + port map( + clk_i => clk_i, + rst_i => rst_i, + + wb_master_i => wb_masters_i(5), + wb_master_o => wb_masters_o(5), + wb_slaves_i => m5_slaves_i, + wb_slaves_o => m5_slaves_o + ); + + M6: wb_conmax_master_if + port map( + clk_i => clk_i, + rst_i => rst_i, + + wb_master_i => wb_masters_i(6), + wb_master_o => wb_masters_o(6), + wb_slaves_i => m6_slaves_i, + wb_slaves_o => m6_slaves_o + ); + + M7: wb_conmax_master_if + port map( + clk_i => clk_i, + rst_i => rst_i, + + wb_master_i => wb_masters_i(7), + wb_master_o => wb_masters_o(7), + wb_slaves_i => m7_slaves_i, + wb_slaves_o => m7_slaves_o + ); + + -------------------------------------------------- + --Slave interfaces + S_GEN: for I in 0 to 14 generate + SLV: wb_conmax_slave_if + generic map( + g_pri_sel => g_pri_sel(I) + ) + port map( + clk_i => clk_i, + rst_i => rst_i, + conf_i => s_conf(I), + + --Slave interface + wb_slave_i => wb_slaves_i(I), + wb_slave_o => wb_slaves_o(I), + + --Interfaces to masters + wb_masters_i(0) => m0_slaves_o(I), + wb_masters_i(1) => m1_slaves_o(I), + wb_masters_i(2) => m2_slaves_o(I), + wb_masters_i(3) => m3_slaves_o(I), + wb_masters_i(4) => m4_slaves_o(I), + wb_masters_i(5) => m5_slaves_o(I), + wb_masters_i(6) => m6_slaves_o(I), + wb_masters_i(7) => m7_slaves_o(I), + + wb_masters_o(0) => m0_slaves_i(I), + wb_masters_o(1) => m1_slaves_i(I), + wb_masters_o(2) => m2_slaves_i(I), + wb_masters_o(3) => m3_slaves_i(I), + wb_masters_o(4) => m4_slaves_i(I), + wb_masters_o(5) => m5_slaves_i(I), + wb_masters_o(6) => m6_slaves_i(I), + wb_masters_o(7) => m7_slaves_i(I) + ); + end generate; + + + s15_wb_masters_i(0) <= m0_slaves_o(15); + s15_wb_masters_i(1) <= m1_slaves_o(15); + s15_wb_masters_i(2) <= m2_slaves_o(15); + s15_wb_masters_i(3) <= m3_slaves_o(15); + s15_wb_masters_i(4) <= m4_slaves_o(15); + s15_wb_masters_i(5) <= m5_slaves_o(15); + s15_wb_masters_i(6) <= m6_slaves_o(15); + s15_wb_masters_i(7) <= m7_slaves_o(15); + + m0_slaves_i(15) <= s15_wb_masters_o(0); + m1_slaves_i(15) <= s15_wb_masters_o(1); + m2_slaves_i(15) <= s15_wb_masters_o(2); + m3_slaves_i(15) <= s15_wb_masters_o(3); + m4_slaves_i(15) <= s15_wb_masters_o(4); + m5_slaves_i(15) <= s15_wb_masters_o(5); + m6_slaves_i(15) <= s15_wb_masters_o(6); + m7_slaves_i(15) <= s15_wb_masters_o(7); + + + SLV15: wb_conmax_slave_if + generic map( + g_pri_sel => g_pri_sel(15) + ) + port map( + clk_i => clk_i, + rst_i => rst_i, + conf_i => s_conf(15), + + --Slave interface + wb_slave_i => intwb_s15_i, + wb_slave_o => intwb_s15_o, + + --Interfaces to masters + wb_masters_i => s15_wb_masters_i, + wb_masters_o => s15_wb_masters_o + ); + + --------------------------------------- + --Register File + + RF: wb_conmax_rf + generic map( + g_rf_addr => g_rf_addr + ) + port map( + clk_i => clk_i, + rst_i => rst_i, + + int_wb_i => intwb_s15_o, + int_wb_o => intwb_s15_i, + ext_wb_i => wb_slaves_i(15), + ext_wb_o => wb_slaves_o(15), + + conf_o => s_conf + ); + +end struct; diff --git a/modules/wishbone/wb_conmax/wbconmax_pkg.vhd b/modules/wishbone/wb_conmax/wbconmax_pkg.vhd new file mode 100644 index 0000000000000000000000000000000000000000..a3497ce2759299a12ab82d5163b4834df1c7d689 --- /dev/null +++ b/modules/wishbone/wb_conmax/wbconmax_pkg.vhd @@ -0,0 +1,63 @@ +------------------------------------------------------------------------------- +-- Title : Wishbone interconnect matrix for WR Core +-- Project : WhiteRabbit +------------------------------------------------------------------------------- +-- File : wbconmax_pkg.vhd +-- Author : Grzegorz Daniluk +-- Company : Elproma +-- Created : 2011-02-16 +-- Last update: 2010-02-16 +-- Platform : FPGA-generics +-- Standard : VHDL +------------------------------------------------------------------------------- +-- Description: +-- Package for WB interconnect matrix. Defines basic constants and types used +-- to simplify WB interface connections. +------------------------------------------------------------------------------- +-- Copyright (c) 2011 Grzegorz Daniluk +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2011-02-16 1.1 greg.d Using generates and types +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +package wbconmax_pkg is + + type t_rf_conf is array(0 to 15) of std_logic_vector(15 downto 0); + + constant c_dw : integer := 32; --data width + constant c_aw : integer := 18; --address width = max 14b (for dpram) + 4b + --for wb_intercom (Mst selects Slave) + constant c_sw : integer := 4; -- c_dw/8 + + --g_pri_selx := 0 (1 priority level), 1 (2 pri levels) or 2 (4 pri levels). + type t_pri_sels is array(0 to 15) of integer range 0 to 3; + constant g_pri_sel : t_pri_sels := (2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); + + --as in original WB conmax spec and implementation, those are + --inputs fed by WB Master from outside + type t_wb_i is record + data : std_logic_vector(c_dw-1 downto 0); + addr : std_logic_vector(c_aw-1 downto 0); + sel : std_logic_vector(c_sw-1 downto 0); + we : std_logic; + cyc : std_logic; + stb : std_logic; + end record; + + type t_wb_o is record + data : std_logic_vector(c_dw-1 downto 0); + ack : std_logic; + err : std_logic; + rty : std_logic; + end record; + + type t_conmax_masters_i is array(0 to 7) of t_wb_i; + type t_conmax_masters_o is array(0 to 7) of t_wb_o; + type t_conmax_slaves_i is array(0 to 15) of t_wb_o; + type t_conmax_slaves_o is array(0 to 15) of t_wb_i; + +end wbconmax_pkg; diff --git a/modules/wishbone/wb_gpio_port/manifest.py b/modules/wishbone/wb_gpio_port/manifest.py new file mode 100644 index 0000000000000000000000000000000000000000..cd4aae4f47d29d26476e0b1ebf6f0a232f28ade5 --- /dev/null +++ b/modules/wishbone/wb_gpio_port/manifest.py @@ -0,0 +1 @@ +files = ["wb_gpio_port.vhd"]; \ No newline at end of file diff --git a/modules/wishbone/wb_gpio_port/wb_gpio_port.vhd b/modules/wishbone/wb_gpio_port/wb_gpio_port.vhd new file mode 100644 index 0000000000000000000000000000000000000000..5f5ddbb490e0394ad8056f55cf92df25b34ac00a --- /dev/null +++ b/modules/wishbone/wb_gpio_port/wb_gpio_port.vhd @@ -0,0 +1,147 @@ +------------------------------------------------------------------------------ +-- Title : Wishbone GPIO port +-- Project : White Rabbit Switch +------------------------------------------------------------------------------ +-- Author : Tomasz Wlostowski +-- Company : CERN BE-Co-HT +-- Created : 2010-05-18 +-- Last update: 2011-04-06 +-- Platform : FPGA-generic +-- Standard : VHDL'87 +------------------------------------------------------------------------------- +-- Description: Bidirectional GPIO port of configurable width (1 to 32 bits). +------------------------------------------------------------------------------- +-- Copyright (c) 2010 Tomasz Wlostowski +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2010-05-18 1.0 twlostow Created +------------------------------------------------------------------------------- + +library ieee; + +use ieee.std_logic_1164.all; +use ieee.std_logic_arith.all; + +library work; + +use work.wishbone_pkg.all; +use work.common_components.all; + +entity wb_gpio_port is + generic(g_num_pins : natural := 8 -- number of GPIO pins + ); + port( +-- System reset, active low + sys_rst_n_i : in std_logic; + +------------------------------------------------------------------------------- +-- Wishbone bus +------------------------------------------------------------------------------- + + wb_clk_i : in std_logic; + wb_sel_i : in std_logic; + wb_cyc_i : in std_logic; + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_addr_i : in std_logic_vector(2 downto 0); + wb_data_i : in std_logic_vector(31 downto 0); + wb_data_o : out std_logic_vector(31 downto 0); + wb_ack_o : out std_logic; + +-- GPIO pin vector + gpio_b : inout std_logic_vector(g_num_pins-1 downto 0) + ); +end wb_gpio_port; + + +architecture behavioral of wb_gpio_port is + + constant c_GPIO_REG_CODR : std_logic_vector(2 downto 0) := "000"; -- *reg* clear output register + constant c_GPIO_REG_SODR : std_logic_vector(2 downto 0) := "001"; -- *reg* set output register + constant c_GPIO_REG_DDR : std_logic_vector(2 downto 0) := "010"; -- *reg* data direction register + constant c_GPIO_REG_PSR : std_logic_vector(2 downto 0) := "011"; -- *reg* pin state register + + + signal out_reg, in_reg, dir_reg : std_logic_vector(g_num_pins-1 downto 0); + signal gpio_in_synced : std_logic_vector(g_num_pins-1 downto 0); + signal ack_int : std_logic; + +begin + + + GEN_SYNC_FFS : for i in 0 to g_num_pins-1 generate + INPUT_SYNC : sync_ffs + generic map ( + g_sync_edge => "positive") + port map ( + rst_n_i => sys_rst_n_i, + clk_i => wb_clk_i, + data_i => gpio_b(i), + synced_o => gpio_in_synced(i), + npulse_o => open + ); + + end generate GEN_SYNC_FFS; + + + process (wb_clk_i, sys_rst_n_i) + begin + if sys_rst_n_i = '0' then + dir_reg <= (others => '0'); + out_reg <= (others => '0'); + ack_int <= '0'; + wb_data_o(g_num_pins-1 downto 0) <= (others => '0'); + elsif rising_edge(wb_clk_i) then + if(ack_int = '1') then + ack_int <= '0'; + elsif(wb_cyc_i = '1') and (wb_sel_i = '1') and (wb_stb_i = '1') then + if(wb_we_i = '1') then + case wb_addr_i(2 downto 0) is + when c_GPIO_REG_SODR => + out_reg <= out_reg or wb_data_i(g_num_pins-1 downto 0); + ack_int <= '1'; + when c_GPIO_REG_CODR => + out_reg <= out_reg and (not wb_data_i(g_num_pins-1 downto 0)); + ack_int <= '1'; + when c_GPIO_REG_DDR => + dir_reg <= wb_data_i(g_num_pins-1 downto 0); + ack_int <= '1'; + when others => + ack_int <= '1'; + end case; + else + case wb_addr_i(2 downto 0) is + when c_GPIO_REG_DDR => + wb_data_o(g_num_pins-1 downto 0) <= dir_reg; + ack_int <= '1'; + + when c_GPIO_REG_PSR => + wb_data_o(g_num_pins-1 downto 0) <= gpio_in_synced; + ack_int <= '1'; + when others => + ack_int <= '1'; + end case; + end if; + else + ack_int <= '0'; + end if; + end if; + end process; + + gpio_out_tristate : process (out_reg, dir_reg) + begin + for i in 0 to g_num_pins-1 loop + if(dir_reg(i) = '1') then + gpio_b(i) <= out_reg(i); + else + gpio_b(i) <= 'Z'; + end if; + + end loop; + end process gpio_out_tristate; + + wb_ack_o <= ack_int; +end behavioral; + + diff --git a/modules/wishbone/wb_i2c_master/i2c_master_bit_ctrl.vhd b/modules/wishbone/wb_i2c_master/i2c_master_bit_ctrl.vhd new file mode 100644 index 0000000000000000000000000000000000000000..a095fde0e882d3b0d6322145e9396759b223b9c2 --- /dev/null +++ b/modules/wishbone/wb_i2c_master/i2c_master_bit_ctrl.vhd @@ -0,0 +1,576 @@ +--------------------------------------------------------------------- +---- ---- +---- WISHBONE revB2 I2C Master Core; bit-controller ---- +---- ---- +---- ---- +---- Author: Richard Herveille ---- +---- richard@asics.ws ---- +---- www.asics.ws ---- +---- ---- +---- Downloaded from: http://www.opencores.org/projects/i2c/ ---- +---- ---- +--------------------------------------------------------------------- +---- ---- +---- Copyright (C) 2000 Richard Herveille ---- +---- richard@asics.ws ---- +---- ---- +---- This source file may be used and distributed without ---- +---- restriction provided that this copyright statement is not ---- +---- removed from the file and that any derivative work contains ---- +---- the original copyright notice and the associated disclaimer.---- +---- ---- +---- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ---- +---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ---- +---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ---- +---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ---- +---- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ---- +---- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ---- +---- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ---- +---- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ---- +---- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ---- +---- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ---- +---- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ---- +---- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ---- +---- POSSIBILITY OF SUCH DAMAGE. ---- +---- ---- +--------------------------------------------------------------------- + +-- CVS Log +-- +-- $Id: i2c_master_bit_ctrl.vhd,v 1.17 2009-02-04 20:17:34 rherveille Exp $ +-- +-- $Date: 2009-02-04 20:17:34 $ +-- $Revision: 1.17 $ +-- $Author: rherveille $ +-- $Locker: $ +-- $State: Exp $ +-- +-- Change History: +-- $Log: not supported by cvs2svn $ +-- Revision 1.16 2009/01/20 20:40:36 rherveille +-- Fixed type iscl_oen instead of scl_oen +-- +-- Revision 1.15 2009/01/20 10:34:51 rherveille +-- Added SCL clock synchronization logic +-- Fixed slave_wait signal generation +-- +-- Revision 1.14 2006/10/11 12:10:13 rherveille +-- Added missing semicolons ';' on endif +-- +-- Revision 1.13 2006/10/06 10:48:24 rherveille +-- fixed short scl high pulse after clock stretch +-- +-- Revision 1.12 2004/05/07 11:53:31 rherveille +-- Fixed previous fix :) Made a variable vs signal mistake. +-- +-- Revision 1.11 2004/05/07 11:04:00 rherveille +-- Fixed a bug where the core would signal an arbitration lost (AL bit set), when another master controls the bus and the other master generates a STOP bit. +-- +-- Revision 1.10 2004/02/27 07:49:43 rherveille +-- Fixed a bug in the arbitration-lost signal generation. VHDL version only. +-- +-- Revision 1.9 2003/08/12 14:48:37 rherveille +-- Forgot an 'end if' :-/ +-- +-- Revision 1.8 2003/08/09 07:01:13 rherveille +-- Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line. +-- Fixed a potential bug in the byte controller's host-acknowledge generation. +-- +-- Revision 1.7 2003/02/05 00:06:02 rherveille +-- Fixed a bug where the core would trigger an erroneous 'arbitration lost' interrupt after being reset, when the reset pulse width < 3 clk cycles. +-- +-- Revision 1.6 2003/02/01 02:03:06 rherveille +-- Fixed a few 'arbitration lost' bugs. VHDL version only. +-- +-- Revision 1.5 2002/12/26 16:05:47 rherveille +-- Core is now a Multimaster I2C controller. +-- +-- Revision 1.4 2002/11/30 22:24:37 rherveille +-- Cleaned up code +-- +-- Revision 1.3 2002/10/30 18:09:53 rherveille +-- Fixed some reported minor start/stop generation timing issuess. +-- +-- Revision 1.2 2002/06/15 07:37:04 rherveille +-- Fixed a small timing bug in the bit controller.\nAdded verilog simulation environment. +-- +-- Revision 1.1 2001/11/05 12:02:33 rherveille +-- Split i2c_master_core.vhd into separate files for each entity; same layout as verilog version. +-- Code updated, is now up-to-date to doc. rev.0.4. +-- Added headers. +-- + + +-- +------------------------------------- +-- Bit controller section +------------------------------------ +-- +-- Translate simple commands into SCL/SDA transitions +-- Each command has 5 states, A/B/C/D/idle +-- +-- start: SCL ~~~~~~~~~~~~~~\____ +-- SDA XX/~~~~~~~\______ +-- x | A | B | C | D | i +-- +-- repstart SCL ______/~~~~~~~\___ +-- SDA __/~~~~~~~\______ +-- x | A | B | C | D | i +-- +-- stop SCL _______/~~~~~~~~~~~ +-- SDA ==\___________/~~~~~ +-- x | A | B | C | D | i +-- +--- write SCL ______/~~~~~~~\____ +-- SDA XXX===============XX +-- x | A | B | C | D | i +-- +--- read SCL ______/~~~~~~~\____ +-- SDA XXXXXXX=XXXXXXXXXXX +-- x | A | B | C | D | i +-- + +-- Timing: Normal mode Fast mode +----------------------------------------------------------------- +-- Fscl 100KHz 400KHz +-- Th_scl 4.0us 0.6us High period of SCL +-- Tl_scl 4.7us 1.3us Low period of SCL +-- Tsu:sta 4.7us 0.6us setup time for a repeated start condition +-- Tsu:sto 4.0us 0.6us setup time for a stop conditon +-- Tbuf 4.7us 1.3us Bus free time between a stop and start condition +-- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity i2c_master_bit_ctrl is + port ( + clk : in std_logic; + rst : in std_logic; + nReset : in std_logic; + ena : in std_logic; -- core enable signal + + clk_cnt : in unsigned(15 downto 0); -- clock prescale value + + cmd : in std_logic_vector(3 downto 0); + cmd_ack : out std_logic; -- command completed + busy : out std_logic; -- i2c bus busy + al : out std_logic; -- arbitration lost + + din : in std_logic; + dout : out std_logic; + + -- i2c lines + scl_i : in std_logic; -- i2c clock line input + scl_o : out std_logic; -- i2c clock line output + scl_oen : out std_logic; -- i2c clock line output enable, active low + sda_i : in std_logic; -- i2c data line input + sda_o : out std_logic; -- i2c data line output + sda_oen : out std_logic -- i2c data line output enable, active low + ); +end entity i2c_master_bit_ctrl; + +architecture structural of i2c_master_bit_ctrl is + constant I2C_CMD_NOP : std_logic_vector(3 downto 0) := "0000"; + constant I2C_CMD_START : std_logic_vector(3 downto 0) := "0001"; + constant I2C_CMD_STOP : std_logic_vector(3 downto 0) := "0010"; + constant I2C_CMD_READ : std_logic_vector(3 downto 0) := "0100"; + constant I2C_CMD_WRITE : std_logic_vector(3 downto 0) := "1000"; + + type states is (idle, start_a, start_b, start_c, start_d, start_e, + stop_a, stop_b, stop_c, stop_d, rd_a, rd_b, rd_c, rd_d, wr_a, wr_b, wr_c, wr_d); + signal c_state : states; + + signal iscl_oen, isda_oen : std_logic; -- internal I2C lines + signal sda_chk : std_logic; -- check SDA status (multi-master arbitration) + signal dscl_oen : std_logic; -- delayed scl_oen signals + signal sSCL, sSDA : std_logic; -- synchronized SCL and SDA inputs + signal dSCL, dSDA : std_logic; -- delayed versions ofsSCL and sSDA + signal clk_en : std_logic; -- statemachine clock enable + signal scl_sync, slave_wait : std_logic; -- clock generation signals + signal ial : std_logic; -- internal arbitration lost signal + signal cnt : unsigned(15 downto 0); -- clock divider counter (synthesis) + +begin + -- whenever the slave is not ready it can delay the cycle by pulling SCL low + -- delay scl_oen + process (clk, nReset) + begin + if (nReset = '0') then + dscl_oen <= '0'; + elsif (clk'event and clk = '1') then + dscl_oen <= iscl_oen; + end if; + end process; + + -- slave_wait is asserted when master wants to drive SCL high, but the slave pulls it low + -- slave_wait remains asserted until the slave releases SCL + process (clk, nReset) + begin + if (nReset = '0') then + slave_wait <= '0'; + elsif (clk'event and clk = '1') then + slave_wait <= (iscl_oen and not dscl_oen and not sSCL) or (slave_wait and not sSCL); + end if; + end process; + + -- master drives SCL high, but another master pulls it low + -- master start counting down its low cycle now (clock synchronization) + scl_sync <= dSCL and not sSCL and iscl_oen; + + -- generate clk enable signal + gen_clken: process(clk, nReset) + begin + if (nReset = '0') then + cnt <= (others => '0'); + clk_en <= '1'; + elsif (clk'event and clk = '1') then + if ((rst = '1') or (cnt = 0) or (ena = '0') or (scl_sync = '1')) then + cnt <= clk_cnt; + clk_en <= '1'; + elsif (slave_wait = '1') then + cnt <= cnt; + clk_en <= '0'; + else + cnt <= cnt -1; + clk_en <= '0'; + end if; + end if; + end process gen_clken; + + + -- generate bus status controller + bus_status_ctrl: block + signal cSCL, cSDA : std_logic_vector( 1 downto 0); -- capture SDA and SCL + signal fSCL, fSDA : std_logic_vector( 2 downto 0); -- filter inputs for SCL and SDA + signal filter_cnt : unsigned(13 downto 0); -- clock divider for filter + signal sta_condition : std_logic; -- start detected + signal sto_condition : std_logic; -- stop detected + signal cmd_stop : std_logic; -- STOP command + signal ibusy : std_logic; -- internal busy signal + begin + -- capture SCL and SDA + capture_scl_sda: process(clk, nReset) + begin + if (nReset = '0') then + cSCL <= "00"; + cSDA <= "00"; + elsif (clk'event and clk = '1') then + if (rst = '1') then + cSCL <= "00"; + cSDA <= "00"; + else + cSCL <= (cSCL(0) & scl_i); + cSDA <= (cSDA(0) & sda_i); + end if; + end if; + end process capture_scl_sda; + + -- filter SCL and SDA; (attempt to) remove glitches + filter_divider: process(clk, nReset) + begin + if (nReset = '0') then + filter_cnt <= (others => '0'); + elsif (clk'event and clk = '1') then + if ( (rst = '1') or (ena = '0') ) then + filter_cnt <= (others => '0'); + elsif (filter_cnt = 0) then + filter_cnt <= clk_cnt(15 downto 2); + else + filter_cnt <= filter_cnt -1; + end if; + end if; + end process filter_divider; + + filter_scl_sda: process(clk, nReset) + begin + if (nReset = '0') then + fSCL <= (others => '1'); + fSDA <= (others => '1'); + elsif (clk'event and clk = '1') then + if (rst = '1') then + fSCL <= (others => '1'); + fSDA <= (others => '1'); + elsif (filter_cnt = 0) then + fSCL <= (fSCL(1 downto 0) & cSCL(1)); + fSDA <= (fSDA(1 downto 0) & cSDA(1)); + end if; + end if; + end process filter_scl_sda; + + -- generate filtered SCL and SDA signals + scl_sda: process(clk, nReset) + begin + if (nReset = '0') then + sSCL <= '1'; + sSDA <= '1'; + + dSCL <= '1'; + dSDA <= '1'; + elsif (clk'event and clk = '1') then + if (rst = '1') then + sSCL <= '1'; + sSDA <= '1'; + + dSCL <= '1'; + dSDA <= '1'; + else + sSCL <= (fSCL(2) and fSCL(1)) or + (fSCL(2) and fSCL(0)) or + (fSCL(1) and fSCL(0)); + sSDA <= (fSDA(2) and fSDA(1)) or + (fSDA(2) and fSDA(0)) or + (fSDA(1) and fSDA(0)); + + dSCL <= sSCL; + dSDA <= sSDA; + end if; + end if; + end process scl_sda; + + + -- detect start condition => detect falling edge on SDA while SCL is high + -- detect stop condition => detect rising edge on SDA while SCL is high + detect_sta_sto: process(clk, nReset) + begin + if (nReset = '0') then + sta_condition <= '0'; + sto_condition <= '0'; + elsif (clk'event and clk = '1') then + if (rst = '1') then + sta_condition <= '0'; + sto_condition <= '0'; + else + sta_condition <= (not sSDA and dSDA) and sSCL; + sto_condition <= (sSDA and not dSDA) and sSCL; + end if; + end if; + end process detect_sta_sto; + + + -- generate i2c-bus busy signal + gen_busy: process(clk, nReset) + begin + if (nReset = '0') then + ibusy <= '0'; + elsif (clk'event and clk = '1') then + if (rst = '1') then + ibusy <= '0'; + else + ibusy <= (sta_condition or ibusy) and not sto_condition; + end if; + end if; + end process gen_busy; + busy <= ibusy; + + + -- generate arbitration lost signal + -- aribitration lost when: + -- 1) master drives SDA high, but the i2c bus is low + -- 2) stop detected while not requested (detect during 'idle' state) + gen_al: process(clk, nReset) + begin + if (nReset = '0') then + cmd_stop <= '0'; + ial <= '0'; + elsif (clk'event and clk = '1') then + if (rst = '1') then + cmd_stop <= '0'; + ial <= '0'; + else + if (clk_en = '1') then + if (cmd = I2C_CMD_STOP) then + cmd_stop <= '1'; + else + cmd_stop <= '0'; + end if; + end if; + + if (c_state = idle) then + ial <= (sda_chk and not sSDA and isda_oen) or (sto_condition and not cmd_stop); + else + ial <= (sda_chk and not sSDA and isda_oen); + end if; + end if; + end if; + end process gen_al; + al <= ial; + + + -- generate dout signal, store dout on rising edge of SCL + gen_dout: process(clk, nReset) + begin + if (nReset = '0') then + dout <= '0'; + elsif (clk'event and clk = '1') then + if (sSCL = '1' and dSCL = '0') then + dout <= sSDA; + end if; + end if; + end process gen_dout; + end block bus_status_ctrl; + + + -- generate statemachine + nxt_state_decoder : process (clk, nReset) + begin + if (nReset = '0') then + c_state <= idle; + cmd_ack <= '0'; + iscl_oen <= '1'; + isda_oen <= '1'; + sda_chk <= '0'; + elsif (clk'event and clk = '1') then + if (rst = '1' or ial = '1') then + c_state <= idle; + cmd_ack <= '0'; + iscl_oen <= '1'; + isda_oen <= '1'; + sda_chk <= '0'; + else + cmd_ack <= '0'; -- default no acknowledge + + if (clk_en = '1') then + case (c_state) is + -- idle + when idle => + case cmd is + when I2C_CMD_START => c_state <= start_a; + when I2C_CMD_STOP => c_state <= stop_a; + when I2C_CMD_WRITE => c_state <= wr_a; + when I2C_CMD_READ => c_state <= rd_a; + when others => c_state <= idle; -- NOP command + end case; + + iscl_oen <= iscl_oen; -- keep SCL in same state + isda_oen <= isda_oen; -- keep SDA in same state + sda_chk <= '0'; -- don't check SDA + + -- start + when start_a => + c_state <= start_b; + iscl_oen <= iscl_oen; -- keep SCL in same state (for repeated start) + isda_oen <= '1'; -- set SDA high + sda_chk <= '0'; -- don't check SDA + + when start_b => + c_state <= start_c; + iscl_oen <= '1'; -- set SCL high + isda_oen <= '1'; -- keep SDA high + sda_chk <= '0'; -- don't check SDA + + when start_c => + c_state <= start_d; + iscl_oen <= '1'; -- keep SCL high + isda_oen <= '0'; -- set SDA low + sda_chk <= '0'; -- don't check SDA + + when start_d => + c_state <= start_e; + iscl_oen <= '1'; -- keep SCL high + isda_oen <= '0'; -- keep SDA low + sda_chk <= '0'; -- don't check SDA + + when start_e => + c_state <= idle; + cmd_ack <= '1'; -- command completed + iscl_oen <= '0'; -- set SCL low + isda_oen <= '0'; -- keep SDA low + sda_chk <= '0'; -- don't check SDA + + -- stop + when stop_a => + c_state <= stop_b; + iscl_oen <= '0'; -- keep SCL low + isda_oen <= '0'; -- set SDA low + sda_chk <= '0'; -- don't check SDA + + when stop_b => + c_state <= stop_c; + iscl_oen <= '1'; -- set SCL high + isda_oen <= '0'; -- keep SDA low + sda_chk <= '0'; -- don't check SDA + + when stop_c => + c_state <= stop_d; + iscl_oen <= '1'; -- keep SCL high + isda_oen <= '0'; -- keep SDA low + sda_chk <= '0'; -- don't check SDA + + when stop_d => + c_state <= idle; + cmd_ack <= '1'; -- command completed + iscl_oen <= '1'; -- keep SCL high + isda_oen <= '1'; -- set SDA high + sda_chk <= '0'; -- don't check SDA + + -- read + when rd_a => + c_state <= rd_b; + iscl_oen <= '0'; -- keep SCL low + isda_oen <= '1'; -- tri-state SDA + sda_chk <= '0'; -- don't check SDA + + when rd_b => + c_state <= rd_c; + iscl_oen <= '1'; -- set SCL high + isda_oen <= '1'; -- tri-state SDA + sda_chk <= '0'; -- don't check SDA + + when rd_c => + c_state <= rd_d; + iscl_oen <= '1'; -- keep SCL high + isda_oen <= '1'; -- tri-state SDA + sda_chk <= '0'; -- don't check SDA + + when rd_d => + c_state <= idle; + cmd_ack <= '1'; -- command completed + iscl_oen <= '0'; -- set SCL low + isda_oen <= '1'; -- tri-state SDA + sda_chk <= '0'; -- don't check SDA + + -- write + when wr_a => + c_state <= wr_b; + iscl_oen <= '0'; -- keep SCL low + isda_oen <= din; -- set SDA + sda_chk <= '0'; -- don't check SDA (SCL low) + + when wr_b => + c_state <= wr_c; + iscl_oen <= '1'; -- set SCL high + isda_oen <= din; -- keep SDA + sda_chk <= '0'; -- don't check SDA yet + -- Allow some more time for SDA and SCL to settle + + when wr_c => + c_state <= wr_d; + iscl_oen <= '1'; -- keep SCL high + isda_oen <= din; -- keep SDA + sda_chk <= '1'; -- check SDA + + when wr_d => + c_state <= idle; + cmd_ack <= '1'; -- command completed + iscl_oen <= '0'; -- set SCL low + isda_oen <= din; -- keep SDA + sda_chk <= '0'; -- don't check SDA (SCL low) + + when others => + + end case; + end if; + end if; + end if; + end process nxt_state_decoder; + + + -- assign outputs + scl_o <= '0'; + scl_oen <= iscl_oen; + sda_o <= '0'; + sda_oen <= isda_oen; +end architecture structural; + diff --git a/modules/wishbone/wb_i2c_master/i2c_master_byte_ctrl.vhd b/modules/wishbone/wb_i2c_master/i2c_master_byte_ctrl.vhd new file mode 100644 index 0000000000000000000000000000000000000000..8e4d02a5bba06586c75d1c68066d7a4258876463 --- /dev/null +++ b/modules/wishbone/wb_i2c_master/i2c_master_byte_ctrl.vhd @@ -0,0 +1,368 @@ +--------------------------------------------------------------------- +---- ---- +---- WISHBONE revB2 compl. I2C Master Core; byte-controller ---- +---- ---- +---- ---- +---- Author: Richard Herveille ---- +---- richard@asics.ws ---- +---- www.asics.ws ---- +---- ---- +---- Downloaded from: http://www.opencores.org/projects/i2c/ ---- +---- ---- +--------------------------------------------------------------------- +---- ---- +---- Copyright (C) 2000 Richard Herveille ---- +---- richard@asics.ws ---- +---- ---- +---- This source file may be used and distributed without ---- +---- restriction provided that this copyright statement is not ---- +---- removed from the file and that any derivative work contains ---- +---- the original copyright notice and the associated disclaimer.---- +---- ---- +---- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ---- +---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ---- +---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ---- +---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ---- +---- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ---- +---- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ---- +---- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ---- +---- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ---- +---- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ---- +---- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ---- +---- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ---- +---- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ---- +---- POSSIBILITY OF SUCH DAMAGE. ---- +---- ---- +--------------------------------------------------------------------- + +-- CVS Log +-- +-- $Id: i2c_master_byte_ctrl.vhd,v 1.5 2004-02-18 11:41:48 rherveille Exp $ +-- +-- $Date: 2004-02-18 11:41:48 $ +-- $Revision: 1.5 $ +-- $Author: rherveille $ +-- $Locker: $ +-- $State: Exp $ +-- +-- Change History: +-- $Log: not supported by cvs2svn $ +-- Revision 1.4 2003/08/09 07:01:13 rherveille +-- Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line. +-- Fixed a potential bug in the byte controller's host-acknowledge generation. +-- +-- Revision 1.3 2002/12/26 16:05:47 rherveille +-- Core is now a Multimaster I2C controller. +-- +-- Revision 1.2 2002/11/30 22:24:37 rherveille +-- Cleaned up code +-- +-- Revision 1.1 2001/11/05 12:02:33 rherveille +-- Split i2c_master_core.vhd into separate files for each entity; same layout as verilog version. +-- Code updated, is now up-to-date to doc. rev.0.4. +-- Added headers. +-- + + + + +-- +------------------------------------------ +-- Byte controller section +------------------------------------------ +-- +library ieee; +use ieee.std_logic_1164.all; +--use ieee.std_logic_arith.all; +use ieee.numeric_std.all; + +entity i2c_master_byte_ctrl is + port ( + clk : in std_logic; + rst : in std_logic; -- synchronous active high reset (WISHBONE compatible) + nReset : in std_logic; -- asynchornous active low reset (FPGA compatible) + ena : in std_logic; -- core enable signal + + clk_cnt : in unsigned(15 downto 0); -- 4x SCL + + -- input signals + start, + stop, + read, + write, + ack_in : std_logic; + din : in std_logic_vector(7 downto 0); + + -- output signals + cmd_ack : out std_logic; -- command done + ack_out : out std_logic; + i2c_busy : out std_logic; -- arbitration lost + i2c_al : out std_logic; -- i2c bus busy + dout : out std_logic_vector(7 downto 0); + + -- i2c lines + scl_i : in std_logic; -- i2c clock line input + scl_o : out std_logic; -- i2c clock line output + scl_oen : out std_logic; -- i2c clock line output enable, active low + sda_i : in std_logic; -- i2c data line input + sda_o : out std_logic; -- i2c data line output + sda_oen : out std_logic -- i2c data line output enable, active low + ); +end entity i2c_master_byte_ctrl; + +architecture structural of i2c_master_byte_ctrl is + component i2c_master_bit_ctrl is + port ( + clk : in std_logic; + rst : in std_logic; + nReset : in std_logic; + ena : in std_logic; -- core enable signal + + clk_cnt : in unsigned(15 downto 0); -- clock prescale value + + cmd : in std_logic_vector(3 downto 0); + cmd_ack : out std_logic; -- command done + busy : out std_logic; -- i2c bus busy + al : out std_logic; -- arbitration lost + + din : in std_logic; + dout : out std_logic; + + -- i2c lines + scl_i : in std_logic; -- i2c clock line input + scl_o : out std_logic; -- i2c clock line output + scl_oen : out std_logic; -- i2c clock line output enable, active low + sda_i : in std_logic; -- i2c data line input + sda_o : out std_logic; -- i2c data line output + sda_oen : out std_logic -- i2c data line output enable, active low + ); + end component i2c_master_bit_ctrl; + + -- commands for bit_controller block + constant I2C_CMD_NOP : std_logic_vector(3 downto 0) := "0000"; + constant I2C_CMD_START : std_logic_vector(3 downto 0) := "0001"; + constant I2C_CMD_STOP : std_logic_vector(3 downto 0) := "0010"; + constant I2C_CMD_READ : std_logic_vector(3 downto 0) := "0100"; + constant I2C_CMD_WRITE : std_logic_vector(3 downto 0) := "1000"; + + -- signals for bit_controller + signal core_cmd : std_logic_vector(3 downto 0); + signal core_ack, core_txd, core_rxd : std_logic; + signal al : std_logic; + + -- signals for shift register + signal sr : std_logic_vector(7 downto 0); -- 8bit shift register + signal shift, ld : std_logic; + + -- signals for state machine + signal go, host_ack : std_logic; + signal dcnt : unsigned(2 downto 0); -- data counter + signal cnt_done : std_logic; + +begin + -- hookup bit_controller + bit_ctrl: i2c_master_bit_ctrl port map( + clk => clk, + rst => rst, + nReset => nReset, + ena => ena, + clk_cnt => clk_cnt, + cmd => core_cmd, + cmd_ack => core_ack, + busy => i2c_busy, + al => al, + din => core_txd, + dout => core_rxd, + scl_i => scl_i, + scl_o => scl_o, + scl_oen => scl_oen, + sda_i => sda_i, + sda_o => sda_o, + sda_oen => sda_oen + ); + i2c_al <= al; + + -- generate host-command-acknowledge + cmd_ack <= host_ack; + + -- generate go-signal + go <= (read or write or stop) and not host_ack; + + -- assign Dout output to shift-register + dout <= sr; + + -- generate shift register + shift_register: process(clk, nReset) + begin + if (nReset = '0') then + sr <= (others => '0'); + elsif (clk'event and clk = '1') then + if (rst = '1') then + sr <= (others => '0'); + elsif (ld = '1') then + sr <= din; + elsif (shift = '1') then + sr <= (sr(6 downto 0) & core_rxd); + end if; + end if; + end process shift_register; + + -- generate data-counter + data_cnt: process(clk, nReset) + begin + if (nReset = '0') then + dcnt <= (others => '0'); + elsif (clk'event and clk = '1') then + if (rst = '1') then + dcnt <= (others => '0'); + elsif (ld = '1') then + dcnt <= (others => '1'); -- load counter with 7 + elsif (shift = '1') then + dcnt <= dcnt -1; + end if; + end if; + end process data_cnt; + + cnt_done <= '1' when (dcnt = 0) else '0'; + + -- + -- state machine + -- + statemachine : block + type states is (st_idle, st_start, st_read, st_write, st_ack, st_stop); + signal c_state : states; + begin + -- + -- command interpreter, translate complex commands into simpler I2C commands + -- + nxt_state_decoder: process(clk, nReset) + begin + if (nReset = '0') then + core_cmd <= I2C_CMD_NOP; + core_txd <= '0'; + shift <= '0'; + ld <= '0'; + host_ack <= '0'; + c_state <= st_idle; + ack_out <= '0'; + elsif (clk'event and clk = '1') then + if (rst = '1' or al = '1') then + core_cmd <= I2C_CMD_NOP; + core_txd <= '0'; + shift <= '0'; + ld <= '0'; + host_ack <= '0'; + c_state <= st_idle; + ack_out <= '0'; + else + -- initialy reset all signal + core_txd <= sr(7); + shift <= '0'; + ld <= '0'; + host_ack <= '0'; + + case c_state is + when st_idle => + if (go = '1') then + if (start = '1') then + c_state <= st_start; + core_cmd <= I2C_CMD_START; + elsif (read = '1') then + c_state <= st_read; + core_cmd <= I2C_CMD_READ; + elsif (write = '1') then + c_state <= st_write; + core_cmd <= I2C_CMD_WRITE; + else -- stop + c_state <= st_stop; + core_cmd <= I2C_CMD_STOP; + end if; + + ld <= '1'; + end if; + + when st_start => + if (core_ack = '1') then + if (read = '1') then + c_state <= st_read; + core_cmd <= I2C_CMD_READ; + else + c_state <= st_write; + core_cmd <= I2C_CMD_WRITE; + end if; + + ld <= '1'; + end if; + + when st_write => + if (core_ack = '1') then + if (cnt_done = '1') then + c_state <= st_ack; + core_cmd <= I2C_CMD_READ; + else + c_state <= st_write; -- stay in same state + core_cmd <= I2C_CMD_WRITE; -- write next bit + shift <= '1'; + end if; + end if; + + when st_read => + if (core_ack = '1') then + if (cnt_done = '1') then + c_state <= st_ack; + core_cmd <= I2C_CMD_WRITE; + else + c_state <= st_read; -- stay in same state + core_cmd <= I2C_CMD_READ; -- read next bit + end if; + + shift <= '1'; + core_txd <= ack_in; + end if; + + when st_ack => + if (core_ack = '1') then + -- check for stop; Should a STOP command be generated ? + if (stop = '1') then + c_state <= st_stop; + core_cmd <= I2C_CMD_STOP; + else + c_state <= st_idle; + core_cmd <= I2C_CMD_NOP; + + -- generate command acknowledge signal + host_ack <= '1'; + end if; + + -- assign ack_out output to core_rxd (contains last received bit) + ack_out <= core_rxd; + + core_txd <= '1'; + else + core_txd <= ack_in; + end if; + + when st_stop => + if (core_ack = '1') then + c_state <= st_idle; + core_cmd <= I2C_CMD_NOP; + + -- generate command acknowledge signal + host_ack <= '1'; + end if; + + when others => -- illegal states + c_state <= st_idle; + core_cmd <= I2C_CMD_NOP; + report ("Byte controller entered illegal state."); + + end case; + + end if; + end if; + end process nxt_state_decoder; + + end block statemachine; + +end architecture structural; + diff --git a/modules/wishbone/wb_i2c_master/wb_i2c_master.vhd b/modules/wishbone/wb_i2c_master/wb_i2c_master.vhd new file mode 100644 index 0000000000000000000000000000000000000000..f1a63eddbd6b81521f614cdd7ba773c2db51d255 --- /dev/null +++ b/modules/wishbone/wb_i2c_master/wb_i2c_master.vhd @@ -0,0 +1,359 @@ +--------------------------------------------------------------------- +---- ---- +---- WISHBONE revB2 compl. I2C Master Core; top level ---- +---- ---- +---- ---- +---- Author: Richard Herveille ---- +---- richard@asics.ws ---- +---- www.asics.ws ---- +---- ---- +---- Downloaded from: http://www.opencores.org/projects/i2c/ ---- +---- ---- +--------------------------------------------------------------------- +---- ---- +---- Copyright (C) 2000 Richard Herveille ---- +---- richard@asics.ws ---- +---- ---- +---- This source file may be used and distributed without ---- +---- restriction provided that this copyright statement is not ---- +---- removed from the file and that any derivative work contains ---- +---- the original copyright notice and the associated disclaimer.---- +---- ---- +---- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ---- +---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ---- +---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ---- +---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ---- +---- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ---- +---- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ---- +---- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ---- +---- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ---- +---- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ---- +---- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ---- +---- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ---- +---- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ---- +---- POSSIBILITY OF SUCH DAMAGE. ---- +---- ---- +--------------------------------------------------------------------- + +-- CVS Log +-- +-- $Id: i2c_master_top.vhd,v 1.8 2009-01-20 10:38:45 rherveille Exp $ +-- +-- $Date: 2009-01-20 10:38:45 $ +-- $Revision: 1.8 $ +-- $Author: rherveille $ +-- $Locker: $ +-- $State: Exp $ +-- +-- Change History: +-- Revision 1.7 2004/03/14 10:17:03 rherveille +-- Fixed simulation issue when writing to CR register +-- +-- Revision 1.6 2003/08/09 07:01:13 rherveille +-- Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line. +-- Fixed a potential bug in the byte controller's host-acknowledge generation. +-- +-- Revision 1.5 2003/02/01 02:03:06 rherveille +-- Fixed a few 'arbitration lost' bugs. VHDL version only. +-- +-- Revision 1.4 2002/12/26 16:05:47 rherveille +-- Core is now a Multimaster I2C controller. +-- +-- Revision 1.3 2002/11/30 22:24:37 rherveille +-- Cleaned up code +-- +-- Revision 1.2 2001/11/10 10:52:44 rherveille +-- Changed PRER reset value from 0x0000 to 0xffff, conform specs. +-- + + +library ieee; +use ieee.std_logic_1164.all; +--use ieee.std_logic_arith.all; +use ieee.numeric_std.all; + +entity i2c_master_top is + generic( + ARST_LVL : std_logic := '0' -- asynchronous reset level + ); + port ( + -- wishbone signals + wb_clk_i : in std_logic; -- master clock input + wb_rst_i : in std_logic := '0'; -- synchronous active high reset + arst_i : in std_logic := not ARST_LVL; -- asynchronous reset + wb_adr_i : in std_logic_vector(2 downto 0); -- lower address bits + wb_dat_i : in std_logic_vector(7 downto 0); -- Databus input + wb_dat_o : out std_logic_vector(7 downto 0); -- Databus output + wb_we_i : in std_logic; -- Write enable input + wb_stb_i : in std_logic; -- Strobe signals / core select signal + wb_cyc_i : in std_logic; -- Valid bus cycle input + wb_ack_o : out std_logic; -- Bus cycle acknowledge output + wb_inta_o : out std_logic; -- interrupt request output signal + + -- i2c lines + scl_pad_i : in std_logic; -- i2c clock line input + scl_pad_o : out std_logic; -- i2c clock line output + scl_padoen_o : out std_logic; -- i2c clock line output enable, active low + sda_pad_i : in std_logic; -- i2c data line input + sda_pad_o : out std_logic; -- i2c data line output + sda_padoen_o : out std_logic -- i2c data line output enable, active low + ); +end entity i2c_master_top; + +architecture structural of i2c_master_top is + component i2c_master_byte_ctrl is + port ( + clk : in std_logic; + rst : in std_logic; -- synchronous active high reset (WISHBONE compatible) + nReset : in std_logic; -- asynchornous active low reset (FPGA compatible) + ena : in std_logic; -- core enable signal + + clk_cnt : in unsigned(15 downto 0); -- 4x SCL + + -- input signals + start, + stop, + read, + write, + ack_in : std_logic; + din : in std_logic_vector(7 downto 0); + + -- output signals + cmd_ack : out std_logic; + ack_out : out std_logic; + i2c_busy : out std_logic; + i2c_al : out std_logic; + dout : out std_logic_vector(7 downto 0); + + -- i2c lines + scl_i : in std_logic; -- i2c clock line input + scl_o : out std_logic; -- i2c clock line output + scl_oen : out std_logic; -- i2c clock line output enable, active low + sda_i : in std_logic; -- i2c data line input + sda_o : out std_logic; -- i2c data line output + sda_oen : out std_logic -- i2c data line output enable, active low + ); + end component i2c_master_byte_ctrl; + + -- registers + signal prer : unsigned(15 downto 0); -- clock prescale register + signal ctr : std_logic_vector(7 downto 0); -- control register + signal txr : std_logic_vector(7 downto 0); -- transmit register + signal rxr : std_logic_vector(7 downto 0); -- receive register + signal cr : std_logic_vector(7 downto 0); -- command register + signal sr : std_logic_vector(7 downto 0); -- status register + + -- internal reset signal + signal rst_i : std_logic; + + -- wishbone write access + signal wb_wacc : std_logic; + + -- internal acknowledge signal + signal iack_o : std_logic; + + -- done signal: command completed, clear command register + signal done : std_logic; + + -- command register signals + signal sta, sto, rd, wr, ack, iack : std_logic; + + signal core_en : std_logic; -- core enable signal + signal ien : std_logic; -- interrupt enable signal + + -- status register signals + signal irxack, rxack : std_logic; -- received aknowledge from slave + signal tip : std_logic; -- transfer in progress + signal irq_flag : std_logic; -- interrupt pending flag + signal i2c_busy : std_logic; -- i2c bus busy (start signal detected) + signal i2c_al, al : std_logic; -- arbitration lost + +begin + -- generate internal reset signal + rst_i <= arst_i xor ARST_LVL; + + -- generate acknowledge output signal + gen_ack_o : process(wb_clk_i) + begin + if (wb_clk_i'event and wb_clk_i = '1') then + iack_o <= wb_cyc_i and wb_stb_i and not iack_o; -- because timing is always honored + end if; + end process gen_ack_o; + wb_ack_o <= iack_o; + + -- generate wishbone write access signal + wb_wacc <= wb_we_i and iack_o; + + -- assign wb_dat_o + assign_dato : process(wb_clk_i) + begin + if (wb_clk_i'event and wb_clk_i = '1') then + case wb_adr_i is + when "000" => wb_dat_o <= std_logic_vector(prer( 7 downto 0)); + when "001" => wb_dat_o <= std_logic_vector(prer(15 downto 8)); + when "010" => wb_dat_o <= ctr; + when "011" => wb_dat_o <= rxr; -- write is transmit register TxR + when "100" => wb_dat_o <= sr; -- write is command register CR + + -- Debugging registers: + -- These registers are not documented. + -- Functionality could change in future releases + when "101" => wb_dat_o <= txr; + when "110" => wb_dat_o <= cr; + when "111" => wb_dat_o <= (others => '0'); + when others => wb_dat_o <= (others => 'X'); -- for simulation only + end case; + end if; + end process assign_dato; + + + -- generate registers (CR, SR see below) + gen_regs: process(rst_i, wb_clk_i) + begin + if (rst_i = '0') then + prer <= (others => '1'); + ctr <= (others => '0'); + txr <= (others => '0'); + elsif (wb_clk_i'event and wb_clk_i = '1') then + if (wb_rst_i = '1') then + prer <= (others => '1'); + ctr <= (others => '0'); + txr <= (others => '0'); + elsif (wb_wacc = '1') then + case wb_adr_i is + when "000" => prer( 7 downto 0) <= unsigned(wb_dat_i); + when "001" => prer(15 downto 8) <= unsigned(wb_dat_i); + when "010" => ctr <= wb_dat_i; + when "011" => txr <= wb_dat_i; + when "100" => null; --write to CR, avoid executing the others clause + + -- illegal cases, for simulation only + when others => + report ("Illegal write address, setting all registers to unknown."); + prer <= (others => 'X'); + ctr <= (others => 'X'); + txr <= (others => 'X'); + end case; + end if; + end if; + end process gen_regs; + + + -- generate command register + gen_cr: process(rst_i, wb_clk_i) + begin + if (rst_i = '0') then + cr <= (others => '0'); + elsif (wb_clk_i'event and wb_clk_i = '1') then + if (wb_rst_i = '1') then + cr <= (others => '0'); + elsif (wb_wacc = '1') then + if ( (core_en = '1') and (wb_adr_i = "100") ) then + -- only take new commands when i2c core enabled + -- pending commands are finished + cr <= wb_dat_i; + end if; + else + if (done = '1' or i2c_al = '1') then + cr(7 downto 4) <= (others => '0'); -- clear command bits when command done or arbitration lost + end if; + + cr(2 downto 1) <= (others => '0'); -- reserved bits, always '0' + cr(0) <= '0'; -- clear IRQ_ACK bit + end if; + end if; + end process gen_cr; + + -- decode command register + sta <= cr(7); + sto <= cr(6); + rd <= cr(5); + wr <= cr(4); + ack <= cr(3); + iack <= cr(0); + + -- decode control register + core_en <= ctr(7); + ien <= ctr(6); + + -- hookup byte controller block + byte_ctrl: i2c_master_byte_ctrl + port map ( + clk => wb_clk_i, + rst => wb_rst_i, + nReset => rst_i, + ena => core_en, + clk_cnt => prer, + start => sta, + stop => sto, + read => rd, + write => wr, + ack_in => ack, + i2c_busy => i2c_busy, + i2c_al => i2c_al, + din => txr, + cmd_ack => done, + ack_out => irxack, + dout => rxr, + scl_i => scl_pad_i, + scl_o => scl_pad_o, + scl_oen => scl_padoen_o, + sda_i => sda_pad_i, + sda_o => sda_pad_o, + sda_oen => sda_padoen_o + ); + + + -- status register block + interrupt request signal + st_irq_block : block + begin + -- generate status register bits + gen_sr_bits: process (wb_clk_i, rst_i) + begin + if (rst_i = '0') then + al <= '0'; + rxack <= '0'; + tip <= '0'; + irq_flag <= '0'; + elsif (wb_clk_i'event and wb_clk_i = '1') then + if (wb_rst_i = '1') then + al <= '0'; + rxack <= '0'; + tip <= '0'; + irq_flag <= '0'; + else + al <= i2c_al or (al and not sta); + rxack <= irxack; + tip <= (rd or wr); + + -- interrupt request flag is always generated + irq_flag <= (done or i2c_al or irq_flag) and not iack; + end if; + end if; + end process gen_sr_bits; + + -- generate interrupt request signals + gen_irq: process (wb_clk_i, rst_i) + begin + if (rst_i = '0') then + wb_inta_o <= '0'; + elsif (wb_clk_i'event and wb_clk_i = '1') then + if (wb_rst_i = '1') then + wb_inta_o <= '0'; + else + -- interrupt signal is only generated when IEN (interrupt enable bit) is set + wb_inta_o <= irq_flag and ien; + end if; + end if; + end process gen_irq; + + -- assign status register bits + sr(7) <= rxack; + sr(6) <= i2c_busy; + sr(5) <= al; + sr(4 downto 2) <= (others => '0'); -- reserved + sr(1) <= tip; + sr(0) <= irq_flag; + end block; + +end architecture structural; diff --git a/modules/wishbone/wb_simple_timer/manifest.py b/modules/wishbone/wb_simple_timer/manifest.py new file mode 100644 index 0000000000000000000000000000000000000000..2bd835b91162e5733a2b04ada27947cd36b8d727 --- /dev/null +++ b/modules/wishbone/wb_simple_timer/manifest.py @@ -0,0 +1 @@ +files = ["wb_tics.vhd"]; \ No newline at end of file diff --git a/modules/wishbone/wb_simple_timer/wb_tics.vhd b/modules/wishbone/wb_simple_timer/wb_tics.vhd new file mode 100644 index 0000000000000000000000000000000000000000..d7acc1388bf909332507783fb592066676f51731 --- /dev/null +++ b/modules/wishbone/wb_simple_timer/wb_tics.vhd @@ -0,0 +1,116 @@ +------------------------------------------------------------------------------- +-- Title : WhiteRabbit PTP Core tics +-- Project : WhiteRabbit +------------------------------------------------------------------------------- +-- File : wb_tics.vhd +-- Author : Grzegorz Daniluk +-- Company : Elproma +-- Created : 2011-04-03 +-- Last update: 2011-04-07 +-- Platform : FPGA-generics +-- Standard : VHDL +------------------------------------------------------------------------------- +-- Description: +-- WB_TICS is a simple counter with wishbone interface. Each step of a counter +-- takes 1 usec. It is used by ptp-noposix as a replace of gettimeofday() +-- function. +------------------------------------------------------------------------------- +-- Copyright (c) 2011 Grzegorz Daniluk +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2011-04-03 1.0 greg.d Created +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.common_components.all; + +entity wb_tics is + + generic ( + g_period : integer); + port( + rst_n_i : in std_logic; + + clk_sys_i : in std_logic; + + wb_addr_i : in std_logic_vector(1 downto 0); + wb_data_i : in std_logic_vector(31 downto 0); + wb_data_o : out std_logic_vector(31 downto 0); + wb_cyc_i : in std_logic; + wb_sel_i : in std_logic_vector(3 downto 0); + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_ack_o : out std_logic + ); +end wb_tics; + +architecture behaviour of wb_tics is + + constant c_TICS_REG : std_logic_vector(1 downto 0) := "00"; + + signal cntr_div : unsigned(23 downto 0); + signal cntr_tics : unsigned(31 downto 0); + signal cntr_overflow : std_logic; + +begin + + process(clk_sys_i) + begin + if rising_edge(clk_sys_i) then + if(rst_n_i = '0') then + cntr_div <= (others => '0'); + cntr_overflow <= '0'; + else + if(cntr_div = g_period-1) then + cntr_div <= (others => '0'); + cntr_overflow <= '1'; + else + cntr_div <= cntr_div + 1; + cntr_overflow <= '0'; + end if; + end if; + end if; + end process; + + --usec counter + process(clk_sys_i) + begin + if(rising_edge(clk_sys_i)) then + if(rst_n_i = '0') then + cntr_tics <= (others => '0'); + elsif(cntr_overflow = '1') then + cntr_tics <= cntr_tics + 1; + end if; + end if; + end process; + + --Wishbone interface + process(clk_sys_i) + begin + if rising_edge(clk_sys_i) then + if(rst_n_i = '0') then + wb_ack_o <= '0'; + wb_data_o <= (others => '0'); + else + if(wb_stb_i = '1' and wb_cyc_i = '1' and wb_we_i = '0') then + case wb_addr_i is + when c_TICS_REG => + wb_data_o <= std_logic_vector(cntr_tics); + when others => + wb_data_o <= (others => '0'); + end case; + wb_ack_o <= '1'; + else + wb_data_o <= (others => '0'); + wb_ack_o <= '0'; + end if; + end if; + end if; + end process; + +end behaviour; diff --git a/modules/wishbone/wb_uart/build_wb.sh b/modules/wishbone/wb_uart/build_wb.sh new file mode 100755 index 0000000000000000000000000000000000000000..63156eace9bcbee8995dd5f9a6c2420b991593e4 --- /dev/null +++ b/modules/wishbone/wb_uart/build_wb.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +mkdir -p doc +wbgen2 -D ./doc/wb_uart.html -V uart_wb_slave.vhd -C ../../../../software/include/hw/wb_uart.h --cstyle defines --lang vhdl -K ../../../sim/wb_uart_defs.v uart.wb diff --git a/modules/wishbone/wb_uart/manifest.py b/modules/wishbone/wb_uart/manifest.py new file mode 100644 index 0000000000000000000000000000000000000000..5568ec6ab597882a08d8cb4ee403dab120ad6206 --- /dev/null +++ b/modules/wishbone/wb_uart/manifest.py @@ -0,0 +1,5 @@ +files = [ "uart_async_rx.vhd", + "uart_async_tx.vhd", + "uart_baud_gen.vhd", + "uart_wb_slave.vhd", + "wb_simple_uart.vhd"]; diff --git a/modules/wishbone/wb_uart/uart.wb b/modules/wishbone/wb_uart/uart.wb new file mode 100644 index 0000000000000000000000000000000000000000..d211b76af199541744ed3374e25eb0922b71d23d --- /dev/null +++ b/modules/wishbone/wb_uart/uart.wb @@ -0,0 +1,80 @@ +-- -*- Mode: LUA; tab-width: 2 -*- + +peripheral { + name = "Simple Wishbone UART"; + description = "A simple Wishbone UART (8N1 mode) with programmable baud rate. "; + prefix = "UART"; + hdl_entity = "uart_wb_slave"; + + reg { + name = "Status Register"; + prefix = "SR"; + + field { + name = "TX busy"; + description = "1: UART is busy transmitting a byte\n0: UART is idle and ready to transmit next byte"; + prefix = "TX_BUSY"; + type = BIT; + access_bus = READ_ONLY; + access_dev = WRITE_ONLY; + }; + + field { + name = "RX ready"; + description = "1: UART received a byte and its in RXD register\n0: no data in RXD register"; + + prefix = "RX_RDY"; + type = BIT; + access_bus = READ_ONLY; + access_dev = WRITE_ONLY; + }; + + }; + + reg { + name = "Baudrate control register"; + description = "Register controlling the UART baudrate"; + prefix = "BCR"; + + field { + name = "Baudrate divider setting"; + description = "Baudrate setting. The value can be calculated using the following equation:\ + BRATE = ((Baudrate * 8) << 9 + (ClockFreq >> 8)) / (ClockFreq >> 7)"; + size = 32; + type = SLV; + access_bus = READ_WRITE; + access_dev = READ_ONLY; + }; + }; + + reg { + name = "Transmit data regsiter"; + prefix = "TDR"; + + field { + name = "Transmit data"; + prefix = "TX_DATA"; + size = 8; + type = SLV; + access_bus = READ_WRITE; + access_dev = READ_WRITE; + load = LOAD_EXT; + }; + }; + + reg { + name = "Receive data regsiter"; + prefix = "RDR"; + + + field { + ack_read = "rdr_rack_o"; + name = "Received data"; + prefix = "RX_DATA"; + size = 8; + type = SLV; + access_bus = READ_ONLY; + access_dev = WRITE_ONLY; + }; + }; +}; \ No newline at end of file diff --git a/modules/wishbone/wb_uart/uart_async_rx.vhd b/modules/wishbone/wb_uart/uart_async_rx.vhd new file mode 100644 index 0000000000000000000000000000000000000000..34857ad6591508afe8bd5cabd4c66cdfdf4c8398 --- /dev/null +++ b/modules/wishbone/wb_uart/uart_async_rx.vhd @@ -0,0 +1,200 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity uart_async_rx is + + + port ( + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + + baud8_tick_i: in std_logic; + + rxd_i : in std_logic; + rx_ready_o : out std_logic; + rx_error_o : out std_logic; + rx_data_o : out std_logic_vector(7 downto 0) + + ); + +end uart_async_rx; + + +architecture behavioral of uart_async_rx is + + signal Baud8Tick : std_logic; + + signal RxD_sync_inv : std_logic_vector(1 downto 0); + signal RxD_cnt_inv : unsigned(1 downto 0); + signal RxD_bit_inv : std_logic; + + signal state : std_logic_vector(3 downto 0); + signal bit_spacing : std_logic_vector(3 downto 0); + signal next_bit : std_logic; + + signal RxD_data : std_logic_vector(7 downto 0); + signal RxD_data_ready : std_logic; + signal RxD_data_error : std_logic; + + + +begin -- behavioral + + Baud8Tick <= baud8_tick_i; + + + process(clk_sys_i, rst_n_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + RxD_sync_inv <= (others => '0'); + else + if(Baud8Tick = '1') then + RxD_sync_inv <= RxD_sync_inv(0) & (not rxd_i); + end if; + end if; + end if; + end process; + + process(clk_sys_i, rst_n_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + RxD_bit_inv <= '0'; + RxD_cnt_inv <= (others => '0'); + else + if(Baud8Tick = '1') then + if(RxD_sync_inv(1) = '1' and RxD_cnt_inv /= "11") then + RxD_cnt_inv <= RxD_cnt_inv + 1; + elsif (RxD_sync_inv(1) = '0' and RxD_cnt_inv /= "00") then + RxD_cnt_inv <= RxD_cnt_inv - 1; + end if; + + if(RxD_cnt_inv = "00") then + RxD_bit_inv <= '0'; + elsif(RxD_cnt_inv = "11") then + RxD_bit_inv <= '1'; + end if; + end if; + end if; + end if; + end process; + + + next_bit <= '1' when (bit_spacing = x"a") else '0'; + + process(clk_sys_i, rst_n_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + bit_spacing <= (others => '0'); + else + if(state = x"0") then + bit_spacing <= "0000"; + elsif(Baud8Tick = '1') then +-- bit_spacing <= std_logic_vector(resize((unsigned(bit_spacing(2 downto 0)) + 1), 4)) + bit_spacing <= std_logic_vector(unsigned('0' & bit_spacing(2 downto 0)) + 1) + or (bit_spacing(3) & "000"); + end if; + end if; + end if; + end process; + + process(clk_sys_i, rst_n_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + state <= (others => '0'); + else + if(Baud8Tick = '1') then + case state is + when "0000" => + if(RxD_bit_inv = '1') then -- start bit + state <= "1000"; + end if; + when "1000" => + if(next_bit = '1') then + state <= "1001"; -- bit 0 + end if; + when "1001" => + if(next_bit = '1') then + state <= "1010"; -- bit 1 + end if; + when "1010" => + if(next_bit = '1') then + state <= "1011"; -- bit 2 + end if; + when "1011" => + if(next_bit = '1') then + state <= "1100"; -- bit 3 + end if; + when "1100" => + if(next_bit = '1') then + state <= "1101"; -- bit 4 + end if; + when "1101" => + if(next_bit = '1') then + state <= "1110"; -- bit 5 + end if; + when "1110" => + if(next_bit = '1') then + state <= "1111"; -- bit 6 + end if; + when "1111" => + if(next_bit = '1') then + state <= "0001"; -- bit 7 + end if; + when "0001" => + if(next_bit = '1') then + state <= "0000"; -- bit stop + end if; + when others => state <= "0000"; + end case; + end if; + end if; + end if; + end process; + + + process(clk_sys_i, rst_n_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + RxD_data <= (others => '0'); + else + if(Baud8Tick = '1' and next_bit = '1' and state(3) = '1') then + RxD_data <= (not RxD_bit_inv) & RxD_data(7 downto 1); + end if; + end if; + end if; + end process; + + process(clk_sys_i, rst_n_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + RxD_data_error <= '0'; + RxD_data_ready <= '0'; + else + if(Baud8Tick = '1' and next_bit = '1' and state = "0001" and RxD_bit_inv = '0') then + RxD_data_ready <= '1'; + else + RxD_data_ready <= '0'; + end if; + + if(Baud8Tick = '1' and next_bit = '1' and state = "0001" and RxD_bit_inv = '1') then + RxD_data_error <= '1'; + else + RxD_data_error <= '0'; + end if; + end if; + end if; + end process; + + rx_data_o <= RxD_data; + rx_ready_o <= RxD_data_ready; + rx_error_o <= RxD_data_error; + + +end behavioral; diff --git a/modules/wishbone/wb_uart/uart_async_tx.vhd b/modules/wishbone/wb_uart/uart_async_tx.vhd new file mode 100644 index 0000000000000000000000000000000000000000..993fb8573c36adc49b2eaad3f5e079b9d1303de2 --- /dev/null +++ b/modules/wishbone/wb_uart/uart_async_tx.vhd @@ -0,0 +1,161 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity uart_async_tx is + + port ( + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + + baud_tick_i: in std_logic; + + txd_o : out std_logic; + tx_start_p_i : in std_logic; + tx_data_i : in std_logic_vector(7 downto 0); + tx_busy_o : out std_logic + + ); + +end uart_async_tx; + +architecture behavioral of uart_async_tx is + +signal BaudTick : std_logic; + signal TxD_busy : std_logic; + signal TxD_ready : std_logic; + signal state : std_logic_vector(3 downto 0); + + signal TxD_dataReg : std_logic_vector(7 downto 0); + signal TxD_dataD : std_logic_vector(7 downto 0); + signal muxbit : std_logic; + signal TxD : std_logic; + +begin -- behavioral + + + + + TxD_ready <= '1' when state = "0000" else '0'; + TxD_busy <= not TxD_ready; + BaudTick <= baud_tick_i; + + + process(clk_sys_i, rst_n_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + TxD_dataReg <= (others => '0'); + elsif TxD_ready = '1' and tx_start_p_i = '1' then + TxD_dataReg <= tx_data_i; + end if; + end if; + end process; + + TxD_dataD <= TxD_dataReg; + + process(clk_sys_i, rst_n_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + state <= "0000"; + else + case state is + when "0000" => + if (tx_start_p_i = '1') then + state <= "0001"; + end if; + + when "0001" => + if (BaudTick = '1') then + state <= "0100"; + end if; + when "0100" => + if (BaudTick = '1') then + state <= "1000"; + end if; + when "1000" => + if (BaudTick = '1') then + state <= "1001"; + end if; + when "1001" => + if (BaudTick = '1') then + state <= "1010"; + end if; + + when "1010" => + if (BaudTick = '1') then + state <= "1011"; + end if; + when "1011" => + if (BaudTick = '1') then + state <= "1100"; + end if; + when "1100" => + if (BaudTick = '1') then + state <= "1101"; + end if; + when "1101" => + if (BaudTick = '1') then + state <= "1110"; + end if; + when "1110" => + if (BaudTick = '1') then + state <= "1111"; + end if; + + when "1111" => + if (BaudTick = '1') then + state <= "0010"; + end if; + when "0010" => + if (BaudTick = '1') then + state <= "0011"; + end if; + + when "0011" => + if (BaudTick = '1') then + state <= "0000"; + end if; + when others => + state <= "0000"; + end case; + end if; + end if; + end process; + + + process(TxD_dataD, state) + begin + case state(2 downto 0) is + when "000" => muxbit <= TxD_dataD(0); + when "001" => muxbit <= TxD_dataD(1); + when "010" => muxbit <= TxD_dataD(2); + when "011" => muxbit <= TxD_dataD(3); + when "100" => muxbit <= TxD_dataD(4); + when "101" => muxbit <= TxD_dataD(5); + when "110" => muxbit <= TxD_dataD(6); + when "111" => muxbit <= TxD_dataD(7); + when others => null; + end case; + end process; + + process(clk_sys_i, rst_n_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + TxD <= '0'; + else + if(unsigned(state) < to_unsigned(4, state'length) or (state(3) = '1' and muxbit = '1')) then + TxD <= '1'; + else + TxD <= '0'; + end if; + end if; + end if; + end process; + + txd_o <= TxD; + tx_busy_o <= TxD_busy; + +end behavioral; diff --git a/modules/wishbone/wb_uart/uart_baud_gen.vhd b/modules/wishbone/wb_uart/uart_baud_gen.vhd new file mode 100644 index 0000000000000000000000000000000000000000..9bc849724b2a508256a709eddd8150f6aaad572a --- /dev/null +++ b/modules/wishbone/wb_uart/uart_baud_gen.vhd @@ -0,0 +1,60 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity uart_baud_gen is + + generic ( + g_baud_acc_width : integer := 16); + + port ( + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + + baudrate_i : in std_logic_vector(g_baud_acc_width downto 0); + + baud_tick_o : out std_logic; + baud8_tick_o : out std_logic); + +end uart_baud_gen; + +architecture behavioral of uart_baud_gen is + + signal Baud8GeneratorInc : unsigned(g_baud_acc_width downto 0); + signal Baud8GeneratorAcc : unsigned(g_baud_acc_width downto 0); + signal Baud8Tick : std_logic; + signal Baud_sreg : std_logic_vector(7 downto 0); + + +begin -- behavioral + + Baud8GeneratorInc <= unsigned(baudrate_i); + + process(clk_sys_i, rst_n_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + Baud8GeneratorAcc <= (others => '0'); + else + Baud8GeneratorAcc <= ('0' & Baud8GeneratorAcc(Baud8GeneratorAcc'high-1 downto 0)) + Baud8GeneratorInc; + end if; + end if; + end process; + + Baud8Tick <= std_logic(Baud8GeneratorAcc(g_baud_acc_width)); + + process(clk_sys_i, rst_n_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + Baud_sreg <= "10000000"; + elsif Baud8Tick = '1' then + Baud_sreg <= Baud_sreg(0) & Baud_sreg(7 downto 1); + end if; + end if; + end process; + + baud_tick_o <= Baud_sreg(0) and Baud8Tick; + baud8_tick_o <= Baud8Tick; + +end behavioral; diff --git a/modules/wishbone/wb_uart/uart_wb_slave.vhd b/modules/wishbone/wb_uart/uart_wb_slave.vhd new file mode 100644 index 0000000000000000000000000000000000000000..fb2d0e87fa8a5c66b783fc0fc32cf9d1493ba5c8 --- /dev/null +++ b/modules/wishbone/wb_uart/uart_wb_slave.vhd @@ -0,0 +1,228 @@ +--------------------------------------------------------------------------------------- +-- Title : Wishbone slave core for Simple Wishbone UART +--------------------------------------------------------------------------------------- +-- File : uart_wb_slave.vhd +-- Author : auto-generated by wbgen2 from uart.wb +-- Created : Mon Feb 21 10:04:29 2011 +-- Standard : VHDL'87 +--------------------------------------------------------------------------------------- +-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE uart.wb +-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY! +--------------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity uart_wb_slave is + port ( + rst_n_i : in std_logic; + wb_clk_i : in std_logic; + wb_addr_i : in std_logic_vector(1 downto 0); + wb_data_i : in std_logic_vector(31 downto 0); + wb_data_o : out std_logic_vector(31 downto 0); + wb_cyc_i : in std_logic; + wb_sel_i : in std_logic_vector(3 downto 0); + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_ack_o : out std_logic; +-- Port for BIT field: 'TX busy' in reg: 'Status Register' + uart_sr_tx_busy_i : in std_logic; +-- Port for BIT field: 'RX ready' in reg: 'Status Register' + uart_sr_rx_rdy_i : in std_logic; +-- Port for std_logic_vector field: 'Baudrate divider setting' in reg: 'Baudrate control register' + uart_bcr_o : out std_logic_vector(31 downto 0); +-- Port for std_logic_vector field: 'Transmit data' in reg: 'Transmit data regsiter' + uart_tdr_tx_data_o : out std_logic_vector(7 downto 0); + uart_tdr_tx_data_i : in std_logic_vector(7 downto 0); + uart_tdr_tx_data_load_o : out std_logic; +-- Port for std_logic_vector field: 'Received data' in reg: 'Receive data regsiter' + uart_rdr_rx_data_i : in std_logic_vector(7 downto 0); + rdr_rack_o : out std_logic + ); +end uart_wb_slave; + +architecture syn of uart_wb_slave is + +signal uart_bcr_int : std_logic_vector(31 downto 0); +signal ack_sreg : std_logic_vector(9 downto 0); +signal rddata_reg : std_logic_vector(31 downto 0); +signal wrdata_reg : std_logic_vector(31 downto 0); +signal bwsel_reg : std_logic_vector(3 downto 0); +signal rwaddr_reg : std_logic_vector(1 downto 0); +signal ack_in_progress : std_logic ; +signal wr_int : std_logic ; +signal rd_int : std_logic ; +signal bus_clock_int : std_logic ; +signal allones : std_logic_vector(31 downto 0); +signal allzeros : std_logic_vector(31 downto 0); + +begin +-- Some internal signals assignments. For (foreseen) compatibility with other bus standards. + wrdata_reg <= wb_data_i; + bwsel_reg <= wb_sel_i; + bus_clock_int <= wb_clk_i; + rd_int <= wb_cyc_i and (wb_stb_i and (not wb_we_i)); + wr_int <= wb_cyc_i and (wb_stb_i and wb_we_i); + allones <= (others => '1'); + allzeros <= (others => '0'); +-- +-- Main register bank access process. + process (bus_clock_int, rst_n_i) + begin + if (rst_n_i = '0') then + ack_sreg <= "0000000000"; + ack_in_progress <= '0'; + rddata_reg <= "00000000000000000000000000000000"; + uart_bcr_int <= "00000000000000000000000000000000"; + uart_tdr_tx_data_load_o <= '0'; + rdr_rack_o <= '0'; + elsif rising_edge(bus_clock_int) then +-- advance the ACK generator shift register + ack_sreg(8 downto 0) <= ack_sreg(9 downto 1); + ack_sreg(9) <= '0'; + if (ack_in_progress = '1') then + if (ack_sreg(0) = '1') then + uart_tdr_tx_data_load_o <= '0'; + rdr_rack_o <= '0'; + ack_in_progress <= '0'; + else + uart_tdr_tx_data_load_o <= '0'; + end if; + else + if ((wb_cyc_i = '1') and (wb_stb_i = '1')) then + case rwaddr_reg(1 downto 0) is + when "00" => + if (wb_we_i = '1') then + else + rddata_reg(0) <= uart_sr_tx_busy_i; + rddata_reg(1) <= uart_sr_rx_rdy_i; + rddata_reg(2) <= 'X'; + rddata_reg(3) <= 'X'; + rddata_reg(4) <= 'X'; + rddata_reg(5) <= 'X'; + rddata_reg(6) <= 'X'; + rddata_reg(7) <= 'X'; + rddata_reg(8) <= 'X'; + rddata_reg(9) <= 'X'; + rddata_reg(10) <= 'X'; + rddata_reg(11) <= 'X'; + rddata_reg(12) <= 'X'; + rddata_reg(13) <= 'X'; + rddata_reg(14) <= 'X'; + rddata_reg(15) <= 'X'; + rddata_reg(16) <= 'X'; + rddata_reg(17) <= 'X'; + rddata_reg(18) <= 'X'; + rddata_reg(19) <= 'X'; + rddata_reg(20) <= 'X'; + rddata_reg(21) <= 'X'; + rddata_reg(22) <= 'X'; + rddata_reg(23) <= 'X'; + rddata_reg(24) <= 'X'; + rddata_reg(25) <= 'X'; + rddata_reg(26) <= 'X'; + rddata_reg(27) <= 'X'; + rddata_reg(28) <= 'X'; + rddata_reg(29) <= 'X'; + rddata_reg(30) <= 'X'; + rddata_reg(31) <= 'X'; + end if; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when "01" => + if (wb_we_i = '1') then + uart_bcr_int <= wrdata_reg(31 downto 0); + else + rddata_reg(31 downto 0) <= uart_bcr_int; + end if; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when "10" => + if (wb_we_i = '1') then + uart_tdr_tx_data_load_o <= '1'; + else + rddata_reg(7 downto 0) <= uart_tdr_tx_data_i; + rddata_reg(8) <= 'X'; + rddata_reg(9) <= 'X'; + rddata_reg(10) <= 'X'; + rddata_reg(11) <= 'X'; + rddata_reg(12) <= 'X'; + rddata_reg(13) <= 'X'; + rddata_reg(14) <= 'X'; + rddata_reg(15) <= 'X'; + rddata_reg(16) <= 'X'; + rddata_reg(17) <= 'X'; + rddata_reg(18) <= 'X'; + rddata_reg(19) <= 'X'; + rddata_reg(20) <= 'X'; + rddata_reg(21) <= 'X'; + rddata_reg(22) <= 'X'; + rddata_reg(23) <= 'X'; + rddata_reg(24) <= 'X'; + rddata_reg(25) <= 'X'; + rddata_reg(26) <= 'X'; + rddata_reg(27) <= 'X'; + rddata_reg(28) <= 'X'; + rddata_reg(29) <= 'X'; + rddata_reg(30) <= 'X'; + rddata_reg(31) <= 'X'; + end if; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when "11" => + if (wb_we_i = '1') then + else + rddata_reg(7 downto 0) <= uart_rdr_rx_data_i; + rdr_rack_o <= '1'; + rddata_reg(8) <= 'X'; + rddata_reg(9) <= 'X'; + rddata_reg(10) <= 'X'; + rddata_reg(11) <= 'X'; + rddata_reg(12) <= 'X'; + rddata_reg(13) <= 'X'; + rddata_reg(14) <= 'X'; + rddata_reg(15) <= 'X'; + rddata_reg(16) <= 'X'; + rddata_reg(17) <= 'X'; + rddata_reg(18) <= 'X'; + rddata_reg(19) <= 'X'; + rddata_reg(20) <= 'X'; + rddata_reg(21) <= 'X'; + rddata_reg(22) <= 'X'; + rddata_reg(23) <= 'X'; + rddata_reg(24) <= 'X'; + rddata_reg(25) <= 'X'; + rddata_reg(26) <= 'X'; + rddata_reg(27) <= 'X'; + rddata_reg(28) <= 'X'; + rddata_reg(29) <= 'X'; + rddata_reg(30) <= 'X'; + rddata_reg(31) <= 'X'; + end if; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when others => +-- prevent the slave from hanging the bus on invalid address + ack_in_progress <= '1'; + ack_sreg(0) <= '1'; + end case; + end if; + end if; + end if; + end process; + + +-- Drive the data output bus + wb_data_o <= rddata_reg; +-- TX busy +-- RX ready +-- Baudrate divider setting + uart_bcr_o <= uart_bcr_int; +-- Transmit data + uart_tdr_tx_data_o <= wrdata_reg(7 downto 0); +-- Received data + rwaddr_reg <= wb_addr_i; +-- ACK signal generation. Just pass the LSB of ACK counter. + wb_ack_o <= ack_sreg(0); +end syn; diff --git a/modules/wishbone/wb_uart/wb_simple_uart.vhd b/modules/wishbone/wb_uart/wb_simple_uart.vhd new file mode 100644 index 0000000000000000000000000000000000000000..437a4f15e2ade0133f54954d0db9763271beab02 --- /dev/null +++ b/modules/wishbone/wb_uart/wb_simple_uart.vhd @@ -0,0 +1,192 @@ +------------------------------------------------------------------------------- +-- Title : Wishbone UART for WR Core +-- Project : WhiteRabbit +------------------------------------------------------------------------------- +-- File : wb_conmax_top.vhd +-- Author : Tomasz Wlostowski +-- Company : CERN BE-Co-HT +-- Created : 2011-02-21 +-- Last update: 2011-02-21 +-- Platform : FPGA-generics +-- Standard : VHDL +------------------------------------------------------------------------------- +-- Description: +-- Simple UART port with Wishbone interface +-- +------------------------------------------------------------------------------- +-- Copyright (c) 2011 Tomasz Wlostowski +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2011-02-21 1.0 twlostow Created +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity wb_simple_uart is + port ( + + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + + wb_addr_i : in std_logic_vector(1 downto 0); + wb_data_i : in std_logic_vector(31 downto 0); + wb_data_o : out std_logic_vector(31 downto 0); + wb_cyc_i : in std_logic; + wb_sel_i : in std_logic_vector(3 downto 0); + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_ack_o : out std_logic; + + uart_rxd_i : in std_logic; + uart_txd_o : out std_logic + ); +end wb_simple_uart; + +architecture syn of wb_simple_uart is + + constant c_baud_acc_width : integer := 16; + + component uart_wb_slave + port ( + rst_n_i : in std_logic; + wb_clk_i : in std_logic; + wb_addr_i : in std_logic_vector(1 downto 0); + wb_data_i : in std_logic_vector(31 downto 0); + wb_data_o : out std_logic_vector(31 downto 0); + wb_cyc_i : in std_logic; + wb_sel_i : in std_logic_vector(3 downto 0); + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_ack_o : out std_logic; + uart_sr_tx_busy_i : in std_logic; + uart_sr_rx_rdy_i : in std_logic; + uart_bcr_o : out std_logic_vector(31 downto 0); + uart_tdr_tx_data_o : out std_logic_vector(7 downto 0); + uart_tdr_tx_data_i : in std_logic_vector(7 downto 0); + uart_tdr_tx_data_load_o : out std_logic; + + uart_rdr_rx_data_i : in std_logic_vector(7 downto 0); + rdr_rack_o : out std_logic); + end component; + + component uart_baud_gen + generic ( + g_baud_acc_width : integer); + port ( + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + baudrate_i : in std_logic_vector(g_baud_acc_width downto 0); + baud_tick_o : out std_logic; + baud8_tick_o : out std_logic); + end component; + + + component uart_async_rx + port ( + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + baud8_tick_i : in std_logic; + rxd_i : in std_logic; + rx_ready_o : out std_logic; + rx_error_o : out std_logic; + rx_data_o : out std_logic_vector(7 downto 0)); + end component; + + component uart_async_tx + port ( + clk_sys_i : in std_logic; + rst_n_i : in std_logic; + baud_tick_i : in std_logic; + txd_o : out std_logic; + tx_start_p_i : in std_logic; + tx_data_i : in std_logic_vector(7 downto 0); + tx_busy_o : out std_logic); + end component; + + signal rx_ready_reg : std_logic; + signal rx_ready : std_logic; + signal uart_sr_tx_busy : std_logic; + signal uart_sr_rx_rdy : std_logic; + signal uart_bcr : std_logic_vector(31 downto 0); + + signal uart_tdr_tx_data : std_logic_vector(7 downto 0); + signal uart_tdr_tx_data_load : std_logic; + + signal uart_rdr_rx_data : std_logic_vector(7 downto 0); + signal rdr_rack : std_logic; + + signal baud_tick : std_logic; + signal baud_tick8 : std_logic; + +begin -- syn + + BAUD_GEN : uart_baud_gen + generic map ( + g_baud_acc_width => c_baud_acc_width) + port map ( + clk_sys_i => clk_sys_i, + rst_n_i => rst_n_i, + baudrate_i => uart_bcr(c_baud_acc_width downto 0), + baud_tick_o => baud_tick, + baud8_tick_o => baud_tick8); + + TX : uart_async_tx + port map ( + clk_sys_i => clk_sys_i, + rst_n_i => rst_n_i, + baud_tick_i => baud_tick, + txd_o => uart_txd_o, + tx_start_p_i => uart_tdr_tx_data_load, + tx_data_i => uart_tdr_tx_data, + tx_busy_o => uart_sr_tx_busy); + + RX : uart_async_rx + port map ( + clk_sys_i => clk_sys_i, + rst_n_i => rst_n_i, + baud8_tick_i => baud_tick8, + rxd_i => uart_rxd_i, + rx_ready_o => rx_ready, + rx_error_o => open, + rx_data_o => uart_rdr_rx_data); + + WB_SLAVE : uart_wb_slave + port map ( + rst_n_i => rst_n_i, + wb_clk_i => clk_sys_i, + wb_addr_i => wb_addr_i, + wb_data_i => wb_data_i, + wb_data_o => wb_data_o, + wb_cyc_i => wb_cyc_i, + wb_sel_i => wb_sel_i, + wb_stb_i => wb_stb_i, + wb_we_i => wb_we_i, + wb_ack_o => wb_ack_o, + + uart_sr_tx_busy_i => uart_sr_tx_busy, + uart_sr_rx_rdy_i => uart_sr_rx_rdy, + uart_bcr_o => uart_bcr, + uart_tdr_tx_data_o => uart_tdr_tx_data, + uart_tdr_tx_data_i => uart_tdr_tx_data, + uart_tdr_tx_data_load_o => uart_tdr_tx_data_load, + uart_rdr_rx_data_i => uart_rdr_rx_data, + rdr_rack_o => rdr_rack); + + process(clk_sys_i, rst_n_i) + begin + if rising_edge(clk_sys_i) then + if rst_n_i = '0' then + uart_sr_rx_rdy <= '0'; + else + if(rx_ready = '1') then + uart_sr_rx_rdy <= '1'; + elsif(rdr_rack = '1') then + uart_sr_rx_rdy <= '0'; + end if; + end if; + end if; + end process; + +end syn; diff --git a/modules/wishbone/wb_vic/Manifest.py b/modules/wishbone/wb_vic/Manifest.py new file mode 100644 index 0000000000000000000000000000000000000000..bc01174c21a939baf6f73301cde152b01c37e158 --- /dev/null +++ b/modules/wishbone/wb_vic/Manifest.py @@ -0,0 +1,3 @@ +files = ["vic_prio_enc.vhd", + "wb_slave_vic.wb", + "wb_vic.vhd"] \ No newline at end of file diff --git a/modules/wishbone/wb_vic/vic_prio_enc.vhd b/modules/wishbone/wb_vic/vic_prio_enc.vhd new file mode 100644 index 0000000000000000000000000000000000000000..4e2c1328edb2367ae77b7edccb2b98f2accf7451 --- /dev/null +++ b/modules/wishbone/wb_vic/vic_prio_enc.vhd @@ -0,0 +1,88 @@ +library ieee; +use ieee.std_logic_1164.all; + +entity vic_prio_enc is + + port ( + in_i : in std_logic_vector(31 downto 0); + out_o : out std_logic_vector(4 downto 0) + ); + +end vic_prio_enc; + +architecture syn of vic_prio_enc is + +begin -- syn + + prencode : process (in_i) + begin -- process prencode + if in_i(0) = '1' then + out_o <= "00000"; + elsif in_i(1) = '1' then + out_o <= "00001"; + elsif in_i(2) = '1' then + out_o <= "00010"; + elsif in_i(3) = '1' then + out_o <= "00011"; + elsif in_i(4) = '1' then + out_o <= "00100"; + elsif in_i(5) = '1' then + out_o <= "00101"; + elsif in_i(6) = '1' then + out_o <= "00110"; + elsif in_i(7) = '1' then + out_o <= "00111"; + elsif in_i(8+0) = '1' then + out_o <= "01000"; + elsif in_i(8+1) = '1' then + out_o <= "01001"; + elsif in_i(8+2) = '1' then + out_o <= "01010"; + elsif in_i(8+3) = '1' then + out_o <= "01011"; + elsif in_i(8+4) = '1' then + out_o <= "01100"; + elsif in_i(8+5) = '1' then + out_o <= "01101"; + elsif in_i(8+6) = '1' then + out_o <= "01110"; + elsif in_i(8+7) = '1' then + out_o <= "01111"; + elsif in_i(16+0) = '1' then + out_o <= "10000"; + elsif in_i(16+1) = '1' then + out_o <= "10001"; + elsif in_i(16+2) = '1' then + out_o <= "10010"; + elsif in_i(16+3) = '1' then + out_o <= "10011"; + elsif in_i(16+4) = '1' then + out_o <= "10100"; + elsif in_i(16+5) = '1' then + out_o <= "10101"; + elsif in_i(16+6) = '1' then + out_o <= "10110"; + elsif in_i(16+7) = '1' then + out_o <= "10111"; + elsif in_i(24+0) = '1' then + out_o <= "11000"; + elsif in_i(24+1) = '1' then + out_o <= "11001"; + elsif in_i(24+2) = '1' then + out_o <= "11010"; + elsif in_i(24+3) = '1' then + out_o <= "11011"; + elsif in_i(24+4) = '1' then + out_o <= "11100"; + elsif in_i(24+5) = '1' then + out_o <= "11101"; + elsif in_i(24+6) = '1' then + out_o <= "11110"; + elsif in_i(24+7) = '1' then + out_o <= "11111"; + else + out_o <= "XXXXX"; + end if; + end process prencode; + +end syn; diff --git a/modules/wishbone/wb_vic/wb_slave_vic.wb b/modules/wishbone/wb_vic/wb_slave_vic.wb new file mode 100644 index 0000000000000000000000000000000000000000..06499dba79e20d0ea889c176c25a43e9cfd9ca86 --- /dev/null +++ b/modules/wishbone/wb_vic/wb_slave_vic.wb @@ -0,0 +1,132 @@ +-- -*- Mode: LUA; tab-width: 2 -*- + +peripheral { + name = "Vectored Interrupt Controller (VIC)"; + description = "Module implementing a 2 to 32-input prioritized interrupt controller with internal interrupt vector storage support."; + prefix = "VIC"; + hdl_entity = "wb_slave_vic"; + + reg { + name = "VIC Control Register"; + prefix = "CTL"; + + field { + name = "VIC Enable"; + description = "1: enables VIC operation\n0: disables VIC operation"; + prefix = "ENABLE"; + type = BIT; + access_dev = READ_ONLY; + access_bus = READ_WRITE; + }; + + field { + name = "VIC output polarity"; + description = "1: IRQ output is active high\n0: IRQ output is active low"; + prefix = "POL"; + type = BIT; + access_dev = READ_ONLY; + access_bus = READ_WRITE; + }; + }; + + reg { + name = "Raw Interrupt Status Register"; + prefix = "RISR"; + + field { + name = "Raw interrupt status"; + description = "Each bit reflects the current state of corresponding IRQ input line.\nread 1: interrupt line is currently active\nread 0: interrupt line is inactive"; + type = SLV; + size = 32; + access_dev = WRITE_ONLY; + access_bus = READ_ONLY; + }; + }; + + reg { + name = "Interrupt Enable Register"; + prefix = "IER"; + + field { + name = "Enable IRQ"; + description = "Write 1: enables interrupt associated with written bit\nWrite 0: no effect"; + type = PASS_THROUGH; + size = 32; + }; + }; + + reg { + name = "Interrupt Disable Register"; + prefix = "IDR"; + + field { + name = "Disable IRQ"; + description = "Write 1: enables interrupt associated with written bit\nWrite 0: no effect"; + type = PASS_THROUGH; + size = 32; + }; + }; + + reg { + name = "Interrupt Mask Register"; + prefix = "IMR"; + + field { + name = "IRQ disabled/enabled"; + description = "Read 1: interrupt associated with bitfield is enabled\nRead 0: interrupt is disabled"; + type = SLV; + size = 32; + access_bus = READ_ONLY; + access_dev = WRITE_ONLY; + }; + }; + + reg { + name = "Vector Address Register"; + prefix = "VAR"; + + field { + name = "Vector Address"; + description = "Address of pending interrupt vector, read from Interrupt Vector Table"; + type = SLV; + size = 32; + access_bus = READ_ONLY; + access_dev = WRITE_ONLY; + }; + }; + + reg { + name = "Software Interrupt Register"; + description = "Writing 1 to one of bits of this register causes a software emulation of the respective interrupt."; + prefix = "SWIR"; + field { + name = "SWI interrupt mask"; + type = PASS_THROUGH; + size = 32; + }; + }; + + reg { + name = "End Of Interrupt Acknowledge Register"; + prefix = "EOIR"; + + field { + name = "End of Interrupt"; + description = "Any write operation acknowledges the pending interrupt. Then, VIC advances to another pending interrupt(s)."; + type = PASS_THROUGH; + size = 32; + }; + }; + + ram { + name = "Interrupt Vector Table"; + description = "Vector Address Table. Word at offset N stores the vector address of IRQ N. When interrupt is requested, VIC reads it's vector address from this memory and stores it in VAR register."; + prefix = "IVT_RAM"; + + size = 32; + width = 32; + + access_bus = READ_WRITE; + access_dev = READ_ONLY; + }; +}; \ No newline at end of file diff --git a/modules/wishbone/wb_vic/wb_vic.vhd b/modules/wishbone/wb_vic/wb_vic.vhd new file mode 100644 index 0000000000000000000000000000000000000000..8cd519631f05ca6dd0a4dc52116733ce3d47b895 --- /dev/null +++ b/modules/wishbone/wb_vic/wb_vic.vhd @@ -0,0 +1,289 @@ +------------------------------------------------------------------------------ +-- Title : Wishbone Vectored Interrupt Controller +-- Project : White Rabbit Switch +------------------------------------------------------------------------------ +-- Author : Tomasz Wlostowski +-- Company : CERN BE-Co-HT +-- Created : 2010-05-18 +-- Last update: 2010-07-29 +-- Platform : FPGA-generic +-- Standard : VHDL'87 +------------------------------------------------------------------------------- +-- Description: Simple interrupt controller/multiplexer: +-- - designed to cooperate with wbgen2 peripherals Embedded Interrupt +-- Controllers (EICs) +-- - accepts 2 to 32 inputs (configurable using g_num_interrupts) +-- - inputs are high-level sensitive +-- - inputs have fixed priorities. Input 0 has the highest priority, Input +-- g_num_interrupts-1 has the lowest priority. +-- - output interrupt line (to the CPU) is active low or high depending on +-- a configuration bit. +-- - interrupt is acknowledged by writing to EIC_EOIR register. +-- - register layout: see wb_vic.wb for details. +------------------------------------------------------------------------------- +-- Copyright (c) 2010 Tomasz Wlostowski +------------------------------------------------------------------------------- +-- Revisions : +-- Date Version Author Description +-- 2010-05-18 1.0 twlostow Created +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; +use work.wishbone_pkg.all; + +entity wb_vic is + + generic ( + g_num_interrupts : natural := 32 -- number of IRQ inputs. + ); + + port ( + rst_n_i : in std_logic; -- reset + wb_clk_i : in std_logic; -- wishbone clock + + wb_addr_i : in std_logic_vector(5 downto 0); + wb_data_i : in std_logic_vector(31 downto 0); + wb_data_o : out std_logic_vector(31 downto 0); + wb_cyc_i : in std_logic; + wb_sel_i : in std_logic_vector(3 downto 0); + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_ack_o : out std_logic; + + irqs_i : in std_logic_vector(g_num_interrupts-1 downto 0); -- IRQ inputs + irq_master_o : out std_logic -- master IRQ output (multiplexed line, + -- to the CPU) + ); + +end wb_vic; + + +architecture syn of wb_vic is + + component vic_prio_enc + port ( + in_i : in std_logic_vector(31 downto 0); + out_o : out std_logic_vector(4 downto 0)); + end component; + + component wb_slave_vic + port ( + rst_n_i : in std_logic; + wb_clk_i : in std_logic; + wb_addr_i : in std_logic_vector(5 downto 0); + wb_data_i : in std_logic_vector(31 downto 0); + wb_data_o : out std_logic_vector(31 downto 0); + wb_cyc_i : in std_logic; + wb_sel_i : in std_logic_vector(3 downto 0); + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_ack_o : out std_logic; + vic_ctl_enable_o : out std_logic; + vic_ctl_pol_o : out std_logic; + vic_risr_i : in std_logic_vector(31 downto 0); + vic_ier_o : out std_logic_vector(31 downto 0); + vic_ier_wr_o : out std_logic; + vic_idr_o : out std_logic_vector(31 downto 0); + vic_idr_wr_o : out std_logic; + vic_imr_i : in std_logic_vector(31 downto 0); + vic_var_i : in std_logic_vector(31 downto 0); + vic_swir_o : out std_logic_vector(31 downto 0); + vic_swir_wr_o : out std_logic; + vic_eoir_o : out std_logic_vector(31 downto 0); + vic_eoir_wr_o : out std_logic; + vic_ivt_ram_addr_i : in std_logic_vector(4 downto 0); + vic_ivt_ram_data_o : out std_logic_vector(31 downto 0); + vic_ivt_ram_rd_i : in std_logic); + end component; + + type t_state is (WAIT_IRQ, PROCESS_IRQ, WAIT_ACK, WAIT_MEM, WAIT_IDLE); + + signal irqs_i_reg : std_logic_vector(32 downto 0); + + signal vic_ctl_enable : std_logic; + signal vic_ctl_pol : std_logic; + signal vic_risr : std_logic_vector(31 downto 0); + signal vic_ier : std_logic_vector(31 downto 0); + signal vic_ier_wr : std_logic; + signal vic_idr : std_logic_vector(31 downto 0); + signal vic_idr_wr : std_logic; + signal vic_imr : std_logic_vector(31 downto 0); + signal vic_var : std_logic_vector(31 downto 0); + signal vic_eoir : std_logic_vector(31 downto 0); + signal vic_eoir_wr : std_logic; + signal vic_ivt_ram_addr : std_logic_vector(4 downto 0); + signal vic_ivt_ram_data : std_logic_vector(31 downto 0); + signal vic_ivt_ram_rd : std_logic; + + signal vic_swir : std_logic_vector(31 downto 0); + signal vic_swir_wr : std_logic; + + signal got_irq : std_logic; + signal swi_mask : std_logic_vector(31 downto 0); + + signal current_irq : std_logic_vector(4 downto 0); + signal irq_id_encoded : std_logic_vector(4 downto 0); + signal state : t_state; + +begin -- syn + + check1 : if (g_num_interrupts < 2 or g_num_interrupts > 32) generate + assert true report "invalid number of interrupts" severity failure; + end generate check1; + + + register_irq_lines : process(wb_clk_i, rst_n_i) + begin + if rising_edge(wb_clk_i) then + if rst_n_i = '0' then + irqs_i_reg <= (others => '0'); + else + + irqs_i_reg(g_num_interrupts-1 downto 0) <= (irqs_i or swi_mask(g_num_interrupts-1 downto 0)) and vic_imr(g_num_interrupts-1 downto 0); + + irqs_i_reg(32 downto g_num_interrupts) <= (others => '0'); + end if; + end if; + end process; + + + vic_risr <= irqs_i_reg(31 downto 0); + + priority_encoder : vic_prio_enc + port map ( + in_i => irqs_i_reg(31 downto 0), + out_o => irq_id_encoded); + + vic_ivt_ram_addr <= current_irq; + + wb_controller : wb_slave_vic + port map ( + rst_n_i => rst_n_i, + wb_clk_i => wb_clk_i, + wb_addr_i => wb_addr_i, + wb_data_i => wb_data_i, + wb_data_o => wb_data_o, + wb_cyc_i => wb_cyc_i, + wb_sel_i => wb_sel_i, + wb_stb_i => wb_stb_i, + wb_we_i => wb_we_i, + wb_ack_o => wb_ack_o, + + vic_ctl_enable_o => vic_ctl_enable, + vic_ctl_pol_o => vic_ctl_pol, + vic_risr_i => vic_risr, + vic_ier_o => vic_ier, + vic_ier_wr_o => vic_ier_wr, + vic_idr_o => vic_idr, + vic_idr_wr_o => vic_idr_wr, + vic_imr_i => vic_imr, + vic_var_i => vic_var, + vic_eoir_o => vic_eoir, + vic_eoir_wr_o => vic_eoir_wr, + vic_swir_o => vic_swir, + vic_swir_wr_o => vic_swir_wr, + vic_ivt_ram_addr_i => vic_ivt_ram_addr, + vic_ivt_ram_data_o => vic_ivt_ram_data, + vic_ivt_ram_rd_i => vic_ivt_ram_rd); + + process (wb_clk_i, rst_n_i) + begin -- process enable_disable_irqs + if rising_edge(wb_clk_i) then + + if rst_n_i = '0' then -- asynchronous reset (active low) + vic_imr <= (others => '0'); + else + + if(vic_ier_wr = '1') then + for i in 0 to g_num_interrupts-1 loop + if(vic_ier(i) = '1') then + vic_imr(i) <= '1'; + end if; + end loop; -- i + end if; + + if(vic_idr_wr = '1') then + for i in 0 to g_num_interrupts-1 loop + if(vic_idr(i) = '1') then + vic_imr(i) <= '0'; + end if; + end loop; -- i + end if; + + end if; + end if; + end process; + + vic_fsm : process (wb_clk_i, rst_n_i) + begin -- process vic_fsm + if rising_edge(wb_clk_i) then + + if rst_n_i = '0' then -- asynchronous reset (active low) + state <= WAIT_IRQ; + vic_ivt_ram_rd <= '0'; + current_irq <= (others => '0'); + irq_master_o <= '0'; + vic_var <= x"12345678"; + swi_mask <= (others => '0'); + + else + if(vic_ctl_enable = '0') then + irq_master_o <= not vic_ctl_pol; + vic_ivt_ram_rd <= '0'; + current_irq <= (others => '0'); + state <= WAIT_IRQ; + vic_var <= x"12345678"; + swi_mask <= (others => '0'); + else + + if(vic_swir_wr = '1') then -- handle the software IRQs + swi_mask <= vic_swir; + end if; + + case state is + when WAIT_IRQ => + if(irqs_i_reg /= std_logic_vector(to_unsigned(0, irqs_i_reg'length))) then + current_irq <= irq_id_encoded; + state <= WAIT_MEM; + vic_ivt_ram_rd <= '1'; + +-- assert the master IRQ line + else +-- no interrupts? de-assert the IRQ line + irq_master_o <= not vic_ctl_pol; + vic_var <= (others => '0'); + end if; + + when WAIT_MEM => + state <= PROCESS_IRQ; + + when PROCESS_IRQ => +-- fetch the vector address from vector table and load it into VIC_VAR register + vic_var <= vic_ivt_ram_data; + vic_ivt_ram_rd <= '0'; + state <= WAIT_ACK; + irq_master_o <= vic_ctl_pol; + + when WAIT_ACK => +-- got write operation to VIC_EOIR register? if yes, advance to next interrupt. + + if(vic_eoir_wr = '1') then + state <= WAIT_IDLE; + swi_mask <= (others => '0'); + end if; + + when WAIT_IDLE => + state <= WAIT_IRQ; + + end case; + end if; + end if; + end if; + end process vic_fsm; + + +end syn; diff --git a/modules/wishbone/wb_virtual_uart/manifest.py b/modules/wishbone/wb_virtual_uart/manifest.py new file mode 100644 index 0000000000000000000000000000000000000000..9c9fdb422743c116ca5658477060e7945627142c --- /dev/null +++ b/modules/wishbone/wb_virtual_uart/manifest.py @@ -0,0 +1,2 @@ +files = ["wb_virtual_uart.vhd", + "wb_virtual_uart_slave.vhd" ]; diff --git a/modules/wishbone/wb_virtual_uart/wb_virtual_uart.vhd b/modules/wishbone/wb_virtual_uart/wb_virtual_uart.vhd new file mode 100644 index 0000000000000000000000000000000000000000..bf40a2031063c3ea98e9ace470957a0c0d231d18 --- /dev/null +++ b/modules/wishbone/wb_virtual_uart/wb_virtual_uart.vhd @@ -0,0 +1,92 @@ +library ieee; +use ieee.std_logic_1164.all; + +entity wb_virtual_uart is + port( + rst_n_i : in std_logic; + clk_sys_i : in std_logic; + wb_addr_i : in std_logic_vector(2 downto 0); + wb_data_i : in std_logic_vector(31 downto 0); + wb_data_o : out std_logic_vector(31 downto 0); + wb_cyc_i : in std_logic; + wb_sel_i : in std_logic_vector(3 downto 0); + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_ack_o : out std_logic + ); +end wb_virtual_uart; + +architecture struct of wb_virtual_uart is + + component wb_virtual_uart_slave + port ( + rst_n_i : in std_logic; + wb_clk_i : in std_logic; + wb_addr_i : in std_logic_vector(2 downto 0); + wb_data_i : in std_logic_vector(31 downto 0); + wb_data_o : out std_logic_vector(31 downto 0); + wb_cyc_i : in std_logic; + wb_sel_i : in std_logic_vector(3 downto 0); + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_ack_o : out std_logic; + uart_sr_tx_busy_i : in std_logic; + uart_sr_rx_rdy_i : in std_logic; + uart_bcr_o : out std_logic_vector(31 downto 0); + uart_tdr_tx_data_o : out std_logic_vector(7 downto 0); + uart_tdr_tx_data_i : in std_logic_vector(7 downto 0); + uart_tdr_tx_data_load_o : out std_logic; + uart_rdr_rx_data_i : in std_logic_vector(7 downto 0); + rdr_rack_o : out std_logic; + uart_debug_wr_req_i : in std_logic; + uart_debug_wr_full_o : out std_logic; + uart_debug_wr_empty_o : out std_logic; + uart_debug_wr_usedw_o : out std_logic_vector(7 downto 0); + uart_debug_tx_i : in std_logic_vector(7 downto 0); + uart_debug_dupa_i : in std_logic_vector(31 downto 0)); + end component; + + + signal tx_data : std_logic_vector(7 downto 0); + signal tx_data_load : std_logic; + signal tdr_load : std_logic; + signal fifo_full : std_logic; + +begin + + tx_data_load <= (not fifo_full) and tdr_load; + + WB_SLAVE: wb_virtual_uart_slave + port map( + rst_n_i => rst_n_i, + wb_clk_i => clk_sys_i, + wb_addr_i => wb_addr_i, + wb_data_i => wb_data_i, + wb_data_o => wb_data_o, + wb_cyc_i => wb_cyc_i, + wb_sel_i => wb_sel_i, + wb_stb_i => wb_stb_i, + wb_we_i => wb_we_i, + wb_ack_o => wb_ack_o, + uart_sr_tx_busy_i => '0', + uart_sr_rx_rdy_i => '0', + uart_bcr_o => open, + uart_tdr_tx_data_o => tx_data, + uart_tdr_tx_data_i => x"00", + uart_tdr_tx_data_load_o => tdr_load, + uart_rdr_rx_data_i => x"00", + rdr_rack_o => open, + -- FIFO write request + uart_debug_wr_req_i => tx_data_load, + -- FIFO full flag + uart_debug_wr_full_o => fifo_full, + -- FIFO empty flag + uart_debug_wr_empty_o => open, + -- FIFO number of used words + uart_debug_wr_usedw_o => open, + uart_debug_tx_i => tx_data, + uart_debug_dupa_i => x"00000000" + ); + + +end struct; diff --git a/modules/wishbone/wb_virtual_uart/wb_virtual_uart.wb b/modules/wishbone/wb_virtual_uart/wb_virtual_uart.wb new file mode 100644 index 0000000000000000000000000000000000000000..eb7fffa9910ffd1acd2356211e969f88ea5baf26 --- /dev/null +++ b/modules/wishbone/wb_virtual_uart/wb_virtual_uart.wb @@ -0,0 +1,105 @@ +-- -*- Mode: LUA; tab-width: 2 -*- + +peripheral { + name = "Virtual UART"; + description = "A simple Wishbone FIFO that acts as UART"; + prefix = "UART"; + hdl_entity = "wb_virtual_uart_slave"; + + reg { + name = "Status Register"; + prefix = "SR"; + + field { + name = "TX busy"; + description = "1: UART is busy transmitting a byte\n0: UART is idle and ready to transmit next byte"; + prefix = "TX_BUSY"; + type = BIT; + access_bus = READ_ONLY; + access_dev = WRITE_ONLY; + }; + + field { + name = "RX ready"; + description = "1: UART received a byte and its in RXD register\n0: no data in RXD register"; + + prefix = "RX_RDY"; + type = BIT; + access_bus = READ_ONLY; + access_dev = WRITE_ONLY; + }; + + }; + + reg { + name = "Baudrate control register"; + description = "Register controlling the UART baudrate"; + prefix = "BCR"; + + field { + name = "Baudrate divider setting"; + description = "Baudrate setting. The value can be calculated using the following equation:\ + BRATE = ((Baudrate * 8) << 9 + (ClockFreq >> 8)) / (ClockFreq >> 7)"; + size = 32; + type = SLV; + access_bus = READ_WRITE; + access_dev = READ_ONLY; + }; + }; + + reg { + name = "Transmit data regsiter"; + prefix = "TDR"; + + field { + name = "Transmit data"; + prefix = "TX_DATA"; + size = 8; + type = SLV; + access_bus = READ_WRITE; + access_dev = READ_WRITE; + load = LOAD_EXT; + }; + }; + + reg { + name = "Receive data regsiter"; + prefix = "RDR"; + + + field { + ack_read = "rdr_rack_o"; + name = "Received data"; + prefix = "RX_DATA"; + size = 8; + type = SLV; + access_bus = READ_ONLY; + access_dev = WRITE_ONLY; + }; + }; + + fifo_reg { + size = 2048; + direction = CORE_TO_BUS; + prefix = "debug"; + name = "UART TX FIFO"; + description = "This FIFO holds the TX chars that UART tries to send away"; + flags_bus = {FIFO_FULL, FIFO_EMPTY, FIFO_COUNT}; + flags_dev = {FIFO_FULL, FIFO_EMPTY, FIFO_COUNT}; + + field { + name = "Char sent by UART to TX"; + prefix = "tx"; + type = SLV; + size = 8; + }; + + field { + name = "Dupa"; + prefix = "dupa"; + type = SLV; + size = 32; + }; + + }; +}; diff --git a/modules/wishbone/wb_virtual_uart/wb_virtual_uart_slave.vhd b/modules/wishbone/wb_virtual_uart/wb_virtual_uart_slave.vhd new file mode 100644 index 0000000000000000000000000000000000000000..517b770cf73b591bbe3863bb633f956b1ac392c4 --- /dev/null +++ b/modules/wishbone/wb_virtual_uart/wb_virtual_uart_slave.vhd @@ -0,0 +1,353 @@ +--------------------------------------------------------------------------------------- +-- Title : Wishbone slave core for Virtual UART +--------------------------------------------------------------------------------------- +-- File : wb_virtual_uart_slave.vhd +-- Author : auto-generated by wbgen2 from wb_virtual_uart.wb +-- Created : Sun Apr 10 20:25:49 2011 +-- Standard : VHDL'87 +--------------------------------------------------------------------------------------- +-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wb_virtual_uart.wb +-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY! +--------------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +library wbgen2; +use wbgen2.wbgen2_pkg.all; + +entity wb_virtual_uart_slave is + port ( + rst_n_i : in std_logic; + wb_clk_i : in std_logic; + wb_addr_i : in std_logic_vector(2 downto 0); + wb_data_i : in std_logic_vector(31 downto 0); + wb_data_o : out std_logic_vector(31 downto 0); + wb_cyc_i : in std_logic; + wb_sel_i : in std_logic_vector(3 downto 0); + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_ack_o : out std_logic; +-- Port for BIT field: 'TX busy' in reg: 'Status Register' + uart_sr_tx_busy_i : in std_logic; +-- Port for BIT field: 'RX ready' in reg: 'Status Register' + uart_sr_rx_rdy_i : in std_logic; +-- Port for std_logic_vector field: 'Baudrate divider setting' in reg: 'Baudrate control register' + uart_bcr_o : out std_logic_vector(31 downto 0); +-- Port for std_logic_vector field: 'Transmit data' in reg: 'Transmit data regsiter' + uart_tdr_tx_data_o : out std_logic_vector(7 downto 0); + uart_tdr_tx_data_i : in std_logic_vector(7 downto 0); + uart_tdr_tx_data_load_o : out std_logic; +-- Port for std_logic_vector field: 'Received data' in reg: 'Receive data regsiter' + uart_rdr_rx_data_i : in std_logic_vector(7 downto 0); + rdr_rack_o : out std_logic; +-- FIFO write request + uart_debug_wr_req_i : in std_logic; +-- FIFO full flag + uart_debug_wr_full_o : out std_logic; +-- FIFO empty flag + uart_debug_wr_empty_o : out std_logic; +-- FIFO number of used words + uart_debug_wr_usedw_o : out std_logic_vector(10 downto 0); + uart_debug_tx_i : in std_logic_vector(7 downto 0); + uart_debug_dupa_i : in std_logic_vector(31 downto 0) + ); +end wb_virtual_uart_slave; + +architecture syn of wb_virtual_uart_slave is + +signal uart_bcr_int : std_logic_vector(31 downto 0); +signal uart_debug_in_int : std_logic_vector(39 downto 0); +signal uart_debug_out_int : std_logic_vector(39 downto 0); +signal uart_debug_rdreq_int : std_logic ; +signal uart_debug_rdreq_int_d0 : std_logic ; +signal uart_debug_full_int : std_logic ; +signal uart_debug_empty_int : std_logic ; +signal uart_debug_usedw_int : std_logic_vector(10 downto 0); +signal ack_sreg : std_logic_vector(9 downto 0); +signal rddata_reg : std_logic_vector(31 downto 0); +signal wrdata_reg : std_logic_vector(31 downto 0); +signal bwsel_reg : std_logic_vector(3 downto 0); +signal rwaddr_reg : std_logic_vector(2 downto 0); +signal ack_in_progress : std_logic ; +signal wr_int : std_logic ; +signal rd_int : std_logic ; +signal bus_clock_int : std_logic ; +signal allones : std_logic_vector(31 downto 0); +signal allzeros : std_logic_vector(31 downto 0); + +begin +-- Some internal signals assignments. For (foreseen) compatibility with other bus standards. + wrdata_reg <= wb_data_i; + bwsel_reg <= wb_sel_i; + bus_clock_int <= wb_clk_i; + rd_int <= wb_cyc_i and (wb_stb_i and (not wb_we_i)); + wr_int <= wb_cyc_i and (wb_stb_i and wb_we_i); + allones <= (others => '1'); + allzeros <= (others => '0'); +-- +-- Main register bank access process. + process (bus_clock_int, rst_n_i) + begin + if (rst_n_i = '0') then + ack_sreg <= "0000000000"; + ack_in_progress <= '0'; + rddata_reg <= "00000000000000000000000000000000"; + uart_bcr_int <= "00000000000000000000000000000000"; + uart_tdr_tx_data_load_o <= '0'; + rdr_rack_o <= '0'; + uart_debug_rdreq_int <= '0'; + elsif rising_edge(bus_clock_int) then +-- advance the ACK generator shift register + ack_sreg(8 downto 0) <= ack_sreg(9 downto 1); + ack_sreg(9) <= '0'; + if (ack_in_progress = '1') then + if (ack_sreg(0) = '1') then + uart_tdr_tx_data_load_o <= '0'; + rdr_rack_o <= '0'; + ack_in_progress <= '0'; + else + uart_tdr_tx_data_load_o <= '0'; + end if; + else + if ((wb_cyc_i = '1') and (wb_stb_i = '1')) then + case rwaddr_reg(2 downto 0) is + when "000" => + if (wb_we_i = '1') then + else + rddata_reg(0) <= uart_sr_tx_busy_i; + rddata_reg(1) <= uart_sr_rx_rdy_i; + rddata_reg(2) <= 'X'; + rddata_reg(3) <= 'X'; + rddata_reg(4) <= 'X'; + rddata_reg(5) <= 'X'; + rddata_reg(6) <= 'X'; + rddata_reg(7) <= 'X'; + rddata_reg(8) <= 'X'; + rddata_reg(9) <= 'X'; + rddata_reg(10) <= 'X'; + rddata_reg(11) <= 'X'; + rddata_reg(12) <= 'X'; + rddata_reg(13) <= 'X'; + rddata_reg(14) <= 'X'; + rddata_reg(15) <= 'X'; + rddata_reg(16) <= 'X'; + rddata_reg(17) <= 'X'; + rddata_reg(18) <= 'X'; + rddata_reg(19) <= 'X'; + rddata_reg(20) <= 'X'; + rddata_reg(21) <= 'X'; + rddata_reg(22) <= 'X'; + rddata_reg(23) <= 'X'; + rddata_reg(24) <= 'X'; + rddata_reg(25) <= 'X'; + rddata_reg(26) <= 'X'; + rddata_reg(27) <= 'X'; + rddata_reg(28) <= 'X'; + rddata_reg(29) <= 'X'; + rddata_reg(30) <= 'X'; + rddata_reg(31) <= 'X'; + end if; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when "001" => + if (wb_we_i = '1') then + uart_bcr_int <= wrdata_reg(31 downto 0); + else + rddata_reg(31 downto 0) <= uart_bcr_int; + end if; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when "010" => + if (wb_we_i = '1') then + uart_tdr_tx_data_load_o <= '1'; + else + rddata_reg(7 downto 0) <= uart_tdr_tx_data_i; + rddata_reg(8) <= 'X'; + rddata_reg(9) <= 'X'; + rddata_reg(10) <= 'X'; + rddata_reg(11) <= 'X'; + rddata_reg(12) <= 'X'; + rddata_reg(13) <= 'X'; + rddata_reg(14) <= 'X'; + rddata_reg(15) <= 'X'; + rddata_reg(16) <= 'X'; + rddata_reg(17) <= 'X'; + rddata_reg(18) <= 'X'; + rddata_reg(19) <= 'X'; + rddata_reg(20) <= 'X'; + rddata_reg(21) <= 'X'; + rddata_reg(22) <= 'X'; + rddata_reg(23) <= 'X'; + rddata_reg(24) <= 'X'; + rddata_reg(25) <= 'X'; + rddata_reg(26) <= 'X'; + rddata_reg(27) <= 'X'; + rddata_reg(28) <= 'X'; + rddata_reg(29) <= 'X'; + rddata_reg(30) <= 'X'; + rddata_reg(31) <= 'X'; + end if; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when "011" => + if (wb_we_i = '1') then + else + rddata_reg(7 downto 0) <= uart_rdr_rx_data_i; + rdr_rack_o <= '1'; + rddata_reg(8) <= 'X'; + rddata_reg(9) <= 'X'; + rddata_reg(10) <= 'X'; + rddata_reg(11) <= 'X'; + rddata_reg(12) <= 'X'; + rddata_reg(13) <= 'X'; + rddata_reg(14) <= 'X'; + rddata_reg(15) <= 'X'; + rddata_reg(16) <= 'X'; + rddata_reg(17) <= 'X'; + rddata_reg(18) <= 'X'; + rddata_reg(19) <= 'X'; + rddata_reg(20) <= 'X'; + rddata_reg(21) <= 'X'; + rddata_reg(22) <= 'X'; + rddata_reg(23) <= 'X'; + rddata_reg(24) <= 'X'; + rddata_reg(25) <= 'X'; + rddata_reg(26) <= 'X'; + rddata_reg(27) <= 'X'; + rddata_reg(28) <= 'X'; + rddata_reg(29) <= 'X'; + rddata_reg(30) <= 'X'; + rddata_reg(31) <= 'X'; + end if; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when "100" => + if (wb_we_i = '1') then + else + if (uart_debug_rdreq_int_d0 = '0') then + uart_debug_rdreq_int <= not uart_debug_rdreq_int; + else + rddata_reg(7 downto 0) <= uart_debug_out_int(7 downto 0); + ack_in_progress <= '1'; + ack_sreg(0) <= '1'; + end if; + rddata_reg(8) <= 'X'; + rddata_reg(9) <= 'X'; + rddata_reg(10) <= 'X'; + rddata_reg(11) <= 'X'; + rddata_reg(12) <= 'X'; + rddata_reg(13) <= 'X'; + rddata_reg(14) <= 'X'; + rddata_reg(15) <= 'X'; + rddata_reg(16) <= 'X'; + rddata_reg(17) <= 'X'; + rddata_reg(18) <= 'X'; + rddata_reg(19) <= 'X'; + rddata_reg(20) <= 'X'; + rddata_reg(21) <= 'X'; + rddata_reg(22) <= 'X'; + rddata_reg(23) <= 'X'; + rddata_reg(24) <= 'X'; + rddata_reg(25) <= 'X'; + rddata_reg(26) <= 'X'; + rddata_reg(27) <= 'X'; + rddata_reg(28) <= 'X'; + rddata_reg(29) <= 'X'; + rddata_reg(30) <= 'X'; + rddata_reg(31) <= 'X'; + end if; + when "101" => + if (wb_we_i = '1') then + else + rddata_reg(31 downto 0) <= uart_debug_out_int(39 downto 8); + end if; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when "110" => + if (wb_we_i = '1') then + else + rddata_reg(16) <= uart_debug_full_int; + rddata_reg(17) <= uart_debug_empty_int; + rddata_reg(10 downto 0) <= uart_debug_usedw_int; + rddata_reg(11) <= 'X'; + rddata_reg(12) <= 'X'; + rddata_reg(13) <= 'X'; + rddata_reg(14) <= 'X'; + rddata_reg(15) <= 'X'; + rddata_reg(18) <= 'X'; + rddata_reg(19) <= 'X'; + rddata_reg(20) <= 'X'; + rddata_reg(21) <= 'X'; + rddata_reg(22) <= 'X'; + rddata_reg(23) <= 'X'; + rddata_reg(24) <= 'X'; + rddata_reg(25) <= 'X'; + rddata_reg(26) <= 'X'; + rddata_reg(27) <= 'X'; + rddata_reg(28) <= 'X'; + rddata_reg(29) <= 'X'; + rddata_reg(30) <= 'X'; + rddata_reg(31) <= 'X'; + end if; + ack_sreg(0) <= '1'; + ack_in_progress <= '1'; + when others => +-- prevent the slave from hanging the bus on invalid address + ack_in_progress <= '1'; + ack_sreg(0) <= '1'; + end case; + end if; + end if; + end if; + end process; + + +-- Drive the data output bus + wb_data_o <= rddata_reg; +-- TX busy +-- RX ready +-- Baudrate divider setting + uart_bcr_o <= uart_bcr_int; +-- Transmit data + uart_tdr_tx_data_o <= wrdata_reg(7 downto 0); +-- Received data +-- extra code for reg/fifo/mem: UART TX FIFO + uart_debug_in_int(7 downto 0) <= uart_debug_tx_i; + uart_debug_in_int(39 downto 8) <= uart_debug_dupa_i; + uart_debug_INST : wbgen2_fifo_sync + generic map ( + g_size => 2048, + g_width => 40, + g_usedw_size => 11 + ) + port map ( + wr_req_i => uart_debug_wr_req_i, + wr_full_o => uart_debug_wr_full_o, + wr_empty_o => uart_debug_wr_empty_o, + wr_usedw_o => uart_debug_wr_usedw_o, + rd_full_o => uart_debug_full_int, + rd_empty_o => uart_debug_empty_int, + rd_usedw_o => uart_debug_usedw_int, + rd_req_i => uart_debug_rdreq_int, + clk_i => bus_clock_int, + wr_data_i => uart_debug_in_int, + rd_data_o => uart_debug_out_int + ); + +-- extra code for reg/fifo/mem: FIFO 'UART TX FIFO' data output register 0 + process (bus_clock_int, rst_n_i) + begin + if (rst_n_i = '0') then + uart_debug_rdreq_int_d0 <= '0'; + elsif rising_edge(bus_clock_int) then + uart_debug_rdreq_int_d0 <= uart_debug_rdreq_int; + end if; + end process; + + +-- extra code for reg/fifo/mem: FIFO 'UART TX FIFO' data output register 1 + rwaddr_reg <= wb_addr_i; +-- ACK signal generation. Just pass the LSB of ACK counter. + wb_ack_o <= ack_sreg(0); +end syn; diff --git a/modules/wishbone/wb_virtual_uart/wb_vuart.h b/modules/wishbone/wb_virtual_uart/wb_vuart.h new file mode 100644 index 0000000000000000000000000000000000000000..95a41b4c75898829c0f754bc68db0e1bd18aec38 --- /dev/null +++ b/modules/wishbone/wb_virtual_uart/wb_vuart.h @@ -0,0 +1,103 @@ +/* + Register definitions for slave core: Virtual UART + + * File : wb_vuart.h + * Author : auto-generated by wbgen2 from wb_virtual_uart.wb + * Created : Thu Apr 7 00:51:02 2011 + * Standard : ANSI C + + THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wb_virtual_uart.wb + DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY! + +*/ + +#ifndef __WBGEN2_REGDEFS_WB_VIRTUAL_UART_WB +#define __WBGEN2_REGDEFS_WB_VIRTUAL_UART_WB + +#include <inttypes.h> + +#if defined( __GNUC__) +#define PACKED __attribute__ ((packed)) +#else +#error "Unsupported compiler?" +#endif + +#ifndef __WBGEN2_MACROS_DEFINED__ +#define __WBGEN2_MACROS_DEFINED__ +#define WBGEN2_GEN_MASK(offset, size) (((1<<(size))-1) << (offset)) +#define WBGEN2_GEN_WRITE(value, offset, size) (((value) & ((1<<(size))-1)) << (offset)) +#define WBGEN2_GEN_READ(reg, offset, size) (((reg) >> (offset)) & ((1<<(size))-1)) +#define WBGEN2_SIGN_EXTEND(value, bits) (((value) & (1<<bits) ? ~((1<<(bits))-1): 0 ) | (value)) +#endif + + +/* definitions for register: Status Register */ + +/* definitions for field: TX busy in reg: Status Register */ +#define UART_SR_TX_BUSY WBGEN2_GEN_MASK(0, 1) + +/* definitions for field: RX ready in reg: Status Register */ +#define UART_SR_RX_RDY WBGEN2_GEN_MASK(1, 1) + +/* definitions for register: Baudrate control register */ + +/* definitions for register: Transmit data regsiter */ + +/* definitions for field: Transmit data in reg: Transmit data regsiter */ +#define UART_TDR_TX_DATA_MASK WBGEN2_GEN_MASK(0, 8) +#define UART_TDR_TX_DATA_SHIFT 0 +#define UART_TDR_TX_DATA_W(value) WBGEN2_GEN_WRITE(value, 0, 8) +#define UART_TDR_TX_DATA_R(reg) WBGEN2_GEN_READ(reg, 0, 8) + +/* definitions for register: Receive data regsiter */ + +/* definitions for field: Received data in reg: Receive data regsiter */ +#define UART_RDR_RX_DATA_MASK WBGEN2_GEN_MASK(0, 8) +#define UART_RDR_RX_DATA_SHIFT 0 +#define UART_RDR_RX_DATA_W(value) WBGEN2_GEN_WRITE(value, 0, 8) +#define UART_RDR_RX_DATA_R(reg) WBGEN2_GEN_READ(reg, 0, 8) + +/* definitions for register: FIFO 'UART TX FIFO' data output register 0 */ + +/* definitions for field: Char sent by UART to TX in reg: FIFO 'UART TX FIFO' data output register 0 */ +#define UART_DEBUG_R0_TX_MASK WBGEN2_GEN_MASK(0, 8) +#define UART_DEBUG_R0_TX_SHIFT 0 +#define UART_DEBUG_R0_TX_W(value) WBGEN2_GEN_WRITE(value, 0, 8) +#define UART_DEBUG_R0_TX_R(reg) WBGEN2_GEN_READ(reg, 0, 8) + +/* definitions for register: FIFO 'UART TX FIFO' data output register 1 */ + +/* definitions for field: Dupa in reg: FIFO 'UART TX FIFO' data output register 1 */ +#define UART_DEBUG_R1_DUPA_MASK WBGEN2_GEN_MASK(0, 32) +#define UART_DEBUG_R1_DUPA_SHIFT 0 +#define UART_DEBUG_R1_DUPA_W(value) WBGEN2_GEN_WRITE(value, 0, 32) +#define UART_DEBUG_R1_DUPA_R(reg) WBGEN2_GEN_READ(reg, 0, 32) + +/* definitions for register: FIFO 'UART TX FIFO' control/status register */ + +/* definitions for field: FIFO full flag in reg: FIFO 'UART TX FIFO' control/status register */ +#define UART_DEBUG_CSR_FULL WBGEN2_GEN_MASK(16, 1) + +/* definitions for field: FIFO empty flag in reg: FIFO 'UART TX FIFO' control/status register */ +#define UART_DEBUG_CSR_EMPTY WBGEN2_GEN_MASK(17, 1) + +/* definitions for field: FIFO counter in reg: FIFO 'UART TX FIFO' control/status register */ +#define UART_DEBUG_CSR_USEDW_MASK WBGEN2_GEN_MASK(0, 8) +#define UART_DEBUG_CSR_USEDW_SHIFT 0 +#define UART_DEBUG_CSR_USEDW_W(value) WBGEN2_GEN_WRITE(value, 0, 8) +#define UART_DEBUG_CSR_USEDW_R(reg) WBGEN2_GEN_READ(reg, 0, 8) +/* [0x0]: REG Status Register */ +#define UART_REG_SR 0x00000000 +/* [0x4]: REG Baudrate control register */ +#define UART_REG_BCR 0x00000004 +/* [0x8]: REG Transmit data regsiter */ +#define UART_REG_TDR 0x00000008 +/* [0xc]: REG Receive data regsiter */ +#define UART_REG_RDR 0x0000000c +/* [0x10]: REG FIFO 'UART TX FIFO' data output register 0 */ +#define UART_REG_DEBUG_R0 0x00000010 +/* [0x14]: REG FIFO 'UART TX FIFO' data output register 1 */ +#define UART_REG_DEBUG_R1 0x00000014 +/* [0x18]: REG FIFO 'UART TX FIFO' control/status register */ +#define UART_REG_DEBUG_CSR 0x00000018 +#endif diff --git a/modules/wishbone/wbgen2/Manifest.py b/modules/wishbone/wbgen2/Manifest.py new file mode 100644 index 0000000000000000000000000000000000000000..a9c5c160d3cefee47cda714a1ff568f586dbc772 --- /dev/null +++ b/modules/wishbone/wbgen2/Manifest.py @@ -0,0 +1,7 @@ +files = ["wbgen2_dpssram.vhd", + "wbgen2_eic.vhd", + "wbgen2_fifo_async.vhd", + "wbgen2_fifo_sync.vhd", + "wbgen2_pkg.vhd"] + +library = "wbgen2" diff --git a/modules/wishbone/wbgen2/wbgen2_dpssram.vhd b/modules/wishbone/wbgen2/wbgen2_dpssram.vhd new file mode 100644 index 0000000000000000000000000000000000000000..f5576651a990e5892aefa0227e599bc68ef091f4 --- /dev/null +++ b/modules/wishbone/wbgen2/wbgen2_dpssram.vhd @@ -0,0 +1,102 @@ +library ieee; +use ieee.std_logic_1164.all; + +--use work.genram_pkg.all; +--use work.common_components.all; + +library wbgen2; +use wbgen2.wbgen2_pkg.all; + +entity wbgen2_dpssram is + + generic ( + g_data_width : natural := 32; + g_size : natural := 1024; + g_addr_width : natural := 10; + g_dual_clock : boolean := true; + g_use_bwsel : boolean := true); + + port ( + clk_a_i : in std_logic; + clk_b_i : in std_logic; + + addr_a_i : in std_logic_vector(g_addr_width-1 downto 0); + addr_b_i : in std_logic_vector(g_addr_width-1 downto 0); + + data_a_i : in std_logic_vector(g_data_width-1 downto 0); + data_b_i : in std_logic_vector(g_data_width-1 downto 0); + + data_a_o : out std_logic_vector(g_data_width-1 downto 0); + data_b_o : out std_logic_vector(g_data_width-1 downto 0); + + bwsel_a_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); + bwsel_b_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); + + rd_a_i : in std_logic; + rd_b_i : in std_logic; + + wr_a_i : in std_logic; + wr_b_i : in std_logic + ); + +end wbgen2_dpssram; + + +architecture syn of wbgen2_dpssram is + function f_log2_size (A : natural) return natural is + begin + for I in 1 to 64 loop -- Works for up to 64 bits + if (2**I > A) then + return(I-1); + end if; + end loop; + return(63); + end function f_log2_size; + + component generic_dpram + generic ( + g_data_width : natural; + g_size : natural; + g_with_byte_enable : boolean; + g_addr_conflict_resolution : string := "read_first"; + g_init_file : string := ""; + g_dual_clock : boolean); + port ( + rst_n_i : in std_logic := '1'; + clka_i : in std_logic; + bwea_i : in std_logic_vector(g_data_width/8-1 downto 0); + wea_i : in std_logic; + aa_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); + da_i : in std_logic_vector(g_data_width-1 downto 0); + qa_o : out std_logic_vector(g_data_width-1 downto 0); + clkb_i : in std_logic; + bweb_i : in std_logic_vector(g_data_width/8-1 downto 0); + web_i : in std_logic; + ab_i : in std_logic_vector(f_log2_size(g_size)-1 downto 0); + db_i : in std_logic_vector(g_data_width-1 downto 0); + qb_o : out std_logic_vector(g_data_width-1 downto 0)); + end component; +begin + + wrapped_dpram: generic_dpram + generic map ( + g_data_width => g_data_width, + g_size => g_size, + g_with_byte_enable => g_use_bwsel, + g_dual_clock => g_dual_clock) + port map ( + rst_n_i => '1', + clka_i => clk_a_i, + bwea_i => bwsel_a_i, + wea_i => wr_a_i, + aa_i => addr_a_i, + da_i => data_a_i, + qa_o => data_a_o, + clkb_i => clk_b_i, + bweb_i => bwsel_b_i, + web_i => wr_b_i, + ab_i => addr_b_i, + db_i => data_b_i, + qb_o => data_b_o); + +end syn; diff --git a/modules/wishbone/wbgen2/wbgen2_eic.vhd b/modules/wishbone/wbgen2/wbgen2_eic.vhd new file mode 100644 index 0000000000000000000000000000000000000000..840590a4bf61bf207aeddb115b31bbec709ff099 --- /dev/null +++ b/modules/wishbone/wbgen2/wbgen2_eic.vhd @@ -0,0 +1,213 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + + +library wbgen2; +use wbgen2.wbgen2_pkg.all; + +entity wbgen2_eic is + + generic ( + g_num_interrupts : natural := 1; + + g_irq00_mode : integer := 0; + g_irq01_mode : integer := 0; + g_irq02_mode : integer := 0; + g_irq03_mode : integer := 0; + g_irq04_mode : integer := 0; + g_irq05_mode : integer := 0; + g_irq06_mode : integer := 0; + g_irq07_mode : integer := 0; + g_irq08_mode : integer := 0; + g_irq09_mode : integer := 0; + g_irq0a_mode : integer := 0; + g_irq0b_mode : integer := 0; + g_irq0c_mode : integer := 0; + g_irq0d_mode : integer := 0; + g_irq0e_mode : integer := 0; + g_irq0f_mode : integer := 0; + g_irq10_mode : integer := 0; + g_irq11_mode : integer := 0; + g_irq12_mode : integer := 0; + g_irq13_mode : integer := 0; + g_irq14_mode : integer := 0; + g_irq15_mode : integer := 0; + g_irq16_mode : integer := 0; + g_irq17_mode : integer := 0; + g_irq18_mode : integer := 0; + g_irq19_mode : integer := 0; + g_irq1a_mode : integer := 0; + g_irq1b_mode : integer := 0; + g_irq1c_mode : integer := 0; + g_irq1d_mode : integer := 0; + g_irq1e_mode : integer := 0; + g_irq1f_mode : integer := 0 + ); + port( + rst_n_i : in std_logic; -- reset & system clock, as always :) + clk_i : in std_logic; + + -- raw interrupt inputs + irq_i : in std_logic_vector(g_num_interrupts-1 downto 0); + + -- interrupt acknowledge signal, used for level-active interrupts to + -- indicate that the interrupt has been handled + irq_ack_o: out std_logic_vector(g_num_interrupts-1 downto 0); + +-- interrupt mask regsiter (slv/bus read-only) + reg_imr_o : out std_logic_vector(g_num_interrupts-1 downto 0); + +-- interrupt enable/disable registers (slv/bus pass-through) + reg_ier_i : in std_logic_vector(g_num_interrupts-1 downto 0); + reg_ier_wr_stb_i : in std_logic; + + reg_idr_i : in std_logic_vector(g_num_interrupts-1 downto 0); + reg_idr_wr_stb_i : in std_logic; + +-- interrupt status register (slv/bus write with LOAD_EXT) + reg_isr_o : out std_logic_vector(g_num_interrupts-1 downto 0); + reg_isr_i : in std_logic_vector(g_num_interrupts-1 downto 0); + reg_isr_wr_stb_i : in std_logic; + +-- multiplexed wishbone irq output + wb_irq_o : out std_logic + + ); + +end wbgen2_eic; + +architecture syn of wbgen2_eic is + + subtype t_irq_mode is integer; + type t_irq_mode_vec is array (0 to 31) of t_irq_mode; + + constant c_IRQ_MODE_RISING_EDGE : t_irq_mode := 0; + constant c_IRQ_MODE_FALLING_EDGE : t_irq_mode := 1; + constant c_IRQ_MODE_LEVEL_0 : t_irq_mode := 2; + constant c_IRQ_MODE_LEVEL_1 : t_irq_mode := 3; + + + signal irq_mode : t_irq_mode_vec; + + signal irq_mask : std_logic_vector(g_num_interrupts-1 downto 0); + signal irq_pending : std_logic_vector(g_num_interrupts-1 downto 0); + + signal irq_i_d0 : std_logic_vector(g_num_interrupts-1 downto 0); + signal irq_i_d1 : std_logic_vector(g_num_interrupts-1 downto 0); + signal irq_i_d2 : std_logic_vector(g_num_interrupts-1 downto 0); + +begin -- syn + + irq_mode(0) <= g_irq00_mode; + irq_mode(1) <= g_irq01_mode; + irq_mode(2) <= g_irq02_mode; + irq_mode(3) <= g_irq03_mode; + irq_mode(4) <= g_irq04_mode; + irq_mode(5) <= g_irq05_mode; + irq_mode(6) <= g_irq06_mode; + irq_mode(7) <= g_irq07_mode; + irq_mode(8) <= g_irq08_mode; + irq_mode(9) <= g_irq09_mode; + irq_mode(10) <= g_irq0a_mode; + irq_mode(11) <= g_irq0b_mode; + irq_mode(12) <= g_irq0c_mode; + irq_mode(13) <= g_irq0d_mode; + irq_mode(14) <= g_irq0e_mode; + irq_mode(15) <= g_irq0f_mode; + irq_mode(16) <= g_irq10_mode; + irq_mode(17) <= g_irq11_mode; + irq_mode(18) <= g_irq12_mode; + irq_mode(19) <= g_irq13_mode; + irq_mode(20) <= g_irq14_mode; + irq_mode(21) <= g_irq15_mode; + irq_mode(22) <= g_irq16_mode; + irq_mode(23) <= g_irq17_mode; + irq_mode(24) <= g_irq18_mode; + irq_mode(25) <= g_irq19_mode; + irq_mode(26) <= g_irq1a_mode; + irq_mode(27) <= g_irq1b_mode; + irq_mode(28) <= g_irq1c_mode; + irq_mode(29) <= g_irq1d_mode; + irq_mode(30) <= g_irq1e_mode; + irq_mode(31) <= g_irq1f_mode; + + + process(clk_i, rst_n_i) + begin + if(rst_n_i = '0') then + irq_i_d0 <= (others => '0'); + irq_i_d1 <= (others => '0'); + irq_i_d1 <= (others => '0'); + irq_pending <= (others => '0'); + irq_mask <= (others => '0'); + + elsif rising_edge(clk_i) then + + for i in 0 to g_num_interrupts-1 loop + + irq_i_d0(i) <= irq_i(i); + irq_i_d1(i) <= irq_i_d0(i); + irq_i_d2(i) <= irq_i_d1(i); + + + if((reg_isr_i(i) = '1' and reg_isr_wr_stb_i = '1') or irq_mask(i) = '0') then + irq_pending(i) <= '0'; + irq_i_d0(i) <= '0'; + irq_i_d1(i) <= '0'; + irq_i_d2(i) <= '0'; + + else + + case irq_mode(i) is + when c_IRQ_MODE_LEVEL_0 => irq_pending(i) <= not irq_i_d2(i); + when c_IRQ_MODE_LEVEL_1 => irq_pending(i) <= irq_i_d2(i); + when c_IRQ_MODE_RISING_EDGE => irq_pending(i) <= irq_pending(i) or ((not irq_i_d2(i)) and irq_i_d1(i)); + when c_IRQ_MODE_FALLING_EDGE => irq_pending(i) <= irq_pending(i) or ((not irq_i_d1(i)) and irq_i_d2(i)); + when others => null; + end case; + end if; + end loop; -- i + + if(reg_ier_wr_stb_i = '1') then + for i in 0 to g_num_interrupts-1 loop + if(reg_ier_i(i) = '1') then + irq_mask(i) <= '1'; + end if; + end loop; + end if; + + if(reg_idr_wr_stb_i = '1') then + for i in 0 to g_num_interrupts-1 loop + if(reg_idr_i(i) = '1') then + irq_mask(i) <= '0'; + end if; + end loop; + end if; + end if; + end process; + + -- generation of wb_irq_o + + process(clk_i, rst_n_i) + begin + if(rst_n_i = '0') then + wb_irq_o <= '0'; + elsif rising_edge(clk_i) then + if(irq_pending = std_logic_vector(to_unsigned(0, g_num_interrupts))) then + wb_irq_o <= '0'; + else + wb_irq_o <= '1'; + end if; + + end if; + end process; + + gen_irq_ack: for i in 0 to g_num_interrupts-1 generate + irq_ack_o(i) <= '1' when (reg_isr_wr_stb_i = '1' and reg_isr_i(i) = '1') else '0'; + end generate gen_irq_ack; + + reg_imr_o <= irq_mask; + reg_isr_o <= irq_pending; + +end syn; diff --git a/modules/wishbone/wbgen2/wbgen2_fifo_async.vhd b/modules/wishbone/wbgen2/wbgen2_fifo_async.vhd new file mode 100644 index 0000000000000000000000000000000000000000..0ffb664e92be97471bd50db4e301b4b5bef9f3f1 --- /dev/null +++ b/modules/wishbone/wbgen2/wbgen2_fifo_async.vhd @@ -0,0 +1,115 @@ +library ieee; +use ieee.std_logic_1164.all; + +library work; +use work.genram_pkg.all; + +library wbgen2; +use wbgen2.wbgen2_pkg.all; + +entity wbgen2_fifo_async is + generic ( + g_size : integer; + g_width : integer; + g_usedw_size : integer + ); + + port + ( + rd_clk_i : in std_logic; + rd_req_i : in std_logic; + rd_data_o : out std_logic_vector(g_width-1 downto 0); + + rd_empty_o : out std_logic; + rd_full_o : out std_logic; + rd_usedw_o : out std_logic_vector(g_usedw_size -1 downto 0); + + + wr_clk_i : in std_logic; + wr_req_i : in std_logic; + wr_data_i : in std_logic_vector(g_width-1 downto 0); + + wr_empty_o : out std_logic; + wr_full_o : out std_logic; + wr_usedw_o : out std_logic_vector(g_usedw_size -1 downto 0) + ); +end wbgen2_fifo_async; + +architecture rtl of wbgen2_fifo_async is + + component generic_async_fifo + generic ( + g_data_width : natural; + g_size : natural; + g_show_ahead : boolean; + g_with_rd_empty : boolean; + g_with_rd_full : boolean; + g_with_rd_almost_empty : boolean; + g_with_rd_almost_full : boolean; + g_with_rd_count : boolean; + g_with_wr_empty : boolean; + g_with_wr_full : boolean; + g_with_wr_almost_empty : boolean; + g_with_wr_almost_full : boolean; + g_with_wr_count : boolean; + g_almost_empty_threshold : integer; + g_almost_full_threshold : integer); + port ( + rst_n_i : in std_logic := '1'; + clk_wr_i : in std_logic; + d_i : in std_logic_vector(g_data_width-1 downto 0); + we_i : in std_logic; + wr_empty_o : out std_logic; + wr_full_o : out std_logic; + wr_almost_empty_o : out std_logic; + wr_almost_full_o : out std_logic; + wr_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0); + clk_rd_i : in std_logic; + q_o : out std_logic_vector(g_data_width-1 downto 0); + rd_i : in std_logic; + rd_empty_o : out std_logic; + rd_full_o : out std_logic; + rd_almost_empty_o : out std_logic; + rd_almost_full_o : out std_logic; + rd_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0)); + end component; + +begin + + wrapped_fifo: generic_async_fifo + generic map ( + g_data_width => g_width, + g_size => g_size, + g_show_ahead => false, + g_with_rd_empty => true, + g_with_rd_full => true, + g_with_rd_almost_empty => false, + g_with_rd_almost_full => false, + g_with_rd_count => true, + g_with_wr_empty => true, + g_with_wr_full => true, + g_with_wr_almost_empty => false, + g_with_wr_almost_full => false, + g_with_wr_count => true, + g_almost_empty_threshold => 0, + g_almost_full_threshold => 0) + port map ( + rst_n_i => '1', + clk_wr_i => wr_clk_i, + d_i => wr_data_i, + we_i => wr_req_i, + wr_empty_o => wr_empty_o, + wr_full_o => wr_full_o, + wr_almost_empty_o => open, + wr_almost_full_o => open, + wr_count_o => wr_usedw_o, + clk_rd_i => rd_clk_i, + q_o => rd_data_o, + rd_i => rd_req_i, + rd_empty_o => rd_empty_o, + rd_full_o => rd_full_o, + rd_almost_empty_o => open, + rd_almost_full_o => open, + rd_count_o => rd_usedw_o); + +end rtl; diff --git a/modules/wishbone/wbgen2/wbgen2_fifo_sync.vhd b/modules/wishbone/wbgen2/wbgen2_fifo_sync.vhd new file mode 100644 index 0000000000000000000000000000000000000000..ea01ae9201bceb14ca559e27d07c61f9ccbcea36 --- /dev/null +++ b/modules/wishbone/wbgen2/wbgen2_fifo_sync.vhd @@ -0,0 +1,114 @@ + +library ieee; +use ieee.std_logic_1164.all; + +library wbgen2; +use wbgen2.wbgen2_pkg.all; + + +entity wbgen2_fifo_sync is + generic ( + g_width : integer; + g_size : integer; + g_usedw_size : integer); + + port + ( + clk_i : in std_logic; + wr_data_i : in std_logic_vector(g_width-1 downto 0); + wr_req_i : in std_logic; + + rd_data_o : out std_logic_vector(g_width-1 downto 0); + rd_req_i : in std_logic; + + wr_empty_o : out std_logic; + wr_full_o : out std_logic; + wr_usedw_o : out std_logic_vector(g_usedw_size -1 downto 0); + + rd_empty_o : out std_logic; + rd_full_o : out std_logic; + rd_usedw_o : out std_logic_vector(g_usedw_size -1 downto 0) + + ); +end wbgen2_fifo_sync; + + +architecture rtl of wbgen2_fifo_sync is + + + function f_log2_size (A : natural) return natural is + begin + for I in 1 to 64 loop -- Works for up to 64 bits + if (2**I > A) then + return(I-1); + end if; + end loop; + return(63); + end function f_log2_size; + + component generic_sync_fifo + generic ( + g_data_width : natural; + g_size : natural; + g_show_ahead : boolean; + g_with_empty : boolean; + g_with_full : boolean; + g_with_almost_empty : boolean; + g_with_almost_full : boolean; + g_with_count : boolean; + g_almost_empty_threshold : integer := 0; + g_almost_full_threshold : integer := 0); + port ( + rst_n_i : in std_logic := '1'; + clk_i : in std_logic; + d_i : in std_logic_vector(g_data_width-1 downto 0); + we_i : in std_logic; + q_o : out std_logic_vector(g_data_width-1 downto 0); + rd_i : in std_logic; + empty_o : out std_logic; + full_o : out std_logic; + almost_empty_o : out std_logic; + almost_full_o : out std_logic; + count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0)); + end component; + + signal empty_int : std_logic; + signal full_int : std_logic; + signal usedw_int : std_logic_vector(g_usedw_size-1 downto 0); + +begin + + wrapped_fifo: generic_sync_fifo + generic map ( + g_data_width => g_width, + g_size => g_size, + g_show_ahead => false, + g_with_empty => true, + g_with_full => true, + g_with_almost_empty => false, + g_with_almost_full => false, + g_with_count => true) + port map ( + rst_n_i => '1', + clk_i => clk_i, + d_i => wr_data_i, + we_i => wr_req_i, + q_o => rd_data_o, + rd_i => rd_req_i, + empty_o => empty_int, + full_o => full_int, + almost_empty_o => open, + almost_full_o => open, + count_o => usedw_int); + + + rd_empty_o <= empty_int; + rd_full_o <= full_int; + rd_usedw_o <= usedw_int; + + wr_empty_o <= empty_int; + wr_full_o <= full_int; + wr_usedw_o <= usedw_int; + + +end rtl; diff --git a/modules/wishbone/wbgen2/wbgen2_pkg.vhd b/modules/wishbone/wbgen2/wbgen2_pkg.vhd new file mode 100644 index 0000000000000000000000000000000000000000..4a0489f6f238be5fd50b58b100d2f0efe920e8ae --- /dev/null +++ b/modules/wishbone/wbgen2/wbgen2_pkg.vhd @@ -0,0 +1,125 @@ +library ieee; +use ieee.std_logic_1164.all; + +library wbgen2; + +package wbgen2_pkg is + + + component wbgen2_dpssram + generic ( + g_data_width : natural; + g_size : natural; + g_addr_width : natural; + g_dual_clock : boolean; + g_use_bwsel : boolean); + port ( + clk_a_i : in std_logic; + clk_b_i : in std_logic; + addr_a_i : in std_logic_vector(g_addr_width-1 downto 0); + addr_b_i : in std_logic_vector(g_addr_width-1 downto 0); + data_a_i : in std_logic_vector(g_data_width-1 downto 0); + data_b_i : in std_logic_vector(g_data_width-1 downto 0); + data_a_o : out std_logic_vector(g_data_width-1 downto 0); + data_b_o : out std_logic_vector(g_data_width-1 downto 0); + bwsel_a_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); + bwsel_b_i : in std_logic_vector((g_data_width+7)/8-1 downto 0); + rd_a_i : in std_logic; + rd_b_i : in std_logic; + wr_a_i : in std_logic; + wr_b_i : in std_logic); + end component; + + + component wbgen2_eic + generic ( + g_num_interrupts : natural; + g_irq00_mode : integer; + g_irq01_mode : integer; + g_irq02_mode : integer; + g_irq03_mode : integer; + g_irq04_mode : integer; + g_irq05_mode : integer; + g_irq06_mode : integer; + g_irq07_mode : integer; + g_irq08_mode : integer; + g_irq09_mode : integer; + g_irq0a_mode : integer; + g_irq0b_mode : integer; + g_irq0c_mode : integer; + g_irq0d_mode : integer; + g_irq0e_mode : integer; + g_irq0f_mode : integer; + g_irq10_mode : integer; + g_irq11_mode : integer; + g_irq12_mode : integer; + g_irq13_mode : integer; + g_irq14_mode : integer; + g_irq15_mode : integer; + g_irq16_mode : integer; + g_irq17_mode : integer; + g_irq18_mode : integer; + g_irq19_mode : integer; + g_irq1a_mode : integer; + g_irq1b_mode : integer; + g_irq1c_mode : integer; + g_irq1d_mode : integer; + g_irq1e_mode : integer; + g_irq1f_mode : integer); + port ( + rst_n_i : in std_logic; + clk_i : in std_logic; + irq_i : in std_logic_vector(g_num_interrupts-1 downto 0); + irq_ack_o : out std_logic_vector(g_num_interrupts-1 downto 0); + reg_imr_o : out std_logic_vector(g_num_interrupts-1 downto 0); + reg_ier_i : in std_logic_vector(g_num_interrupts-1 downto 0); + reg_ier_wr_stb_i : in std_logic; + reg_idr_i : in std_logic_vector(g_num_interrupts-1 downto 0); + reg_idr_wr_stb_i : in std_logic; + reg_isr_o : out std_logic_vector(g_num_interrupts-1 downto 0); + reg_isr_i : in std_logic_vector(g_num_interrupts-1 downto 0); + reg_isr_wr_stb_i : in std_logic; + wb_irq_o : out std_logic); + end component; + + component wbgen2_fifo_async + generic ( + g_size : integer; + g_width : integer; + g_usedw_size : integer); + port ( + rd_clk_i : in std_logic; + rd_req_i : in std_logic; + rd_data_o : out std_logic_vector(g_width-1 downto 0); + rd_empty_o : out std_logic; + rd_full_o : out std_logic; + rd_usedw_o : out std_logic_vector(g_usedw_size -1 downto 0); + wr_clk_i : in std_logic; + wr_req_i : in std_logic; + wr_data_i : in std_logic_vector(g_width-1 downto 0); + wr_empty_o : out std_logic; + wr_full_o : out std_logic; + wr_usedw_o : out std_logic_vector(g_usedw_size -1 downto 0)); + end component; + + + component wbgen2_fifo_sync + generic ( + g_width : integer; + g_size : integer; + g_usedw_size : integer); + port ( + clk_i : in std_logic; + wr_data_i : in std_logic_vector(g_width-1 downto 0); + wr_req_i : in std_logic; + rd_data_o : out std_logic_vector(g_width-1 downto 0); + rd_req_i : in std_logic; + wr_empty_o : out std_logic; + wr_full_o : out std_logic; + wr_usedw_o : out std_logic_vector(g_usedw_size -1 downto 0); + rd_empty_o : out std_logic; + rd_full_o : out std_logic; + rd_usedw_o : out std_logic_vector(g_usedw_size -1 downto 0)); + end component; + +end wbgen2_pkg; diff --git a/modules/wishbone/wishbone_pkg.vhd b/modules/wishbone/wishbone_pkg.vhd new file mode 100644 index 0000000000000000000000000000000000000000..15d2e045009dbd6754f4d24e8cc39db6b26badc3 --- /dev/null +++ b/modules/wishbone/wishbone_pkg.vhd @@ -0,0 +1,97 @@ +library ieee; + +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library work; + +package wishbone_pkg is + +-- number of wishbone masters provided by CPU->WB bridge +-- constant c_wishbone_num_masters : integer := 12; +-- CPU address bus width + constant c_cpu_addr_width : integer := 19; +-- WB address bus width. Must be log2(c_wishbone_num_masters) smaller than +-- c_cpu_addr_width as the most significant bits select the master port (peripheral) + constant c_wishbone_addr_width : integer := 14; + + + component wb_cpu_bridge + generic ( + g_simulation :integer := 0; + g_wishbone_num_masters : integer); + port ( + sys_rst_n_i : in std_logic; + cpu_clk_i : in std_logic; + cpu_cs_n_i : in std_logic; + cpu_wr_n_i : in std_logic; + cpu_rd_n_i : in std_logic; + cpu_bs_n_i : in std_logic_vector(3 downto 0); + cpu_addr_i : in std_logic_vector(c_cpu_addr_width-1 downto 0); + cpu_data_b : inout std_logic_vector(31 downto 0); + cpu_nwait_o : out std_logic; + wb_clk_i : in std_logic; + wb_addr_o : out std_logic_vector(c_wishbone_addr_width - 1 downto 0); + wb_data_o : out std_logic_vector(31 downto 0); + wb_stb_o : out std_logic; + wb_we_o : out std_logic; + wb_sel_o : out std_logic_vector(3 downto 0); + wb_cyc_o : out std_logic_vector (g_wishbone_num_masters - 1 downto 0); + wb_data_i : in std_logic_vector (32 * g_wishbone_num_masters-1 downto 0); + wb_ack_i : in std_logic_vector(g_wishbone_num_masters-1 downto 0)); + end component; + + component wb_gpio_port + generic ( + g_num_pins : natural); + port ( + sys_rst_n_i : in std_logic; + wb_clk_i : in std_logic; + wb_sel_i : in std_logic; + wb_cyc_i : in std_logic; + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_addr_i : in std_logic_vector(2 downto 0); + wb_data_i : in std_logic_vector(31 downto 0); + wb_data_o : out std_logic_vector(31 downto 0); + wb_ack_o : out std_logic; + gpio_b : inout std_logic_vector(g_num_pins-1 downto 0)); + end component; + + component wb_spi_master + port ( + refclk2_i : in std_logic; + sys_rst_n_i : in std_logic; + wb_sel_i : in std_logic; + wb_cyc_i : in std_logic; + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_addr_i : in std_logic_vector(c_wishbone_addr_width-1 downto 0); + wb_data_i : in std_logic_vector(31 downto 0); + wb_data_o : out std_logic_vector(31 downto 0); + wb_ack_o : out std_logic; + spi_mosi_o : out std_logic; + spi_miso_i : in std_logic; + spi_cs_o : out std_logic; + spi_sck_o : out std_logic); + end component; + + component wb_vic + generic ( + g_num_interrupts : natural); + port ( + rst_n_i : in std_logic; + wb_clk_i : in std_logic; + wb_addr_i : in std_logic_vector(5 downto 0); + wb_data_i : in std_logic_vector(31 downto 0); + wb_data_o : out std_logic_vector(31 downto 0); + wb_cyc_i : in std_logic; + wb_sel_i : in std_logic_vector(3 downto 0); + wb_stb_i : in std_logic; + wb_we_i : in std_logic; + wb_ack_o : out std_logic; + irqs_i : in std_logic_vector(g_num_interrupts-1 downto 0); + irq_master_o : out std_logic); + end component; + +end wishbone_pkg;