diff --git a/fpga/arty-lcd-ts.vhdl b/fpga/arty-lcd-ts.vhdl new file mode 100644 index 0000000..2ec3786 --- /dev/null +++ b/fpga/arty-lcd-ts.vhdl @@ -0,0 +1,331 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +library unisim; +use unisim.vcomponents.all; + +library work; +use work.wishbone_types.all; + +-- Interface for LCD/touchscreen connected to Arduino-compatible socket on Arty A7 +entity lcd_touchscreen is + port ( + clk : in std_ulogic; + rst : in std_ulogic; + wb_in : in wb_io_master_out; + wb_out : out wb_io_slave_out; + wb_sel : in std_ulogic; + tp : out std_ulogic; + + lcd_din : in std_ulogic_vector(7 downto 0); + lcd_dout : out std_ulogic_vector(7 downto 0); + lcd_doe : out std_ulogic; + lcd_doe0 : out std_ulogic; + lcd_doe1 : out std_ulogic; + lcd_rd : out std_ulogic; -- note active low + lcd_wr : out std_ulogic; -- note active low + lcd_rs : out std_ulogic; + lcd_rsoe : out std_ulogic; + lcd_cs : out std_ulogic; -- note active low + lcd_csoe : out std_ulogic; + lcd_rst : out std_ulogic; -- note active low + + -- Differential analog inputs from touchscreen + a2_p : in std_ulogic; + a2_n : in std_ulogic; + a3_p : in std_ulogic; + a3_n : in std_ulogic; + a4_p : in std_ulogic; + a4_n : in std_ulogic; + a5_p : in std_ulogic; + a5_n : in std_ulogic + ); +end entity lcd_touchscreen; + +architecture rtl of lcd_touchscreen is + + type state_t is (idle, prep1, prep2, writing, wr_pause, reading, rd_recovery, + drp_lo, drp_hi); + + signal state : state_t; + signal delay : unsigned(5 downto 0); + signal ack : std_ulogic; + signal idle1 : std_ulogic; + signal idle2 : std_ulogic; + + signal rs : std_ulogic; + signal rsoe : std_ulogic; + signal cs : std_ulogic; + signal csoe : std_ulogic; + signal d0 : std_ulogic; + signal doe0 : std_ulogic; + signal doe1 : std_ulogic; + signal d1 : std_ulogic; + signal tsctrl : std_ulogic; + + signal wr_data : std_ulogic_vector(31 downto 0); + signal rd_data : std_ulogic_vector(31 downto 0); + signal wr_sel : std_ulogic_vector(3 downto 0); + signal req_wr : std_ulogic; + + signal xadc_di : std_ulogic_vector(15 downto 0); + signal xadc_do : std_ulogic_vector(15 downto 0); + signal xadc_addr : std_ulogic_vector(6 downto 0); + signal xadc_en : std_ulogic; + signal xadc_we : std_ulogic; + signal xadc_rdy : std_ulogic; + signal xadc_eoc : std_ulogic; + signal xadc_eos : std_ulogic; + signal xadc_busy : std_ulogic; + signal eoc_stat : std_ulogic; + signal eos_stat : std_ulogic; + + -- Assume touchscreen is connected to the A2 - A5 analog inputs + +begin + + -- The connection of the analog A0 - A5 pins on the Arty + -- to FPGA pins is as follows: + -- A0 connects to AD4P/AD4N + -- A1 connects to AD5P/AD5N + -- A2 connects to AD6P/AD6N + -- A3 connects to AD7P/AD7N + -- A4 connects to AD15P/AD15N + -- A5 connects to AD0P/AD0N + xadc_0 : XADC + generic map ( + init_42 => x"0400" -- adcclk = dclk / 4, i.e. 25MHz + ) + port map ( + di => xadc_di, + do => xadc_do, + daddr => xadc_addr, + den => xadc_en, + dwe => xadc_we, + dclk => clk, + drdy => xadc_rdy, + reset => rst, + convst => '0', + convstclk => '0', + vp => '0', + vn => '0', + vauxp => a4_p & "0000000" & a3_p & a2_p & "00000" & a5_p, + vauxn => a4_n & "0000000" & a3_n & a2_n & "00000" & a5_n, + eoc => xadc_eoc, + eos => xadc_eos, + busy => xadc_busy + ); + + -- for now; should make sure it is at least 10us wide + lcd_rst <= not rst; + + wb_out.dat <= rd_data; + wb_out.ack <= ack; + wb_out.stall <= '0' when state = idle else '1'; + + lcd_doe0 <= doe0; + lcd_doe1 <= doe1; + lcd_rs <= rs; + lcd_rsoe <= rsoe; + lcd_cs <= cs; + lcd_csoe <= csoe; + + tp <= tsctrl; + + process (clk) + variable rdat : std_ulogic_vector(7 downto 0); + begin + if rising_edge(clk) then + ack <= '0'; + xadc_en <= '0'; + idle2 <= idle1; + if xadc_eoc = '1' then + eoc_stat <= '1'; + end if; + if xadc_eos = '1' then + eos_stat <= '1'; + end if; + if rst = '1' then + state <= idle; + delay <= to_unsigned(0, 6); + rd_data <= (others => '0'); + lcd_rd <= '1'; + lcd_wr <= '1'; + cs <= '1'; + csoe <= '1'; + rs <= '0'; + rsoe <= '1'; + lcd_doe <= '0'; + doe0 <= '0'; + doe1 <= '0'; + d0 <= '0'; + d1 <= '0'; + idle1 <= '0'; + idle2 <= '0'; + tsctrl <= '0'; + xadc_en <= '0'; + eoc_stat <= '0'; + eos_stat <= '0'; + elsif delay /= "000000" then + delay <= delay - 1; + else + case state is + when idle => + req_wr <= wb_in.we; + wr_data <= wb_in.dat; + wr_sel <= wb_in.sel; + if idle2 = '1' then + -- delay this one cycle after entering idle + lcd_doe <= '0'; + doe0 <= '0'; + doe1 <= '0'; + end if; + idle1 <= '0'; + if wb_in.cyc = '1' and wb_in.stb = '1' and wb_sel = '1' then + if wb_in.sel = "0000" then + ack <= '1'; + elsif wb_in.adr(6) = '0' then + if wb_in.we = '1' or wb_in.adr(2) = '1' then + ack <= '1'; + end if; + if wb_in.adr(2) = '0' then + -- c8050000 or 8, access LCD controller chip + tsctrl <= '0'; + csoe <= '1'; + cs <= '0'; -- active low + rsoe <= '1'; + rs <= wb_in.adr(1); + doe0 <= '0'; + doe1 <= '0'; + state <= prep1; + elsif wb_in.adr(1) = '0' then + -- c8050010, touchscreen drive register + tsctrl <= '1'; + idle2 <= '0'; + rdat := rsoe & rs & doe0 & d0 & doe1 & d1 & csoe & cs; + rd_data <= rdat & rdat & rdat & rdat; + if wb_in.we = '1' and wb_in.sel(0) = '1' then + rsoe <= wb_in.dat(7); + rs <= wb_in.dat(6); + doe0 <= wb_in.dat(5); + d0 <= wb_in.dat(4); + lcd_dout(0) <= wb_in.dat(4); + doe1 <= wb_in.dat(3); + d1 <= wb_in.dat(2); + lcd_dout(1) <= wb_in.dat(2); + csoe <= wb_in.dat(1); + cs <= wb_in.dat(0); + end if; + else + -- c8050018, touchscreen status register + rdat := 4x"0" & xadc_busy & eoc_stat & eos_stat & tsctrl; + rd_data <= rdat & rdat & rdat & rdat; + if wb_in.we = '1' and wb_in.sel(0) = '1' then + -- for eoc_stat and eos_state, write 0 to clear + if wb_in.dat(2) = '0' then + eoc_stat <= '0'; + end if; + if wb_in.dat(1) = '0' then + eos_stat <= '0'; + end if; + end if; + end if; + else + -- c80501xx, access to the XADC DRP port + xadc_en <= '1'; + xadc_we <= wb_in.we; + xadc_addr(6 downto 1) <= wb_in.adr(5 downto 0); + if wb_in.sel(1 downto 0) = "00" then + xadc_di <= wb_in.dat(31 downto 16); + xadc_addr(0) <= '1'; + state <= drp_hi; + else + xadc_di <= wb_in.dat(15 downto 0); + xadc_addr(0) <= '0'; + state <= drp_lo; + end if; + end if; + else + if tsctrl = '0' then + cs <= '1'; + end if; + end if; + when prep1 => + lcd_doe <= req_wr; + doe0 <= req_wr; + doe1 <= req_wr; + if req_wr = '1' then + if wr_sel(1 downto 0) /= "00" then + if wr_sel(1) = '1' then + lcd_dout <= wr_data(15 downto 8); + wr_sel(1) <= '0'; + else + lcd_dout <= wr_data(7 downto 0); + wr_sel(0) <= '0'; + end if; + else + if wr_sel(3) = '1' then + lcd_dout <= wr_data(31 downto 24); + wr_sel(3) <= '0'; + else + lcd_dout <= wr_data(23 downto 16); + wr_sel(2) <= '0'; + end if; + end if; + end if; + state <= prep2; + when prep2 => + if req_wr = '1' then + lcd_wr <= '0'; -- active low + state <= writing; + delay <= to_unsigned(1, 6); + else + lcd_rd <= '0'; + state <= reading; + delay <= to_unsigned(35, 6); + end if; + when writing => + -- last cycle of writing state + lcd_wr <= '1'; + if wr_sel = "0000" then + state <= idle; + idle1 <= '1'; + else + state <= wr_pause; + end if; + when wr_pause => + state <= prep1; + when reading => + -- last cycle of reading state + lcd_rd <= '1'; + rd_data <= lcd_din & lcd_din & lcd_din & lcd_din; + ack <= '1'; + state <= rd_recovery; + delay <= to_unsigned(6, 6); + when rd_recovery => + state <= idle; + when drp_lo => + if xadc_rdy = '1' then + rd_data(15 downto 0) <= xadc_do; + if wr_sel(3 downto 2) = "00" then + ack <= '1'; + state <= idle; + else + xadc_di <= wr_data(31 downto 16); + xadc_addr(0) <= '1'; + state <= drp_hi; + end if; + end if; + when drp_hi => + if xadc_rdy = '1' then + rd_data(31 downto 16) <= xadc_do; + ack <= '1'; + state <= idle; + end if; + end case; + end if; + end if; + end process; + +end architecture; diff --git a/fpga/arty_a7.xdc b/fpga/arty_a7.xdc index cf90805..2c42303 100644 --- a/fpga/arty_a7.xdc +++ b/fpga/arty_a7.xdc @@ -82,14 +82,14 @@ set_property IOB true [get_cells -hierarchical -filter {NAME =~*/spi_rxtx/input_ #set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { pmod_ja_10 }]; # connection to Digilent PmodSD on JA -set_property -dict { PACKAGE_PIN G13 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard_data[3] }]; -set_property -dict { PACKAGE_PIN B11 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard_cmd }]; -set_property -dict { PACKAGE_PIN A11 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard_data[0] }]; -set_property -dict { PACKAGE_PIN D12 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard_clk }]; -set_property -dict { PACKAGE_PIN D13 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard_data[1] }]; -set_property -dict { PACKAGE_PIN B18 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard_data[2] }]; -set_property -dict { PACKAGE_PIN A18 IOSTANDARD LVCMOS33 } [get_ports { sdcard_cd }]; -#set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { sdcard_wp }]; +set_property -dict { PACKAGE_PIN G13 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { ja_sdcard_data[3] }]; +set_property -dict { PACKAGE_PIN B11 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { ja_sdcard_cmd }]; +set_property -dict { PACKAGE_PIN A11 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { ja_sdcard_data[0] }]; +set_property -dict { PACKAGE_PIN D12 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { ja_sdcard_clk }]; +set_property -dict { PACKAGE_PIN D13 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { ja_sdcard_data[1] }]; +set_property -dict { PACKAGE_PIN B18 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { ja_sdcard_data[2] }]; +set_property -dict { PACKAGE_PIN A18 IOSTANDARD LVCMOS33 } [get_ports { ja_sdcard_cd }]; +#set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { ja_sdcard_wp }]; # Put registers into IOBs to improve timing set_property IOB true [get_cells -hierarchical -filter {NAME =~*.litesdcard/sdpads_data_i_reg*}] @@ -101,14 +101,14 @@ set_property IOB true [get_cells -hierarchical -filter {NAME =~*.litesdcard/sdpa # PMOD header JB (high-speed, no protection resisters) ################################################################################ -#set_property -dict { PACKAGE_PIN E15 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_1 }]; -#set_property -dict { PACKAGE_PIN E16 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_2 }]; -#set_property -dict { PACKAGE_PIN D15 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_3 }]; -#set_property -dict { PACKAGE_PIN C15 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_4 }]; -#set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_7 }]; -#set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_8 }]; -#set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_9 }]; -#set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_10 }]; +set_property -dict { PACKAGE_PIN E15 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_1 }]; +set_property -dict { PACKAGE_PIN E16 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_2 }]; +set_property -dict { PACKAGE_PIN D15 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_3 }]; +set_property -dict { PACKAGE_PIN C15 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_4 }]; +set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_7 }]; +set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_8 }]; +set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_9 }]; +set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports { pmod_jb_10 }]; # connection to Digilent PmodSD on JB #set_property -dict { PACKAGE_PIN E15 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard_data[3] }]; @@ -133,6 +133,22 @@ set_property IOB true [get_cells -hierarchical -filter {NAME =~*.litesdcard/sdpa #set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { pmod_jc_9 }]; #set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { pmod_jc_10 }]; +# connection to second Digilent PmodSD on JC +set_property -dict { PACKAGE_PIN U12 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard2_data[3] }]; +set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard2_cmd }]; +set_property -dict { PACKAGE_PIN V10 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard2_data[0] }]; +set_property -dict { PACKAGE_PIN V11 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { sdcard2_clk }]; +set_property -dict { PACKAGE_PIN U14 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard2_data[1] }]; +set_property -dict { PACKAGE_PIN V14 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { sdcard2_data[2] }]; +set_property -dict { PACKAGE_PIN T13 IOSTANDARD LVCMOS33 } [get_ports { sdcard2_cd }]; +#set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { sdcard2_wp }]; + +# Put registers into IOBs to improve timing +set_property IOB true [get_cells -hierarchical -filter {NAME =~*.litesdcard2/sdpads_data_i_reg*}] +set_property IOB true [get_cells -hierarchical -filter {NAME =~*.litesdcard2/xilinxsdrtristateimpl*_o_reg}] +set_property IOB true [get_cells -hierarchical -filter {NAME =~*.litesdcard2/sdcard_clk_reg}] +set_property IOB true [get_cells -hierarchical -filter {NAME =~*.litesdcard2/sdpads_cmd_i_reg}] + ################################################################################ # PMOD header JD (standard, 200 ohm protection resisters) ################################################################################ @@ -146,43 +162,91 @@ set_property IOB true [get_cells -hierarchical -filter {NAME =~*.litesdcard/sdpa #set_property -dict { PACKAGE_PIN H2 IOSTANDARD LVCMOS33 } [get_ports { pmod_jd_9 }]; #set_property -dict { PACKAGE_PIN G2 IOSTANDARD LVCMOS33 } [get_ports { pmod_jd_10 }]; +# connection to i2c RTC chip (Dallas DS3231) on JD +set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 PULLUP TRUE } [get_ports { i2c_rtc_d }]; +set_property -dict { PACKAGE_PIN H2 IOSTANDARD LVCMOS33 PULLUP TRUE } [get_ports { i2c_rtc_c }]; + +################################################################################ +# TFT LCD shield (arduino-compatible) +# hacked to swap the LCD_RST and LCD_D0 lines, and put LCD_D1 on A5 +################################################################################ + +set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { lcd_rst }]; +#set_property -dict { PACKAGE_PIN M16 IOSTANDARD LVCMOS33 } [get_ports { lcd_tp }]; +set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { lcd_d[2] }]; +set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { lcd_d[3] }]; +set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 } [get_ports { lcd_d[4] }]; +set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { lcd_d[5] }]; +set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { lcd_d[6] }]; +set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { lcd_d[7] }]; +set_property -dict { PACKAGE_PIN F5 IOSTANDARD LVCMOS33 PULLUP TRUE } [get_ports { lcd_rd }]; # A0 +set_property -dict { PACKAGE_PIN D8 IOSTANDARD LVCMOS33 PULLUP TRUE } [get_ports { lcd_wr }]; # A1 +set_property -dict { PACKAGE_PIN C7 IOSTANDARD LVCMOS33 } [get_ports { lcd_rs }]; # A2 +set_property -dict { PACKAGE_PIN E7 IOSTANDARD LVCMOS33 } [get_ports { lcd_cs }]; # A3 +set_property -dict { PACKAGE_PIN D7 IOSTANDARD LVCMOS33 } [get_ports { lcd_d[0] }]; # A4 +set_property -dict { PACKAGE_PIN D5 IOSTANDARD LVCMOS33 } [get_ports { lcd_d[1] }]; # A5 + +################################################################################ +# Analog inputs (connected to touchscreen) +################################################################################ +set_property -dict { PACKAGE_PIN C4 IOSTANDARD LVCMOS33 } [get_ports { a2_p }]; +set_property -dict { PACKAGE_PIN B4 IOSTANDARD LVCMOS33 } [get_ports { a2_n }]; +set_property -dict { PACKAGE_PIN B1 IOSTANDARD LVCMOS33 } [get_ports { a3_p }]; +set_property -dict { PACKAGE_PIN A1 IOSTANDARD LVCMOS33 } [get_ports { a3_n }]; +set_property -dict { PACKAGE_PIN B3 IOSTANDARD LVCMOS33 } [get_ports { a4_p }]; +set_property -dict { PACKAGE_PIN B2 IOSTANDARD LVCMOS33 } [get_ports { a4_n }]; +set_property -dict { PACKAGE_PIN D14 IOSTANDARD LVCMOS33 } [get_ports { a5_p }]; +set_property -dict { PACKAGE_PIN C14 IOSTANDARD LVCMOS33 } [get_ports { a5_n }]; + +################################################################################ +# connection to micro SD card socket on touchscreen board +################################################################################ +set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { ts_sdcard_data[3] }]; +set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { ts_sdcard_cmd }]; +set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { ts_sdcard_data[0] }]; +set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 SLEW FAST } [get_ports { ts_sdcard_clk }]; +set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { ts_sdcard_data[1] }]; +set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 SLEW FAST PULLUP TRUE } [get_ports { ts_sdcard_data[2] }]; +set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 PULLUP TRUE } [get_ports { ts_sdcard_cd }]; +#set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { ts_sdcard_wp }]; + ################################################################################ # Arduino/chipKIT shield connector ################################################################################ -set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io0 }]; -set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io1 }]; -set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io2 }]; -set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io3 }]; -set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io4 }]; -set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io5 }]; -set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io6 }]; -set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io7 }]; -set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io8 }]; +#set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io0 }]; +#set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io1 }]; +#set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io2 }]; +#set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io3 }]; +#set_property -dict { PACKAGE_PIN R12 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io4 }]; +#set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io5 }]; +#set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io6 }]; +#set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io7 }]; +#set_property -dict { PACKAGE_PIN N15 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io8 }]; set_property -dict { PACKAGE_PIN M16 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io9 }]; -set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io10 }]; -set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io11 }]; -set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io12 }]; -set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io13 }]; -set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io26 }]; -set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io27 }]; -set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io28 }]; -set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io29 }]; +#set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io10 }]; +#set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io11 }]; +#set_property -dict { PACKAGE_PIN R17 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io12 }]; +#set_property -dict { PACKAGE_PIN P17 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io13 }]; +#set_property -dict { PACKAGE_PIN U11 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io26 }]; +#set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io27 }]; +#set_property -dict { PACKAGE_PIN M13 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io28 }]; +#set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io29 }]; set_property -dict { PACKAGE_PIN R11 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io30 }]; set_property -dict { PACKAGE_PIN R13 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io31 }]; set_property -dict { PACKAGE_PIN R15 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io32 }]; set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io33 }]; -set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io34 }]; -set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io35 }]; -set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io36 }]; -set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io37 }]; -set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io38 }]; -set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io39 }]; -set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io40 }]; -set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io41 }]; +#set_property -dict { PACKAGE_PIN R16 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io34 }]; +#set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io35 }]; +#set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io36 }]; +#set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io37 }]; +#set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io38 }]; +#set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io39 }]; +#set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io40 }]; +#set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io41 }]; #set_property -dict { PACKAGE_PIN M17 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io42 }]; # A -set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io43 }]; # SCL -set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io44 }]; # SDA +#set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io43 }]; # SCL +#set_property -dict { PACKAGE_PIN M18 IOSTANDARD LVCMOS33 PULLDOWN TRUE } [get_ports { shield_io44 }]; # SDA #set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { shield_rst }]; #set_property -dict { PACKAGE_PIN C1 IOSTANDARD LVCMOS33 } [get_ports { spi_hdr_ss }]; diff --git a/fpga/top-arty.vhdl b/fpga/top-arty.vhdl index e86cecd..3d5f3f3 100644 --- a/fpga/top-arty.vhdl +++ b/fpga/top-arty.vhdl @@ -30,6 +30,7 @@ entity toplevel is HAS_UART1 : boolean := true; USE_LITESDCARD : boolean := false; HAS_GPIO : boolean := true; + USE_LCD : boolean := true; NGPIO : natural := 32 ); port( @@ -68,38 +69,46 @@ entity toplevel is sw3 : in std_ulogic; -- GPIO - shield_io0 : inout std_ulogic; - shield_io1 : inout std_ulogic; - shield_io2 : inout std_ulogic; - shield_io3 : inout std_ulogic; - shield_io4 : inout std_ulogic; - shield_io5 : inout std_ulogic; - shield_io6 : inout std_ulogic; - shield_io7 : inout std_ulogic; - shield_io8 : inout std_ulogic; + --shield_io0 : inout std_ulogic; + --shield_io1 : inout std_ulogic; + --shield_io2 : inout std_ulogic; + --shield_io3 : inout std_ulogic; + --shield_io4 : inout std_ulogic; + --shield_io5 : inout std_ulogic; + --shield_io6 : inout std_ulogic; + --shield_io7 : inout std_ulogic; + --shield_io8 : inout std_ulogic; shield_io9 : inout std_ulogic; - shield_io10 : inout std_ulogic; - shield_io11 : inout std_ulogic; - shield_io12 : inout std_ulogic; - shield_io13 : inout std_ulogic; - shield_io26 : inout std_ulogic; - shield_io27 : inout std_ulogic; - shield_io28 : inout std_ulogic; - shield_io29 : inout std_ulogic; + --shield_io10 : inout std_ulogic; + --shield_io11 : inout std_ulogic; + --shield_io12 : inout std_ulogic; + --shield_io13 : inout std_ulogic; + --shield_io26 : inout std_ulogic; + --shield_io27 : inout std_ulogic; + --shield_io28 : inout std_ulogic; + --shield_io29 : inout std_ulogic; shield_io30 : inout std_ulogic; shield_io31 : inout std_ulogic; shield_io32 : inout std_ulogic; shield_io33 : inout std_ulogic; - shield_io34 : inout std_ulogic; - shield_io35 : inout std_ulogic; - shield_io36 : inout std_ulogic; - shield_io37 : inout std_ulogic; - shield_io38 : inout std_ulogic; - shield_io39 : inout std_ulogic; - shield_io40 : inout std_ulogic; - shield_io41 : inout std_ulogic; - shield_io43 : inout std_ulogic; - shield_io44 : inout std_ulogic; + --shield_io34 : inout std_ulogic; + --shield_io35 : inout std_ulogic; + --shield_io36 : inout std_ulogic; + --shield_io37 : inout std_ulogic; + --shield_io38 : inout std_ulogic; + --shield_io39 : inout std_ulogic; + --shield_io40 : inout std_ulogic; + --shield_io41 : inout std_ulogic; + --shield_io43 : inout std_ulogic; + --shield_io44 : inout std_ulogic; + pmod_jb_1 : inout std_ulogic; + pmod_jb_2 : inout std_ulogic; + pmod_jb_3 : inout std_ulogic; + pmod_jb_4 : inout std_ulogic; + pmod_jb_7 : inout std_ulogic; + pmod_jb_8 : inout std_ulogic; + pmod_jb_9 : inout std_ulogic; + pmod_jb_10 : inout std_ulogic; -- Ethernet eth_ref_clk : out std_ulogic; @@ -116,11 +125,45 @@ entity toplevel is eth_col : in std_ulogic; eth_crs : in std_ulogic; - -- SD card - sdcard_data : inout std_ulogic_vector(3 downto 0); - sdcard_cmd : inout std_ulogic; - sdcard_clk : out std_ulogic; - sdcard_cd : in std_ulogic; + -- SD card pmod on JA + ja_sdcard_data : inout std_ulogic_vector(3 downto 0); + ja_sdcard_cmd : inout std_ulogic; + ja_sdcard_clk : out std_ulogic; + ja_sdcard_cd : in std_ulogic; + + -- SD card slot on touchscreen/LCD board + ts_sdcard_data : inout std_ulogic_vector(3 downto 0); + ts_sdcard_cmd : inout std_ulogic; + ts_sdcard_clk : out std_ulogic; + ts_sdcard_cd : in std_ulogic; + + -- Second SD card + sdcard2_data : inout std_ulogic_vector(3 downto 0); + sdcard2_cmd : inout std_ulogic; + sdcard2_clk : out std_ulogic; + sdcard2_cd : in std_ulogic; + + -- I2C RTC chip + i2c_rtc_d : inout std_ulogic; + i2c_rtc_c : inout std_ulogic; + + -- LCD display interface + lcd_d : inout std_ulogic_vector(7 downto 0); + lcd_rs : out std_ulogic; + lcd_cs : out std_ulogic; + lcd_rd : out std_ulogic; + lcd_wr : out std_ulogic; + lcd_rst : out std_ulogic; + + -- Differential analog inputs from touchscreen + a2_p : in std_ulogic; + a2_n : in std_ulogic; + a3_p : in std_ulogic; + a3_n : in std_ulogic; + a4_p : in std_ulogic; + a4_n : in std_ulogic; + a5_p : in std_ulogic; + a5_n : in std_ulogic; -- DRAM wires ddram_a : out std_ulogic_vector(13 downto 0); @@ -146,6 +189,8 @@ architecture behaviour of toplevel is -- Status signal run_out : std_ulogic; signal run_outs : std_ulogic_vector(CPUS-1 downto 0); + signal init_done : std_ulogic; + signal init_err : std_ulogic; -- Reset signals: signal soc_rst : std_ulogic; @@ -165,6 +210,7 @@ architecture behaviour of toplevel is signal wb_ext_is_dram_init : std_ulogic; signal wb_ext_is_eth : std_ulogic; signal wb_ext_is_sdcard : std_ulogic; + signal wb_ext_is_lcd : std_ulogic; -- DRAM main data wishbone connection signal wb_dram_in : wishbone_master_out; @@ -179,18 +225,28 @@ architecture behaviour of toplevel is -- LiteSDCard connection signal ext_irq_sdcard : std_ulogic := '0'; + signal ext_irq_sdcard2 : std_ulogic := '0'; signal wb_sdcard_out : wb_io_slave_out := wb_io_slave_out_init; + signal wb_sdcard2_out : wb_io_slave_out := wb_io_slave_out_init; signal wb_sddma_out : wb_io_master_out := wb_io_master_out_init; signal wb_sddma_in : wb_io_slave_out; signal wb_sddma_nr : wb_io_master_out; + signal wb_sddma1_nr : wb_io_master_out; + signal wb_sddma2_nr : wb_io_master_out; signal wb_sddma_ir : wb_io_slave_out; + signal wb_sddma1_ack : std_ulogic; + signal wb_sddma2_ack : std_ulogic; -- for conversion from non-pipelined wishbone to pipelined signal wb_sddma_stb_sent : std_ulogic; + -- LCD touchscreen connection + signal wb_lcd_out : wb_io_slave_out := wb_io_slave_out_init; + -- Status LED - signal led_b_pwm : std_ulogic_vector(3 downto 0); - signal led_r_pwm : std_ulogic_vector(3 downto 0); - signal led_g_pwm : std_ulogic_vector(3 downto 0); + signal led_b_pwm : std_ulogic_vector(3 downto 0) := (others => '0'); + signal led_r_pwm : std_ulogic_vector(3 downto 0) := (others => '0'); + signal led_g_pwm : std_ulogic_vector(3 downto 0) := (others => '0'); + signal disk_activity : std_ulogic := '0'; -- Dumb PWM for the LEDs, those RGB LEDs are too bright otherwise signal pwm_counter : std_ulogic_vector(8 downto 0); @@ -261,6 +317,8 @@ begin UART0_IS_16550 => UART_IS_16550, HAS_UART1 => HAS_UART1, HAS_SD_CARD => USE_LITESDCARD, + HAS_SD_CARD2 => USE_LITESDCARD, + HAS_LCD => USE_LCD, HAS_GPIO => HAS_GPIO, NGPIO => NGPIO ) @@ -295,6 +353,7 @@ begin -- External interrupts ext_irq_eth => ext_irq_eth, ext_irq_sdcard => ext_irq_sdcard, + ext_irq_sdcard2 => ext_irq_sdcard2, -- DRAM wishbone wb_dram_in => wb_dram_in, @@ -307,6 +366,7 @@ begin wb_ext_is_dram_init => wb_ext_is_dram_init, wb_ext_is_eth => wb_ext_is_eth, wb_ext_is_sdcard => wb_ext_is_sdcard, + wb_ext_is_lcd => wb_ext_is_lcd, -- DMA wishbone wishbone_dma_in => wb_sddma_in, @@ -383,9 +443,8 @@ begin pll_locked_out => system_clk_locked ); - led_b_pwm <= "1111"; - led_r_pwm <= "1111"; - led_g_pwm <= "0000"; + init_done <= '1'; + init_err <= '0'; -- Vivado barfs on those differential signals if left -- unconnected. So instanciate a diff. buffer and feed @@ -483,9 +542,8 @@ begin ddram_reset_n => ddram_reset_n ); - led_b_pwm(0) <= not dram_init_done; - led_r_pwm(0) <= dram_init_error; - led_g_pwm(0) <= dram_init_done and not dram_init_error; + init_done <= dram_init_done; + init_err <= dram_init_error; end generate; @@ -623,7 +681,7 @@ begin ext_irq_eth <= '0'; end generate; - -- SD card pmod + -- SD card pmod, two interfaces has_sdcard : if USE_LITESDCARD generate component litesdcard_core port ( clk : in std_ulogic; @@ -662,49 +720,133 @@ begin end component; signal wb_sdcard_cyc : std_ulogic; + signal wb_sdcard2_cyc : std_ulogic; signal wb_sdcard_adr : std_ulogic_vector(29 downto 0); + signal dma_msel : std_ulogic; + signal other_cyc : std_ulogic; + signal sdc0_activity : std_ulogic := '0'; + signal sdc1_activity : std_ulogic := '0'; begin - litesdcard : litesdcard_core + sdcard_ja: if not USE_LCD generate + litesdcard : litesdcard_core + port map ( + clk => system_clk, + rst => periph_rst, + wb_ctrl_adr => wb_sdcard_adr, + wb_ctrl_dat_w => wb_ext_io_in.dat, + wb_ctrl_dat_r => wb_sdcard_out.dat, + wb_ctrl_sel => wb_ext_io_in.sel, + wb_ctrl_cyc => wb_sdcard_cyc, + wb_ctrl_stb => wb_ext_io_in.stb, + wb_ctrl_ack => wb_sdcard_out.ack, + wb_ctrl_we => wb_ext_io_in.we, + wb_ctrl_cti => "000", + wb_ctrl_bte => "00", + wb_ctrl_err => open, + wb_dma_adr => wb_sddma1_nr.adr, + wb_dma_dat_w => wb_sddma1_nr.dat, + wb_dma_dat_r => wb_sddma_ir.dat, + wb_dma_sel => wb_sddma1_nr.sel, + wb_dma_cyc => wb_sddma1_nr.cyc, + wb_dma_stb => wb_sddma1_nr.stb, + wb_dma_ack => wb_sddma1_ack, + wb_dma_we => wb_sddma1_nr.we, + wb_dma_cti => open, + wb_dma_bte => open, + wb_dma_err => '0', + sdcard_data => ja_sdcard_data, + sdcard_cmd => ja_sdcard_cmd, + sdcard_clk => ja_sdcard_clk, + sdcard_cd => ja_sdcard_cd, + irq => ext_irq_sdcard + ); + end generate; + + sdcard_ts: if USE_LCD generate + litesdcard : litesdcard_core + port map ( + clk => system_clk, + rst => periph_rst, + wb_ctrl_adr => wb_sdcard_adr, + wb_ctrl_dat_w => wb_ext_io_in.dat, + wb_ctrl_dat_r => wb_sdcard_out.dat, + wb_ctrl_sel => wb_ext_io_in.sel, + wb_ctrl_cyc => wb_sdcard_cyc, + wb_ctrl_stb => wb_ext_io_in.stb, + wb_ctrl_ack => wb_sdcard_out.ack, + wb_ctrl_we => wb_ext_io_in.we, + wb_ctrl_cti => "000", + wb_ctrl_bte => "00", + wb_ctrl_err => open, + wb_dma_adr => wb_sddma1_nr.adr, + wb_dma_dat_w => wb_sddma1_nr.dat, + wb_dma_dat_r => wb_sddma_ir.dat, + wb_dma_sel => wb_sddma1_nr.sel, + wb_dma_cyc => wb_sddma1_nr.cyc, + wb_dma_stb => wb_sddma1_nr.stb, + wb_dma_ack => wb_sddma1_ack, + wb_dma_we => wb_sddma1_nr.we, + wb_dma_cti => open, + wb_dma_bte => open, + wb_dma_err => '0', + sdcard_data => ts_sdcard_data, + sdcard_cmd => ts_sdcard_cmd, + sdcard_clk => ts_sdcard_clk, + sdcard_cd => ts_sdcard_cd, + irq => ext_irq_sdcard + ); + end generate; + + litesdcard2 : litesdcard_core port map ( clk => system_clk, rst => periph_rst, wb_ctrl_adr => wb_sdcard_adr, wb_ctrl_dat_w => wb_ext_io_in.dat, - wb_ctrl_dat_r => wb_sdcard_out.dat, + wb_ctrl_dat_r => wb_sdcard2_out.dat, wb_ctrl_sel => wb_ext_io_in.sel, - wb_ctrl_cyc => wb_sdcard_cyc, + wb_ctrl_cyc => wb_sdcard2_cyc, wb_ctrl_stb => wb_ext_io_in.stb, - wb_ctrl_ack => wb_sdcard_out.ack, + wb_ctrl_ack => wb_sdcard2_out.ack, wb_ctrl_we => wb_ext_io_in.we, wb_ctrl_cti => "000", wb_ctrl_bte => "00", wb_ctrl_err => open, - wb_dma_adr => wb_sddma_nr.adr, - wb_dma_dat_w => wb_sddma_nr.dat, + wb_dma_adr => wb_sddma2_nr.adr, + wb_dma_dat_w => wb_sddma2_nr.dat, wb_dma_dat_r => wb_sddma_ir.dat, - wb_dma_sel => wb_sddma_nr.sel, - wb_dma_cyc => wb_sddma_nr.cyc, - wb_dma_stb => wb_sddma_nr.stb, - wb_dma_ack => wb_sddma_ir.ack, - wb_dma_we => wb_sddma_nr.we, + wb_dma_sel => wb_sddma2_nr.sel, + wb_dma_cyc => wb_sddma2_nr.cyc, + wb_dma_stb => wb_sddma2_nr.stb, + wb_dma_ack => wb_sddma2_ack, + wb_dma_we => wb_sddma2_nr.we, wb_dma_cti => open, wb_dma_bte => open, wb_dma_err => '0', - sdcard_data => sdcard_data, - sdcard_cmd => sdcard_cmd, - sdcard_clk => sdcard_clk, - sdcard_cd => sdcard_cd, - irq => ext_irq_sdcard + sdcard_data => sdcard2_data, + sdcard_cmd => sdcard2_cmd, + sdcard_clk => sdcard2_clk, + sdcard_cd => sdcard2_cd, + irq => ext_irq_sdcard2 ); - -- Gate cyc with chip select from SoC - wb_sdcard_cyc <= wb_ext_io_in.cyc and wb_ext_is_sdcard; + -- Gate cyc with chip selects from SoC + -- Select first or second interface based on real address bit 15 + wb_sdcard_cyc <= wb_ext_io_in.cyc and wb_ext_is_sdcard and not wb_ext_io_in.adr(13); + wb_sdcard2_cyc <= wb_ext_io_in.cyc and wb_ext_is_sdcard and wb_ext_io_in.adr(13); - wb_sdcard_adr <= x"0000" & wb_ext_io_in.adr(13 downto 0); + wb_sdcard_adr <= 17x"0" & wb_ext_io_in.adr(12 downto 0); wb_sdcard_out.stall <= not wb_sdcard_out.ack; - + wb_sdcard2_out.stall <= not wb_sdcard2_out.ack; + + -- Simple arbiter to multiplex the two DMA wishbones + wb_sddma_nr <= wb_sddma1_nr when dma_msel = '0' else wb_sddma2_nr; + wb_sddma1_ack <= wb_sddma_ir.ack and not dma_msel; + wb_sddma2_ack <= wb_sddma_ir.ack and dma_msel; + other_cyc <= wb_sddma2_nr.cyc when dma_msel = '0' else wb_sddma1_nr.cyc; + -- Convert non-pipelined DMA wishbone to pipelined by suppressing -- non-acknowledged strobes process(system_clk) @@ -721,16 +863,113 @@ begin wb_sddma_stb_sent <= wb_sddma_nr.stb; end if; wb_sddma_ir <= wb_sddma_in; + + -- Decide which wishbone to use next cycle + if periph_rst = '1' then + dma_msel <= '0'; + elsif wb_sddma_nr.cyc = '0' and other_cyc = '1' then + dma_msel <= not dma_msel; + end if; + end if; + end process; + + -- Capture writes to the interrupt enable registers, and record + -- the state of the command-done interrupt enable bit to use + -- as an activity indicator. + process(system_clk) + begin + if rising_edge(system_clk) then + if periph_rst = '1' then + sdc0_activity <= '0'; + sdc1_activity <= '0'; + elsif wb_sdcard_adr(11 downto 0) = x"602" + and wb_ext_io_in.stb = '1' and wb_ext_io_in.we = '1' then + if wb_sdcard_cyc = '1' then + sdc0_activity <= wb_ext_io_in.dat(3); + end if; + if wb_sdcard2_cyc = '1' then + sdc1_activity <= wb_ext_io_in.dat(3); + end if; + end if; end if; end process; + disk_activity <= sdc0_activity or sdc1_activity; + end generate; + -- LCD touchscreen on arduino-compatible pins + has_lcd : if USE_LCD generate + signal lcd_dout : std_ulogic_vector(7 downto 0); + signal lcd_doe : std_ulogic; + signal lcd_doe0 : std_ulogic; + signal lcd_doe1 : std_ulogic; + signal lcd_rso : std_ulogic; + signal lcd_rsoe : std_ulogic; + signal lcd_cso : std_ulogic; + signal lcd_csoe : std_ulogic; + signal tp : std_ulogic; + begin + lcd0 : entity work.lcd_touchscreen + port map ( + clk => system_clk, + rst => soc_rst, + wb_in => wb_ext_io_in, + wb_out => wb_lcd_out, + wb_sel => wb_ext_is_lcd, + tp => tp, + + lcd_din => lcd_d, + lcd_dout => lcd_dout, + lcd_doe => lcd_doe, + lcd_doe0 => lcd_doe0, + lcd_doe1 => lcd_doe1, + lcd_rd => lcd_rd, + lcd_wr => lcd_wr, + lcd_rs => lcd_rso, + lcd_rsoe => lcd_rsoe, + lcd_cs => lcd_cso, + lcd_csoe => lcd_csoe, + lcd_rst => lcd_rst, + + a2_p => a2_p, + a2_n => a2_n, + a3_p => a3_p, + a3_n => a3_n, + a4_p => a4_p, + a4_n => a4_n, + a5_p => a5_p, + a5_n => a5_n + ); + -- lcd_d(0), lcd_d(1), lcd_rs, lcd_cs are used for the touchscreen + -- interface and hence have individual output enables. + lcd_d(0) <= lcd_dout(0) when lcd_doe0 = '1' else 'Z'; + lcd_d(1) <= lcd_dout(1) when lcd_doe1 = '1' else 'Z'; + lcd_d(7 downto 2) <= lcd_dout(7 downto 2) when lcd_doe = '1' else (others => 'Z'); + lcd_rs <= lcd_rso when lcd_rsoe = '1' else 'Z'; + lcd_cs <= lcd_cso when lcd_csoe = '1' else 'Z'; end generate; -- Mux WB response on the IO bus wb_ext_io_out <= wb_eth_out when wb_ext_is_eth = '1' else - wb_sdcard_out when wb_ext_is_sdcard = '1' else + wb_sdcard_out when wb_ext_is_sdcard = '1' and wb_ext_io_in.adr(13) = '0' else + wb_sdcard2_out when wb_ext_is_sdcard = '1' and wb_ext_io_in.adr(13) = '1' else + wb_lcd_out when wb_ext_is_lcd = '1' else wb_dram_ctrl_out; + status_led_colour : process(all) + variable rgb : std_ulogic_vector(2 downto 0); + begin + if soc_rst = '1' then + rgb := "000"; + elsif system_clk_locked = '0' then + rgb := "110"; + else + rgb := init_err & (init_done and not init_err) & (not init_done); + end if; + led_r_pwm(0) <= rgb(2); + led_g_pwm(0) <= rgb(1); + led_b_pwm(0) <= rgb(0); + end process; + leds_pwm : process(system_clk) begin if rising_edge(system_clk) then @@ -747,8 +986,8 @@ begin end if; end process; - led4 <= system_clk_locked; - led5 <= not soc_rst; + led4 <= '0'; + led5 <= disk_activity; led6 <= run_outs(1) when CPUS > 1 else '0'; led7 <= run_outs(0); @@ -762,82 +1001,58 @@ begin gpio_in(16) <= sw2; gpio_in(17) <= sw3; - gpio_in(0) <= shield_io10; - gpio_in(1) <= shield_io11; - gpio_in(2) <= shield_io12; - gpio_in(3) <= shield_io13; - gpio_in(4) <= shield_io26; - gpio_in(5) <= shield_io27; - gpio_in(6) <= shield_io28; - gpio_in(7) <= shield_io29; - gpio_in(8) <= shield_io8; + gpio_in(0) <= '0'; + gpio_in(1) <= '0'; + gpio_in(2) <= '0'; + gpio_in(3) <= '0'; + gpio_in(4) <= '0'; + gpio_in(5) <= '0'; + gpio_in(6) <= '0'; + gpio_in(7) <= '0'; + gpio_in(8) <= '0'; + gpio_in(9) <= shield_io9; - --gpio_in(10) <= shield_io10; - --gpio_in(11) <= shield_io11; - --gpio_in(12) <= shield_io12; - --gpio_in(13) <= shield_io13; - --gpio_in(14) <= shield_io26; - --gpio_in(15) <= shield_io27; - --gpio_in(16) <= shield_io28; - --gpio_in(17) <= shield_io29; gpio_in(18) <= shield_io30; gpio_in(19) <= shield_io31; gpio_in(20) <= shield_io32; gpio_in(21) <= shield_io33; - gpio_in(22) <= shield_io34; - gpio_in(23) <= shield_io35; - gpio_in(24) <= shield_io36; - gpio_in(25) <= shield_io37; - gpio_in(26) <= shield_io38; - gpio_in(27) <= shield_io39; - gpio_in(28) <= shield_io40; - gpio_in(29) <= shield_io41; - gpio_in(30) <= shield_io43; - gpio_in(31) <= shield_io44; - - led_b_pwm(1) <= gpio_out(0) when gpio_dir(0) = '1' else 'Z'; - led_g_pwm(1) <= gpio_out(1) when gpio_dir(1) = '1' else 'Z'; - led_r_pwm(1) <= gpio_out(2) when gpio_dir(2) = '1' else 'Z'; - - led_b_pwm(2) <= gpio_out(3) when gpio_dir(3) = '1' else 'Z'; - led_g_pwm(2) <= gpio_out(4) when gpio_dir(4) = '1' else 'Z'; - led_r_pwm(2) <= gpio_out(5) when gpio_dir(5) = '1' else 'Z'; - - led_b_pwm(3) <= gpio_out(6) when gpio_dir(6) = '1' else 'Z'; - led_g_pwm(3) <= gpio_out(7) when gpio_dir(7) = '1' else 'Z'; - led_r_pwm(3) <= gpio_out(8) when gpio_dir(8) = '1' else 'Z'; - - --shield_io0 <= gpio_out(0) when gpio_dir(0) = '1' else 'Z'; - --shield_io1 <= gpio_out(1) when gpio_dir(1) = '1' else 'Z'; - --shield_io2 <= gpio_out(2) when gpio_dir(2) = '1' else 'Z'; - --shield_io3 <= gpio_out(3) when gpio_dir(3) = '1' else 'Z'; - --shield_io4 <= gpio_out(4) when gpio_dir(4) = '1' else 'Z'; - --shield_io5 <= gpio_out(5) when gpio_dir(5) = '1' else 'Z'; - --shield_io6 <= gpio_out(6) when gpio_dir(6) = '1' else 'Z'; - --shield_io7 <= gpio_out(7) when gpio_dir(7) = '1' else 'Z'; - --shield_io8 <= gpio_out(8) when gpio_dir(8) = '1' else 'Z'; + gpio_in(22) <= i2c_rtc_d; + gpio_in(23) <= i2c_rtc_c; + gpio_in(24) <= pmod_jb_1; + gpio_in(25) <= pmod_jb_2; + gpio_in(26) <= pmod_jb_3; + gpio_in(27) <= pmod_jb_4; + gpio_in(28) <= pmod_jb_7; + gpio_in(29) <= pmod_jb_8; + gpio_in(30) <= pmod_jb_9; + gpio_in(31) <= pmod_jb_10; + + led_b_pwm(1) <= gpio_out(0) and gpio_dir(0); + led_g_pwm(1) <= gpio_out(1) and gpio_dir(1); + led_r_pwm(1) <= gpio_out(2) and gpio_dir(2); + + led_b_pwm(2) <= gpio_out(3) and gpio_dir(3); + led_g_pwm(2) <= gpio_out(4) and gpio_dir(4); + led_r_pwm(2) <= gpio_out(5) and gpio_dir(5); + + led_b_pwm(3) <= gpio_out(6) and gpio_dir(6); + led_g_pwm(3) <= gpio_out(7) and gpio_dir(7); + led_r_pwm(3) <= gpio_out(8) and gpio_dir(8); + shield_io9 <= gpio_out(9) when gpio_dir(9) = '1' else 'Z'; - shield_io10 <= gpio_out(10) when gpio_dir(10) = '1' else 'Z'; - shield_io11 <= gpio_out(11) when gpio_dir(11) = '1' else 'Z'; - shield_io12 <= gpio_out(12) when gpio_dir(12) = '1' else 'Z'; - shield_io13 <= gpio_out(13) when gpio_dir(13) = '1' else 'Z'; - shield_io26 <= gpio_out(14) when gpio_dir(14) = '1' else 'Z'; - shield_io27 <= gpio_out(15) when gpio_dir(15) = '1' else 'Z'; - shield_io28 <= gpio_out(16) when gpio_dir(16) = '1' else 'Z'; - shield_io29 <= gpio_out(17) when gpio_dir(17) = '1' else 'Z'; shield_io30 <= gpio_out(18) when gpio_dir(18) = '1' else 'Z'; shield_io31 <= gpio_out(19) when gpio_dir(19) = '1' else 'Z'; shield_io32 <= gpio_out(20) when gpio_dir(20) = '1' else 'Z'; shield_io33 <= gpio_out(21) when gpio_dir(21) = '1' else 'Z'; - shield_io34 <= gpio_out(22) when gpio_dir(22) = '1' else 'Z'; - shield_io35 <= gpio_out(23) when gpio_dir(23) = '1' else 'Z'; - shield_io36 <= gpio_out(24) when gpio_dir(24) = '1' else 'Z'; - shield_io37 <= gpio_out(25) when gpio_dir(25) = '1' else 'Z'; - shield_io38 <= gpio_out(26) when gpio_dir(26) = '1' else 'Z'; - shield_io39 <= gpio_out(27) when gpio_dir(27) = '1' else 'Z'; - shield_io40 <= gpio_out(28) when gpio_dir(28) = '1' else 'Z'; - shield_io41 <= gpio_out(29) when gpio_dir(29) = '1' else 'Z'; - shield_io43 <= gpio_out(30) when gpio_dir(30) = '1' else 'Z'; - shield_io44 <= gpio_out(31) when gpio_dir(31) = '1' else 'Z'; + i2c_rtc_d <= gpio_out(22) when gpio_dir(22) = '1' else 'Z'; + i2c_rtc_c <= gpio_out(23) when gpio_dir(23) = '1' else 'Z'; + pmod_jb_1 <= gpio_out(24) when gpio_dir(24) = '1' else 'Z'; + pmod_jb_2 <= gpio_out(25) when gpio_dir(25) = '1' else 'Z'; + pmod_jb_3 <= gpio_out(26) when gpio_dir(26) = '1' else 'Z'; + pmod_jb_4 <= gpio_out(27) when gpio_dir(27) = '1' else 'Z'; + pmod_jb_7 <= gpio_out(28) when gpio_dir(28) = '1' else 'Z'; + pmod_jb_8 <= gpio_out(29) when gpio_dir(29) = '1' else 'Z'; + pmod_jb_9 <= gpio_out(30) when gpio_dir(30) = '1' else 'Z'; + pmod_jb_10 <= gpio_out(31) when gpio_dir(31) = '1' else 'Z'; end architecture behaviour; diff --git a/include/microwatt_soc.h b/include/microwatt_soc.h index 6e367b1..6203535 100644 --- a/include/microwatt_soc.h +++ b/include/microwatt_soc.h @@ -19,6 +19,7 @@ #define LETH_CSR_BASE 0xc8020000 /* LiteEth CSR registers */ #define LETH_SRAM_BASE 0xc8030000 /* LiteEth MMIO space */ #define LSDC_CSR_BASE 0xc8040000 /* LiteSDCard MMIO space */ +#define LSDC2_CSR_BASE 0xc8048000 /* 2nd LiteSDCard MMIO space */ #define SPI_FLASH_BASE 0xf0000000 /* SPI Flash memory map */ #define DRAM_INIT_BASE 0xff000000 /* Internal DRAM init firmware */ @@ -30,6 +31,7 @@ #define IRQ_UART1 2 #define IRQ_SDCARD 3 #define IRQ_GPIO 4 +#define IRQ_SDCARD2 5 /* * Register definitions for the syscon registers @@ -46,6 +48,7 @@ #define SYS_REG_INFO_HAS_UART1 (1ull << 6) #define SYS_REG_INFO_HAS_ARTB (1ull << 7) #define SYS_REG_INFO_HAS_LITESDCARD (1ull << 8) +#define SYS_REG_INFO_HAS_LITESDCARD2 (1ull << 9) #define SYS_REG_BRAMINFO 0x10 #define SYS_REG_BRAMINFO_SIZE_MASK 0xfffffffffffffull #define SYS_REG_DRAMINFO 0x18 diff --git a/microwatt.core b/microwatt.core index c1f6184..b54248e 100644 --- a/microwatt.core +++ b/microwatt.core @@ -139,6 +139,10 @@ filesets: uart16550: depend : [":microwatt:uart16550"] + lcdts: + files: + - fpga/arty-lcd-ts.vhdl : {file_type : vhdlSource-2008} + targets: nexys_a7: default_tool: vivado @@ -315,7 +319,7 @@ targets: arty_a7-100-nodram: default_tool: vivado - filesets: [core, arty_a7, soc, fpga, debug_xilinx, uart16550, xilinx_specific, litesdcard] + filesets: [core, arty_a7, soc, fpga, debug_xilinx, uart16550, xilinx_specific, litesdcard, lcdts] parameters : - memory_size - ram_init_file @@ -336,7 +340,7 @@ targets: arty_a7-100: default_tool: vivado - filesets: [core, arty_a7, soc, fpga, debug_xilinx, litedram, liteeth, uart16550, xilinx_specific, litesdcard] + filesets: [core, arty_a7, soc, fpga, debug_xilinx, litedram, liteeth, uart16550, xilinx_specific, litesdcard, lcdts] parameters: - cpus - memory_size @@ -344,6 +348,7 @@ targets: - use_litedram=true - use_liteeth=true - use_litesdcard + - use_lcd - disable_flatten_core - no_bram - spi_flash_offset=4194304 @@ -570,6 +575,12 @@ parameters: paramtype : generic default : false + use_lcd: + datatype : bool + description : Use LCD touchscreen interface + paramtype : generic + default : false + uart_is_16550: datatype : bool description : Use 16550-compatible UART from OpenCores diff --git a/soc.vhdl b/soc.vhdl index 3daeb73..539b26e 100644 --- a/soc.vhdl +++ b/soc.vhdl @@ -34,6 +34,7 @@ use work.wishbone_types.all; -- 0xc8020000: LiteEth CSRs (*) -- 0xc8030000: LiteEth MMIO (*) -- 0xc8040000: LiteSDCard CSRs +-- 0xc8050000: LCD touchscreen interface -- (*) LiteEth must be a single aligned 32KB block as the CSRs and MMIOs -- are actually decoded as a single wishbone which LiteEth will @@ -50,6 +51,7 @@ use work.wishbone_types.all; -- 2 : UART1 -- 3 : SD card -- 4 : GPIO +-- 5 : SD card 2 -- Resets: -- The soc can be reset externally by its parent top- entity (via rst port), @@ -93,6 +95,8 @@ entity soc is DCACHE_TLB_SET_SIZE : natural := 64; DCACHE_TLB_NUM_WAYS : natural := 2; HAS_SD_CARD : boolean := false; + HAS_SD_CARD2 : boolean := false; + HAS_LCD : boolean := false; HAS_GPIO : boolean := false; NGPIO : natural := 32 ); @@ -114,6 +118,7 @@ entity soc is wb_ext_is_dram_init : out std_ulogic; wb_ext_is_eth : out std_ulogic; wb_ext_is_sdcard : out std_ulogic; + wb_ext_is_lcd : out std_ulogic; -- external DMA wishbone with 32-bit data/address wishbone_dma_in : out wb_io_slave_out := wb_io_slave_out_init; @@ -122,6 +127,7 @@ entity soc is -- External interrupts ext_irq_eth : in std_ulogic := '0'; ext_irq_sdcard : in std_ulogic := '0'; + ext_irq_sdcard2 : in std_ulogic := '0'; -- UART0 signals: uart0_txd : out std_ulogic; @@ -683,6 +689,7 @@ begin wb_ext_is_dram_csr <= '0'; wb_ext_is_eth <= '0'; wb_ext_is_sdcard <= '0'; + wb_ext_is_lcd <= '0'; end if; if do_cyc = '1' then -- Decode I/O address @@ -712,6 +719,10 @@ begin slave_io := SLAVE_IO_EXTERNAL; io_cycle_external <= '1'; wb_ext_is_sdcard <= '1'; + elsif std_match(match, x"--05-") and HAS_LCD then + slave_io := SLAVE_IO_EXTERNAL; + io_cycle_external <= '1'; + wb_ext_is_lcd <= '1'; else io_cycle_none <= '1'; end if; @@ -822,6 +833,7 @@ begin SPI_FLASH_OFFSET => SPI_FLASH_OFFSET, HAS_LITEETH => HAS_LITEETH, HAS_SD_CARD => HAS_SD_CARD, + HAS_SD_CARD2 => HAS_SD_CARD2, UART0_IS_16550 => UART0_IS_16550, HAS_UART1 => HAS_UART1 ) @@ -1031,6 +1043,7 @@ begin int_level_in(2) <= uart1_irq; int_level_in(3) <= ext_irq_sdcard; int_level_in(4) <= gpio_intr; + int_level_in(5) <= ext_irq_sdcard2; end process; -- BRAM Memory slave diff --git a/syscon.vhdl b/syscon.vhdl index ad9ba2c..bdeabd2 100644 --- a/syscon.vhdl +++ b/syscon.vhdl @@ -21,6 +21,7 @@ entity syscon is SPI_FLASH_OFFSET : integer; HAS_LITEETH : boolean; HAS_SD_CARD : boolean; + HAS_SD_CARD2 : boolean; UART0_IS_16550 : boolean; HAS_UART1 : boolean ); @@ -75,6 +76,7 @@ architecture behaviour of syscon is constant SYS_REG_INFO_HAS_URT1 : integer := 6; -- Has second UART constant SYS_REG_INFO_HAS_ARTB : integer := 7; -- Has architected TB frequency constant SYS_REG_INFO_HAS_SDCARD : integer := 8; -- Has LiteSDCard SD-card interface + constant SYS_REG_INFO_HAS_SDCARD2 : integer := 9; -- Has 2nd LiteSDCard SD-card interface -- BRAMINFO contains the BRAM size in the bottom 52 bits -- DRAMINFO contains the DRAM size if any in the bottom 52 bits @@ -129,6 +131,7 @@ architecture behaviour of syscon is signal info_has_spif : std_ulogic; signal info_has_leth : std_ulogic; signal info_has_lsdc : std_ulogic; + signal info_has_lsd2 : std_ulogic; signal info_has_urt1 : std_ulogic; signal info_clk : std_ulogic_vector(39 downto 0); signal info_fl_off : std_ulogic_vector(31 downto 0); @@ -155,6 +158,7 @@ begin info_has_spif <= '1' when HAS_SPI_FLASH else '0'; info_has_leth <= '1' when HAS_LITEETH else '0'; info_has_lsdc <= '1' when HAS_SD_CARD else '0'; + info_has_lsd2 <= '1' when HAS_SD_CARD2 else '0'; info_has_urt1 <= '1' when HAS_UART1 else '0'; info_clk <= std_ulogic_vector(to_unsigned(CLK_FREQ, 40)); reg_info <= (SYS_REG_INFO_HAS_UART => info_has_uart, @@ -163,6 +167,7 @@ begin SYS_REG_INFO_HAS_SPIF => info_has_spif, SYS_REG_INFO_HAS_LETH => info_has_leth, SYS_REG_INFO_HAS_SDCARD => info_has_lsdc, + SYS_REG_INFO_HAS_SDCARD2 => info_has_lsd2, SYS_REG_INFO_HAS_LSYS => '1', SYS_REG_INFO_HAS_URT1 => info_has_urt1, others => '0'); diff --git a/xilinx-mult.vhdl b/xilinx-mult.vhdl index 26ba5d7..b78e950 100644 --- a/xilinx-mult.vhdl +++ b/xilinx-mult.vhdl @@ -960,7 +960,7 @@ begin CEALUMODE => valid_1, CEB1 => '0', CEB2 => valid_1, - CEC => valid_1, + CEC => '0', CECARRYIN => '0', CECTRL => '0', CED => '0',