From 12bbdb42cdcf5e6e39832d75fbbd31e3781d550a Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Fri, 11 Apr 2014 19:29:53 +0200 Subject: Import fichiers projet Quartus --- FPGA/vhdl/clock_divider.vhd | 57 ++++++ FPGA/vhdl/codec_config.vhd | 92 +++++++++ FPGA/vhdl/codec_dac.vhd | 110 +++++++++++ FPGA/vhdl/dds_sinus.vhd | 101 ++++++++++ FPGA/vhdl/i2c_master.vhd | 255 +++++++++++++++++++++++++ FPGA/vhdl/lcd.vhd | 89 +++++++++ FPGA/vhdl/lcd_controller.vhd | 363 ++++++++++++++++++++++++++++++++++++ FPGA/vhdl/lcd_message.vhd | 158 ++++++++++++++++ FPGA/vhdl/message.vhd | 67 +++++++ FPGA/vhdl/rom_sinus.vhd | 75 ++++++++ FPGA/vhdl/seven_segment_decoder.vhd | 72 +++++++ 11 files changed, 1439 insertions(+) create mode 100644 FPGA/vhdl/clock_divider.vhd create mode 100644 FPGA/vhdl/codec_config.vhd create mode 100644 FPGA/vhdl/codec_dac.vhd create mode 100644 FPGA/vhdl/dds_sinus.vhd create mode 100644 FPGA/vhdl/i2c_master.vhd create mode 100644 FPGA/vhdl/lcd.vhd create mode 100644 FPGA/vhdl/lcd_controller.vhd create mode 100644 FPGA/vhdl/lcd_message.vhd create mode 100644 FPGA/vhdl/message.vhd create mode 100644 FPGA/vhdl/rom_sinus.vhd create mode 100644 FPGA/vhdl/seven_segment_decoder.vhd diff --git a/FPGA/vhdl/clock_divider.vhd b/FPGA/vhdl/clock_divider.vhd new file mode 100644 index 0000000..3a061bb --- /dev/null +++ b/FPGA/vhdl/clock_divider.vhd @@ -0,0 +1,57 @@ +------------------------------------------------------ +-- Clock Divider +------------------------------------------------------ +-- Creation : A. Exertier, 2005 +------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; + +------------------------------------------------------ +-- PARAMETRES GENERIQUES +------------------------------------------------------ +-- board_frequency : frequency of the FPGA +-- user_frequency : desired frequency +------------------------------------------------------ +-- INPUTS +------------------------------------------------------ +-- clk : main clock +-- resetn : asynchronous active low reset +------------------------------------------------------ +-- OUTPUT +------------------------------------------------------ +-- en_user : signal at user_frequency +-- set to 1 only 1 main clock cycle +------------------------------------------------------ + + +entity clock_divider is + generic( + board_frequency : real :=50_000_000.0; -- 50 MHz + user_frequency : real :=4.0); -- 4 Hz + Port ( + clk : in std_logic; + resetn : in std_logic; -- active low + en_user : out std_logic); +end clock_divider; + +architecture RTL of clock_divider is + constant max : natural := integer(board_frequency/user_frequency); +begin + process(clk,resetn) + variable counter : natural range 0 to max-1; + begin + if resetn='0' then + counter := 0; + en_user <= '0'; + elsif rising_edge(clk) then + if counter = max-1 then + counter := 0; + en_user <= '1'; + else + counter := counter+1; + en_user <= '0'; + end if; + end if; + end process; +end RTL; diff --git a/FPGA/vhdl/codec_config.vhd b/FPGA/vhdl/codec_config.vhd new file mode 100644 index 0000000..2ae71f8 --- /dev/null +++ b/FPGA/vhdl/codec_config.vhd @@ -0,0 +1,92 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity codec_config is + generic ( + system_frequency : real := 50.0E6; -- 50 MHz + i2c_rate : real := 20.0E3 -- 20 kHz + ); + port ( + clk : in std_logic; + resetn : in std_logic; + end_config : out std_logic; + i2c_scl : out std_logic; + i2c_sda : inout std_logic + ); +end entity; + +architecture rtl of codec_config is + type t_config is array(natural range 0 to 10) of std_logic_vector(23 downto 0); + constant config_data : t_config := + (X"34001A", + X"34021A", + X"34047B", + X"34067B", + X"3408F8", + X"340A06", + X"340C00", + X"340E01", + X"341002", + X"341201", + X"000000" + ); + type state is (init, config, finished); + signal i2c_data : std_logic_vector(23 downto 0); + signal i2c_go : std_logic; + signal i2c_ack : std_logic; + signal i2c_ready : std_logic; + signal ctr_data : natural range 0 to 10; + signal current_state : state; + +begin + + i2c_data <= config_data(ctr_data); + + process(resetn, clk) is + begin + if resetn = '0' then + ctr_data <= 0; + current_state <= init; + i2c_go <= '0'; + end_config <= '0'; + elsif rising_edge(clk) then + case current_state is + when init => i2c_go <= '1'; + if i2c_ready = '0' then + current_state <= config; + ctr_data <= ctr_data+1; + end if; + + when config => i2c_go <= '0'; + if i2c_ready = '1' then + if ctr_data<10 then + current_state <= init; + else + current_state <= finished; + end if; + end if; + when finished => end_config <= '1'; + i2c_go <= '0'; + end case; + + end if; + end process; + + + i2c_ctrl : entity work.i2C_master + generic map ( + system_frequency => system_frequency, + i2c_rate => i2c_rate + ) + port map ( + clk => clk, + resetn => resetn, + go => i2c_go, + ready => i2c_ready, + data_in => i2c_data, + i2c_scl => i2c_scl, + i2c_sda => i2c_sda, + ack => i2c_ack + ); +end architecture; \ No newline at end of file diff --git a/FPGA/vhdl/codec_dac.vhd b/FPGA/vhdl/codec_dac.vhd new file mode 100644 index 0000000..0cfd858 --- /dev/null +++ b/FPGA/vhdl/codec_dac.vhd @@ -0,0 +1,110 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity codec_dac is + generic ( + system_frequency : real := 50.0E6; -- 50 MHz + sample_rate : real := 48.0E3; -- 48 kHz + data_width : positive := 16; -- 16 bits + channel_num : positive := 2 -- dual channel + ); + port ( + clk : in std_logic; -- + resetn : in std_logic; -- + go : in std_logic; + data_in : in std_logic_vector(data_width-1 downto 0); + -- codec + tempo_dac : out std_logic; + end_dac : out std_logic; + codec_dac_bclk : out std_logic; -- B4 + codec_dac_data : out std_logic; -- A4 + codec_dac_lrck : out std_logic -- C6 + ); +end entity; +architecture rtl of codec_dac is + constant mod_bclk : positive := integer(system_frequency/(2.0*sample_rate*real(data_width)*real(channel_num))); + constant mod_lrck : positive := data_width*channel_num/2; + type state is (wait_for_go, tx); + signal current_state : state; + signal next_state : state; + signal ctr_bclk : natural range 0 to mod_bclk-1; + signal ctr_lrck : natural range 0 to mod_lrck-1; + signal reg_data : std_logic_vector(data_in'range); + signal cmd_data : std_logic_vector(1 downto 0); + signal bclk : std_logic; + signal lrck : std_logic; + signal end_bit : std_logic; +begin + codec_dac_bclk <= bclk; + codec_dac_lrck <= lrck; + codec_dac_data <= reg_data(reg_data'low); + tempo_dac <= end_bit; + end_bit <= '0' when (ctr_bclk< mod_bclk-1) or bclk='0' + else '1'; + -- registers and counters + process(clk, resetn) is + begin + if resetn ='0' then + bclk <= '0'; + lrck <= '0'; + reg_data <= (others => '0'); + ctr_bclk <= 0; + ctr_lrck <= 0; + current_state <= wait_for_go; + elsif rising_edge(clk) then + current_state <= next_state; + if ctr_bclk< mod_bclk-1 then + ctr_bclk <= ctr_bclk+1; + else + ctr_bclk <= 0; + bclk <=not bclk; + end if; + + -- data register + case cmd_data is + when "10" => reg_data <= data_in; + when "11" => reg_data <= '0'®_data(reg_data'high downto 1); + when others => null; + end case; + + if end_bit = '1' then + if ctr_lrck < mod_lrck-1 then + ctr_lrck <= ctr_lrck +1; + else + ctr_lrck <= 0; + lrck <= not lrck; + end if; + end if; + end if; + end process; + process(current_state,go,end_bit, ctr_lrck) is + begin + next_state <= current_state; + cmd_data <= "00"; + end_dac <= '1'; + case current_state is + when wait_for_go => if go = '1' then + next_state <= tx; + cmd_data <= "10"; + end if; + when tx => if end_bit='1' then + if ctr_lrck >= mod_lrck-1 then + if go ='0' then + next_state <= wait_for_go; + else + cmd_data <= "10"; + end if; + else + cmd_data <= "11"; + end if; + end if; + end_dac <= '0'; + end case; + end process; +end architecture; + + + + + diff --git a/FPGA/vhdl/dds_sinus.vhd b/FPGA/vhdl/dds_sinus.vhd new file mode 100644 index 0000000..d47f290 --- /dev/null +++ b/FPGA/vhdl/dds_sinus.vhd @@ -0,0 +1,101 @@ +---------------------------------------------------- +-- DDS : sinus +---------------------------------------------------- +-- ESIEE +-- creation : A. Exertier, 06/2009 +-- modification : A. Exertier, 12/2011 +---------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +----------------------------------------------------- +-- GENERIC PARAMETER +----------------------------------------------------- +-- N_data : output data number of bits +-- M : phase accumulator precision +-- amplitude : sinus amplitude +-- should be < 2**N_data +----------------------------------------------------- +-- INPUTS +----------------------------------------------------- +-- clk : clock +-- resetn : asynchronous reset (active low) +-- incr_step : incrementation step (N_adr_ROM bits) +-- => sinus frequency +----------------------------------------------------- +-- OUTPUT +----------------------------------------------------- +-- dds_out : output data (N_data bits) +----------------------------------------------------- + +entity dds_sinus is + generic( + N_data : positive := 16; + M : positive := 12 + ); + port ( + resetn : in std_logic; + clk : in std_logic; + en : in std_logic; + incr_step : in std_logic_vector(M-1 downto 0); + dds_out : out std_logic_vector(N_data-1 downto 0) + ); +end dds_sinus; + +architecture RTL of dds_sinus is + constant amplitude : positive :=2**(N_data-1)-1; + constant N_adr_ROM : positive := M-2; + constant middle : unsigned (N_data-1 downto 0) := to_unsigned(2**(dds_out'length-1),dds_out'length); --(N_data-1=>'1', others => '0'); + + signal counter : unsigned(N_adr_ROM+1 downto 0); + signal address_sinus : std_logic_vector(N_adr_ROM-1 downto 0); + signal data_sinus : std_logic_vector(N_data-2 downto 0); + signal dds_out_int : std_logic_vector(dds_out'range); + + begin +------------------------------------ +-- counter & output register +------------------------------------ + process(resetn, clk) is + begin + if resetn = '0' then + counter <= (others => '0'); + dds_out <= (others => '0'); + dds_out(dds_out'high) <= '1'; + elsif rising_edge(clk) then + if en = '1' then + counter <= counter+unsigned(incr_step); + dds_out <= dds_out_int; + end if; + end if; + end process; + +------------------------------------- +-- address & signed output +------------------------------------- + +address_sinus <= std_logic_vector(counter(address_sinus'range)) + when counter <2**(N_adr_ROM) or (counter >= 2**(N_adr_ROM+1) and counter <2**(N_adr_ROM)*3) + else std_logic_vector(2**(N_adr_ROM)-1 - counter(address_sinus'range)) ; + +dds_out_int <= std_logic_vector(middle - unsigned(data_sinus)) + when (counter >=(2**(N_adr_ROM+1)) + unsigned(incr_step)) or (counter N_data, + N_adr_ROM => N_adr_ROM, + amplitude => amplitude + ) + port map( + address => address_sinus, + clk => clk, + data => data_sinus + ); + +end architecture; \ No newline at end of file diff --git a/FPGA/vhdl/i2c_master.vhd b/FPGA/vhdl/i2c_master.vhd new file mode 100644 index 0000000..99b179b --- /dev/null +++ b/FPGA/vhdl/i2c_master.vhd @@ -0,0 +1,255 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity i2C_master is + generic ( + system_frequency : real := 50.0E6; -- 50 MHz + i2c_rate : real := 20.0E3 -- 20 kHz + ); + port ( + clk : in std_logic; + resetn : in std_logic; + go : in std_logic; + ready : out std_logic; + data_in : in std_logic_vector(23 downto 0); -- adress & command & data + ack : out std_logic; + -- i2c + i2c_scl : out std_logic; -- A6 + i2c_sda : inout std_logic -- B6 + ); +end entity; + +architecture rtl of i2c_master is + constant mod_ctr_tempo : positive := integer(system_frequency/(2.0*i2c_rate)); + constant mod_ctr_bit : positive := 35; + type state is (wait_for_go, wait_for_i2clk, tx); + signal current_state : state; + signal next_state : state; + signal sdo : std_logic; + signal ctr_tempo : natural range 0 to mod_ctr_tempo-1; + signal end_tempo : std_logic; + signal ctr_bit : natural range 0 to mod_ctr_bit-1; + signal ack1 : std_logic; + signal ack2 : std_logic; + signal ack3 : std_logic; + signal reg_data : std_logic_vector(data_in'range); + signal cmd_data : std_logic_vector(1 downto 0); + signal cmd_bit : std_logic_vector(1 downto 0); + signal cmd_ack1 : std_logic_vector(1 downto 0); + signal cmd_ack2 : std_logic_vector(1 downto 0); + signal cmd_ack3 : std_logic_vector(1 downto 0); + signal sclk : std_logic; + signal i2c_clk : std_logic; + signal ready_i : std_logic; + +begin + i2c_sda <= 'Z' when sdo = '1' + else '0'; + i2c_scl <= '1' when sclk='1' + else not i2c_clk when (ctr_bit>=4 and ctr_bit <= 30) + else '0'; + ack <= ack1 or ack2 or ack3; + end_tempo <= '0' when ctr_tempo< mod_ctr_tempo-1 else '1'; + + process(resetn, clk) is + begin + if resetn = '0' then + i2c_clk <= '0'; + ctr_tempo <= 0; + ctr_bit <= 0; + reg_data <= (others => '0'); + --sclk <= '1'; + ACK1 <= '0'; + ACK2 <= '0'; + ACK3 <= '0'; + ready <= '1'; + current_state <= wait_for_go; + elsif rising_edge(clk) then + current_state <= next_state; + ready <= ready_i; + + -- temporisation et i2_clk + if current_state = wait_for_go then + ctr_tempo <= 0; + i2c_clk <= '0'; + elsif end_tempo='0' then + ctr_tempo <= ctr_tempo +1; + else + ctr_tempo <= 0; + i2c_clk <= not i2c_clk; + end if; + -- reg_data + case cmd_data is + when "10" => reg_data <= data_in; + when "11" => reg_data <= reg_data(22 downto 0)&'0'; + when others => null; + end case; + -- ctr_bit + case cmd_bit is + when "10" => ctr_bit <= 0; + when "11" => if ctr_bit null; + end case; + -- ack1 + case cmd_ack1 is + when "10" => ack1 <= '0'; + when "11" => ack1 <= '1'; + when others => null; + end case; + -- ack2 + case cmd_ack2 is + when "10" => ack2 <= '0'; + when "11" => ack2 <= '1'; + when others => null; + end case; + -- ack1 + case cmd_ack3 is + when "10" => ack3 <= '0'; + when "11" => ack3 <= '1'; + when others => null; + end case; + end if; +end process; +-------------------------------- +-- FSM +------------------------------- +process(current_state, end_tempo, i2c_clk, go,reg_data(23), i2c_sda,ctr_bit) is +begin + next_state <= current_state; + ready_i <= '0'; + cmd_ack1 <= "00"; + cmd_ack2 <= "00"; + cmd_ack3 <= "00"; + cmd_bit <= "00"; + cmd_data <= "00"; + sdo <= '1'; + sclk <= '0'; + case current_state is + when wait_for_go => if go = '1' then next_state <=wait_for_i2clk; + end if; + ready_i <= '1'; + cmd_bit <= "10"; + cmd_data <= "10"; + sclk <= '1'; + when wait_for_i2clk => if i2c_clk='0' and end_tempo='1' then next_state <=tx; + end if; + cmd_ack1 <= "10"; + cmd_ack2 <= "10"; + cmd_ack3 <= "10"; + sclk <= '1'; + when tx => if ctr_bit< mod_ctr_bit-1 then + if i2c_clk='0' and end_tempo='1'then + cmd_bit <= "11"; + end if; + elsif end_tempo='1'then + next_state <= wait_for_go; + end if; + case ctr_bit is + when 0 => sdo <= '1'; sclk <= '1'; + -- start + when 1 => sdo <= '0'; sclk <= '0'; + when 2 => sdo <= '0'; sclk <= '0'; + -- slave address + when 3 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 4 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 5 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 6 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 7 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 8 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 9 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 10 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 11 => sdo <= '1'; -- ack + + -- command + when 12 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + if i2c_sda='1' then cmd_ack1 <= "11" ; + else cmd_ack1 <= "10" ; + end if; + when 13 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 14 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 15 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 16 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 17 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 18 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 19 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 20 => sdo <= '1'; -- ack + -- data + when 21 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + if i2c_sda='1' then cmd_ack2 <= "11" ; + else cmd_ack2 <= "10" ; + end if; + when 22 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 23 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 24 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 25 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 26 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 27 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 28 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 29 => sdo <= '1'; -- ack + --stop + when 30 => sdo <= '0'; + if i2c_sda='1' then cmd_ack3 <= "11" ; + else cmd_ack3 <= "10" ; + end if; + sclk <= '0'; + when 31 => sdo <= '0'; sclk <= '1'; + when others => sdo <= '1'; sclk <= '1'; + end case; + + + end case; + +end process; + +end architecture; diff --git a/FPGA/vhdl/lcd.vhd b/FPGA/vhdl/lcd.vhd new file mode 100644 index 0000000..186aa52 --- /dev/null +++ b/FPGA/vhdl/lcd.vhd @@ -0,0 +1,89 @@ +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +entity lcd is + generic (board_frequency : real := 50_000_000.0); + port( + clk : in std_logic; + resetn : in std_logic; + + -- User Interface + ready : out std_logic; + mode : in std_logic_vector(1 downto 0); + char : in std_logic_vector(7 downto 0); + address : in std_logic_vector(6 downto 0); + write_char : in std_logic; + write_address : in std_logic; + + D : in std_logic; + C : in std_logic; + B : in std_logic; + + -- lcd signals + lcd_data : inout std_logic_vector(7 downto 0); + lcd_on : out std_logic; + lcd_blon : out std_logic; + lcd_rs : out std_logic; + lcd_rw : out std_logic; + lcd_en : out std_logic + ); +end entity; + +architecture rtl of lcd is + + signal en_user : std_logic; + signal lcd_data_int : std_logic_vector(lcd_data'range); + signal lcd_rs_int : std_logic; + signal lcd_en_int : std_logic; + +begin + +-------------------------------- +-- lcd +-------------------------------- +lcd_on <= '1'; +lcd_blon <= '1'; + + ctrl : entity work.lcd_Controller + port map( + Clk => clk, + resetn => resetn, + en_250kHz => en_user, + char => char, + D => D, + C => C, + B => B, + write_char => write_char, + mode => mode, + address => address, + write_address => write_address, + ready => ready, + lcd_data => lcd_data_int, + lcd_RS => lcd_rs_int, + lcd_RW => lcd_rw, + lcd_EN => lcd_en_int + ); + +ck : entity work.clock_divider + generic map (board_frequency => 50_000_000.0, + user_frequency => 250_000.0 ) + port map ( + clk => clk, + resetn => resetn, + en_user => en_user + ); + process(resetn,clk) is + begin + if resetn = '0' then + lcd_data <= (others => '0'); + lcd_rs <= '0'; + lcd_en <= '0'; + elsif rising_edge (clk) then + lcd_data <= lcd_data_int; + lcd_rs <= lcd_rs_int; + lcd_en <= lcd_en_int; + end if; + end process; +end architecture; + \ No newline at end of file diff --git a/FPGA/vhdl/lcd_controller.vhd b/FPGA/vhdl/lcd_controller.vhd new file mode 100644 index 0000000..0818db2 --- /dev/null +++ b/FPGA/vhdl/lcd_controller.vhd @@ -0,0 +1,363 @@ +---------------------------------------------------------- +-- LCD 2 lines controller +-- +-- 8 bits interface -- +---------------------------------------------------------- +-- ESIEE +-- Creation : A. Exertier, mars 2008 +---------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +---------------------------------------------------------- +-- INPUTS +---------------------------------------------------------- +-- clk : system clock +-- resetn : aynchronous active low reset +-- en_250kHz : enable at 250 kHz (lasts 1 clock cycle) +-- char : input ASCII character +-- write_char : write character command +-- ready : set to 1 when device is ready for a writing +---------------------------------------------------------- +-- OUTPUTS +---------------------------------------------------------- +-- LCD_DATA : ASCII data to LCD +-- LCD_RS : RS to LCD +-- LCD_RW : Read/write to LCD +-- LCD_EN : Enable to LCD +------------------------------------------------------------ + +Entity LCD_controller is + + port( + clk : in std_logic; + resetn : in std_logic; + en_250kHz : in std_logic; + + mode : in std_logic_vector(1 downto 0); + char : in std_logic_vector (7 downto 0); + address : in std_logic_vector(6 downto 0); + write_char : in std_logic; + write_address : in std_logic; + ready : out std_logic; + D : in std_logic; + C : in std_logic; + B : in std_logic; + + -- LCD signals + + LCD_data : inout std_logic_vector(7 downto 0); + LCD_RS : out std_logic; + LCD_RW : out std_logic; + LCD_EN : out std_logic + ); + +end LCD_Controller; + + + +Architecture RTL of LCD_Controller is + + type State_type is (Boot, FunctionSet, DisplayControl, EntryModeSet, Clear, + Address_set, Waiting, Verify, Putchar, Homecursor, + WriteAddress, WriteData); + signal present : State_type; + + signal future : State_type; + + +-- Timing Constants : + + constant T_30ms : integer := 30_000/4; -- 7500; -- 30 ms + + constant T_2ms : integer := 2_000/4; --500; -- 2 ms + + constant T_40us : integer := 12; -- > 39 us after E down + + constant En_delay : integer := 1; -- 8 us + + constant LastPosition : integer := 16; + + +-- CLEAR DisplayControl + constant CLR : std_logic_vector(7 downto 0) := "00000001"; +-- RETURN HOME + constant RET_HOME : std_logic_vector(7 downto 0) := "00000010"; -- 0000001x + -- DDRAM address to 0 (beginning of first line) + +-- ENTRY MODE SET + constant ENTRY_MODE : std_logic_vector(7 downto 0) := "00000110"; -- 0000 01 I/D S + -- I/D : 1 => Increment, 0 => Decrement + -- S : 1 => DisplayControl shift + +-- FUNCTION SET + constant FUNC_SET : std_logic_vector(7 downto 0) := "00111100"; -- 001 DL N F xx + -- DL : 1 => 8 bits, 0 => 4 bits + -- N : 1 => 2 lines, 0 => 1 line + -- F : 1 => 5x10 dots, 0 => 5x8 dots + +-- DisplayControl ON/OFF CONTROL + constant DON : std_logic_vector(7 downto 0) := "00001110"; -- 0000 1 D C B + -- D : 1 => Display on + -- C : 1 => Cursor on + -- B : 1 => Cursor blink on + + constant RET_LINE2 : std_logic_vector(7 downto 0) := "11000000"; + -- set DDRAM address to 32 (beginning of second line) + constant RET_LINE1 : std_logic_vector(7 downto 0) := "10000000"; + -- set DDRAM address to 0 (beginning of first line) + + + + signal Position : natural range 0 to 2*LastPosition; + + signal Count : natural range 0 to T_30ms; + signal inc_C : std_logic; + + signal cmd_P : std_logic_vector(1 downto 0); + --signal reset_P : std_logic; + + signal test_EN : std_logic; + signal test_T_40us : std_logic; + + + + begin + + + LCD_RW <= '0'; + + +process (Clk, resetn) + + begin + + if resetn = '0' then + + present <= Boot; + position <= 0; + count <= 0; + + elsif rising_edge(clk) then + + if en_250kHz = '1' then + + present <= future; + + if inc_C = '1' then count <= count+1; + + else count <= 0; + + end if; + case cmd_P is + when "00" => position <= 0; + when "01" => if position >= 31 then position <= 0; + else position <= position+1; + end if; + when "10" => if address(6 downto 4) = "000" then position <= to_integer(unsigned(address(3 downto 0))); + elsif address(6 downto 4) = "100" then position <= to_integer(unsigned(address(3 downto 0)))+16; + else position <= 0; + end if; + when others => null; + end case; + + end if; + + end if; + end process; + + +test_EN <= '1' when Count = En_delay else '0'; +test_T_40us <= '1' when count >= T_40us else '0'; + + process(present, Write_char, mode, write_address, count, Position,char, + address,test_EN, test_T_40us , D, C, b) is + + begin + + future <= present; + + inc_C <= '1'; + + cmd_P <= "11"; + + ready <= '0'; + + LCD_RS <= '0'; + + LCD_EN <= '0'; + + LCD_data <= X"00"; + + + + case present is + + + when Boot => -- Wait for 30 ms + + if Count = T_30ms then + future <= FunctionSet; + inc_C <= '0'; + end if; + cmd_P <= "00"; + + + + when FunctionSet => -- Function Set + LCD_data <= FUNC_SET; + + LCD_EN <= test_EN; + + if test_T_40us = '1' then + future <= EntryModeSet; + inc_C <= '0'; + end if; + cmd_P <= "00"; + + + + + when EntryModeSet => -- Entry Mode Set + + LCD_data <= ENTRY_MODE; + + LCD_EN <= test_EN; + + if test_T_40us = '1' then + future <= DisplayControl; + inc_C <= '0'; + end if; + cmd_P <= "00"; + + when DisplayControl => + -- Display ON/OFF control + + LCD_data <= DON(7 downto 3)&D&C&B; + LCD_EN <= test_EN; + + if test_T_40us = '1' then + future <= Clear; + inc_C <= '0'; + end if; + cmd_P <= "00"; + + when Clear => + -- Clear Display + LCD_data <= CLR; + LCD_EN <= test_EN; + if Count >= T_2ms then + inc_C <= '0'; + future <= Address_set; + end if; + cmd_P <= "00"; + + when Address_set => + -- DDRAM address set + LCD_data <= RET_LINE1; + + LCD_EN <= test_EN; + + if test_T_40us = '1' then + + future <= Waiting; + + inc_C <= '0'; + end if; + cmd_P <= "00"; + + when Waiting => + -- Waits for input + if mode (1) = '1' then + + if write_address = '1' then future <= WriteAddress; + elsif write_char = '1' then future <= WriteData; + end if; + elsif write_char = '1' then + + if char = x"0C" then future <= Clear; + else future <= Putchar; + end if; + end if; + + ready <= '1'; + + inc_C <= '0'; + + + when WriteAddress => + -- Set CGRAM/DDRAM Address + if mode(0) = '0' then LCD_data <= '1'&address; + else LCD_data <= "01"&address(5 downto 0); + end if; + LCD_EN <= test_EN; + if test_T_40us = '1' then + future <= Waiting; + inc_C <= '0'; + end if; + cmd_P <= "10"; + + when WriteData => + -- Write data to CGRAM or DDRAM + LCD_RS <= '1'; + LCD_EN <= test_EN; + LCD_DATA <= char; + if test_T_40us = '1' then + future <= Waiting; + inc_C <= '0'; + cmd_P <= "01"; + end if; + + + when Verify => + + if char = x"0C" then -- FormFeed => Clear Screen + + future <= Clear; + else future <= Putchar; + + end if; + inc_C <= '0'; + LCD_data <= char; + + + + when Putchar => + -- Display character on the LCD + LCD_RS <= '1'; + LCD_EN <= test_EN; + if test_T_40us = '1' then + if Position = 15 or Position = 31 then + future <= HomeCursor; + else future <= Waiting; + cmd_P <= "01"; + end if; + inc_C <= '0'; + end if; + LCD_data <= char; + + + + when HomeCursor => + LCD_EN <= test_EN; + if Position = 31 then LCD_data <= RET_LINE1; --RET_HOME; + else LCD_data <= RET_LINE2; + end if; + if test_T_40us = '1' then + --if Count >= T_2ms then + if Position = 31 then cmd_P <= "00"; + else cmd_P <= "01"; + end if; + future <= Waiting; + inc_C <= '0'; + + end if; + + end case; + + end process; + + +end RTL; diff --git a/FPGA/vhdl/lcd_message.vhd b/FPGA/vhdl/lcd_message.vhd new file mode 100644 index 0000000..7784055 --- /dev/null +++ b/FPGA/vhdl/lcd_message.vhd @@ -0,0 +1,158 @@ +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +entity lcd_message is + + port( + clk : in std_logic; + resetn : in std_logic; -- KEY0 + -- LCD signals + LCD_DATA : inout std_logic_vector(7 downto 0); + LCD_ON : out std_logic; + LCD_BLON : out std_logic; + LCD_RS : out std_logic; + LCD_RW : out std_logic; + LCD_EN : out std_logic + ); +end entity; + +architecture RTL of lcd_message is + constant board_frequency : real := 50_000_000.0; + constant mode : std_logic_vector(1 downto 0) := "00"; + constant address : std_logic_vector(6 downto 0):= "0000000"; + constant char : std_logic_vector(7 downto 0):= X"00"; + constant write_char : std_logic:='1'; + constant write_address : std_logic:='1'; + constant go : std_logic:='0'; + type state is (boot, message1,message2, waiting,write1,write2, reset1, reset2); + signal present : state; + signal future : state; + + signal lcd_write_char : std_logic; + signal lcd_write_address : std_logic; + signal Din : std_logic_vector (7 downto 0); + signal lcd_char : std_logic_vector (7 downto 0); + signal lcd_ready : std_logic; + signal cpt : std_logic_vector(4 downto 0); + signal inc_cpt : std_logic; + + + signal lcd_mode : std_logic_vector(1 downto 0); + signal lcd_address : std_logic_vector(address'range); + +begin + + +-------------------------------- +-- LCD +-------------------------------- + + dut : entity work.LCD + generic map (board_frequency => board_frequency) + port map( + Clk => clk, + resetn => resetn, + + D => '1', + C => '0', + B => '0', + + char => lcd_char, + write_char => lcd_write_char, + mode => lcd_mode, + address => lcd_address, + write_address => lcd_write_address, + ready => lcd_ready, + LCD_ON => LCD_ON, + LCD_BLON => LCD_BLON, + LCD_data => LCD_DATA, + Lcd_RS => LCD_RS, + Lcd_RW => LCD_RW, + Lcd_EN => LCD_EN + ); + + + + + + + rom : entity work.message + port map ( + adr => cpt, + do => din + ); + + process(resetn,clk) is + begin + if resetn = '0' then + present <= boot; + cpt <= (others => '0'); + elsif rising_edge (clk) then + present <= future; + if inc_cpt = '1' then cpt <= std_logic_vector(unsigned(cpt)+1); + end if; + end if; + end process; + + process(present, lcd_ready, cpt,Din ) is + begin + future <= present; + inc_cpt <= '0'; + + lcd_write_char <= '0'; + lcd_write_address <= '0'; + lcd_char <= char; + lcd_mode <= mode; + lcd_address <= address; + + case present is + when boot => if lcd_ready = '1' then future <= reset1; + end if; + lcd_mode <= "00"; + + + when waiting => future <= waiting; + + when reset1 => lcd_write_char <= '1'; + lcd_write_address <= '0'; + lcd_char <= X"0C"; + lcd_address <= "0000000"; + lcd_mode <= "00"; + if lcd_ready = '0' then future <= reset2; + end if; + + when reset2 => if lcd_ready = '1' then future <= message1; + end if; + + + when message1 => if lcd_ready = '0' then future <= message2; + end if; + lcd_write_char <= '1'; + lcd_mode <= "00"; + lcd_char <= Din; + + when message2 => if lcd_ready = '1' then + if unsigned (cpt) <31 then future <= message1; + else future <= waiting; + end if; + inc_cpt <= '1'; + end if; + lcd_mode <= "00"; + lcd_char <= Din; + + when write1 => lcd_write_char <= not write_char; + lcd_write_address <= not write_address; + lcd_char <= char; + if lcd_ready = '0' then future <= write2; + end if; + + when write2 => if write_char= '1' and write_address = '1' and lcd_ready= '1' then + future <= waiting ; + end if; + + + end case; + end process; +end architecture; + \ No newline at end of file diff --git a/FPGA/vhdl/message.vhd b/FPGA/vhdl/message.vhd new file mode 100644 index 0000000..09988e4 --- /dev/null +++ b/FPGA/vhdl/message.vhd @@ -0,0 +1,67 @@ +------------------------------------------ +-- Message 32 characteres ASCII +-- ESIEE, JPO 2008 +-- Bienvenue +------------------------------------------ +-- Creation : A. Exertier, mars 2008 +-- Modification : A. Exertier, avril 2013 +------------------------------------------ + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity message is +port ( + adr : in std_logic_vector(4 downto 0); + do : out std_logic_vector(7 downto 0) + ); +end entity; + +architecture RTL of message is + type contenu is array (0 to 31) of std_logic_vector(7 downto 0); + constant mes : contenu := ( + -- 1ere ligne (de 15 caracteres) + -- Mettre le code ASCII (en hexadecimal) de chaque caractère + -- exemple T => 54 (en hexadecimal) + -- 0=> X"54", indique que le 1er caractere (n°0) est un T + -- Modifier les valeurs ASCII ci-dessous + 0 => X"54", -- T + 1 => X"68", -- h + 2 => X"65", -- e + 3 => X"20", -- + 4 => X"44", -- D + 5 => X"72", -- r + 6 => X"65", -- e + 7 => X"61", -- a + 8 => X"6D", -- m + 9 => X"20", -- + 10 => X"54", -- T + 11 => X"65", -- e + 12 => X"61", -- a + 13 => X"6D", -- m + 14 => X"20", -- + 15 => X"3A", -- : + -- 2eme ligne (de 15 caracteres) + 16 => X"43", -- C + 17 => X"6F", -- o + 18 => X"72", -- r + 19 => X"69", -- i + 20 => X"6E", -- n + 21 => X"6E", -- n + 22 => X"65", -- e + 23 => X"20", -- + 24 => X"65", -- e + 25 => X"74", -- t + 26 => X"20", -- + 27 => X"41", -- A + 28 => X"6E", -- n + 29 => X"6E", -- n + 30 => X"65", -- e + 31 => X"21" -- ! + -- ne plus rien modifier en dessous de cette ligne + ); +begin + do <= mes(to_integer(unsigned(adr))); +end architecture; \ No newline at end of file diff --git a/FPGA/vhdl/rom_sinus.vhd b/FPGA/vhdl/rom_sinus.vhd new file mode 100644 index 0000000..7b3ce2c --- /dev/null +++ b/FPGA/vhdl/rom_sinus.vhd @@ -0,0 +1,75 @@ +---------------------------------------------------- +-- QUART de SINUS : SYNCHRONOUS ROM +---------------------------------------------------- +-- ESIEE +-- creation : A. Exertier, 06/2009 +-- modification : A. Exertier, 12/2011 +---------------------------------------------------- + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.math_real.all; + +----------------------------------------------------- +-- GENERIC PARAMETER +----------------------------------------------------- +-- N_data : output data number of bits +-- N_adr_ROM : address number of bits +-- amplitude : sinus amplitude +-- should be < 2**N_data +----------------------------------------------------- +-- INPUTS +----------------------------------------------------- +-- clk : clock +-- address : ROM address +----------------------------------------------------- +-- OUTPUT +----------------------------------------------------- +-- data : output data +----------------------------------------------------- + +entity rom_sinus is + generic ( + N_data : natural := 14; + N_adr_ROM : natural := 8; + amplitude : natural := 1024 + ); + port ( + clk : in std_logic; + address : in std_logic_vector(N_adr_ROM-1 downto 0); + data : out std_logic_vector(N_data-2 downto 0)); + +end entity rom_sinus; + +architecture RTL of rom_sinus is + subtype DAC_data_type is std_logic_vector (N_data-2 downto 0); + type memory_type is array (0 to 2**N_adr_ROM-1) of DAC_data_type; + + function sinus_tabule return memory_type is + variable temp : memory_type; + variable sinus_real : real; + begin + for i in 0 to 2**N_adr_ROM-1 loop + sinus_real := real(amplitude)*(sin(math_pi_over_2 * real(i)/real(2**N_adr_ROM))); + if integer(sinus_real)= 2**(N_data-1) then + temp(i) := (others => '1'); + else + temp(i) := std_logic_vector(to_unsigned(integer(sinus_real), N_data-1)); + end if; + end loop; + return temp; + end sinus_tabule; + + constant memory_values : memory_type := sinus_tabule; + +begin + + process(clk) is + begin + if rising_edge(clk) then data<= memory_values(to_integer(unsigned(address))); + end if; + end process; + +end RTL; diff --git a/FPGA/vhdl/seven_segment_decoder.vhd b/FPGA/vhdl/seven_segment_decoder.vhd new file mode 100644 index 0000000..8852319 --- /dev/null +++ b/FPGA/vhdl/seven_segment_decoder.vhd @@ -0,0 +1,72 @@ +------------------------------------------- +-- decodeur 7 segments +------------------------------------------- +-- ESIEE +-- Creation : A. Exertier, novembre 2004 +-- Modification : A. Exertier, decembre 2011 +------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +--------------------------------------------------- +-- Parametre generique +--------------------------------------------------- +-- active_low : true => segment allume par 0 +-- false => segment allume par 1 +--------------------------------------------------- +-- Entrees/sorties +--------------------------------------------------- +-- hexa : entree code hexadacimal (4 bits) +-- abcdefg : sortie 7 segments +-- a : segment horizontal superieur +-- a est le MSB de abcdefg +-- b : segment vertical superieur droit +-- c : segment vertical inferieur droit +-- d : segment horizontal inferieur +-- e : segment vertical indefieur gauche +-- f : segment vertical superieur gauche +-- g : segment horizontal milieu +--------------------------------------------------- + +entity seven_segment_decoder is + generic (active_low : boolean := true); + port (hexa : in std_logic_vector(3 downto 0); + hex : out std_logic_vector(6 downto 0)); +end ; + + +architecture RTL of seven_segment_decoder is + signal segments : std_logic_vector(hex'range); + signal abcdefg : std_logic_vector(hex'range); +begin + abcdefg <= segments when active_low else not segments; + process(abcdefg) is + begin + for i in hex'range loop + hex(i) <= abcdefg(hex'length-1-i); + end loop; + end process; + + process(hexa) + begin + case hexa is + when "0000" => segments <= "0000001"; -- 0 + when "0001" => segments <= "1001111"; -- 1 + when "0010" => segments <= "0010010"; -- 2 + when "0011" => segments <= "0000110"; -- 3 + when "0100" => segments <= "1001100"; -- 4 + when "0101" => segments <= "0100100"; -- 5 + when "0110" => segments <= "0100000"; -- 6 + when "0111" => segments <= "0001111"; -- 7 + when "1000" => segments <= "0000000"; -- 8 + when "1001" => segments <= "0000100"; -- 9 + when "1010" => segments <= "0001000"; -- A + when "1011" => segments <= "1100000"; -- B + when "1100" => segments <= "0110001"; -- C + when "1101" => segments <= "1000010"; -- D + when "1110" => segments <= "0110000"; -- E + when "1111" => segments <= "0111000"; -- F + when others => segments <= "1111111"; + end case; + end process; +end ; -- cgit v1.2.3