diff --git a/programs/segments_test.prog b/programs/segments_test.prog index 02dbd1f..aa6994d 100644 --- a/programs/segments_test.prog +++ b/programs/segments_test.prog @@ -20,7 +20,7 @@ number_array3: segment_addr0: .word 0x000F00A0 segment_addr1: .word 0x000F00A4 -// w_cnt_top: .word 0x1FC000 +// w_cnt_top: .word 0xFFC000 w_cnt_top: .word 0x100 //for simulation only diff --git a/soc/lib/config.vhd b/soc/lib/config.vhd index 2abe033..5ee83df 100644 --- a/soc/lib/config.vhd +++ b/soc/lib/config.vhd @@ -51,7 +51,7 @@ package config is constant CFG_MADR_LED : generic_mask_type := 16#3FFFFF#; -- size=1 byte constant CFG_MADR_SW : generic_mask_type := 16#3FFFFF# - (4 - 1); -- size=4 byte constant CFG_MADR_TIMER : generic_mask_type := 16#3FFFFF# - (8 - 1); -- size=8 byte (2 words) - constant CFG_MADR_SEG : generic_mask_type := 16#3FFFFF# - (8 - 1); -- size=8 byte (2 words) + constant CFG_MADR_SEG : generic_mask_type := 16#3FFFFF# - (4 - 1); -- size=4 byte end package config; diff --git a/soc/peripheral/hex2physical.vhd b/soc/peripheral/hex2physical.vhd index 6c622a1..b61a2fc 100644 --- a/soc/peripheral/hex2physical.vhd +++ b/soc/peripheral/hex2physical.vhd @@ -19,22 +19,22 @@ begin process(hex) begin case hex is - when "00000" => cathodes <= "10000001"; -- "0" - when "00001" => cathodes <= "11110011"; -- "1" - when "00010" => cathodes <= "01001001"; -- "2" - when "00011" => cathodes <= "01100001"; -- "3" - when "00100" => cathodes <= "00110011"; -- "4" - when "00101" => cathodes <= "00100101"; -- "5" - when "00110" => cathodes <= "00000101"; -- "6" - when "00111" => cathodes <= "11110001"; -- "7" - when "01000" => cathodes <= "00000001"; -- "8" - when "01001" => cathodes <= "00100001"; -- "9" - when "01010" => cathodes <= "00010001"; -- "A" - when "01011" => cathodes <= "00000111"; -- "B" - when "01100" => cathodes <= "10001101"; -- "C" - when "01101" => cathodes <= "01000011"; -- "D" - when "01110" => cathodes <= "00001101"; -- "E" - when "01111" => cathodes <= "00011101"; -- "F" + when "10000" => cathodes <= "10000001"; -- "0" + when "10001" => cathodes <= "11110011"; -- "1" + when "10010" => cathodes <= "01001001"; -- "2" + when "10011" => cathodes <= "01100001"; -- "3" + when "10100" => cathodes <= "00110011"; -- "4" + when "10101" => cathodes <= "00100101"; -- "5" + when "10110" => cathodes <= "00000101"; -- "6" + when "10111" => cathodes <= "11110001"; -- "7" + when "11000" => cathodes <= "00000001"; -- "8" + when "11001" => cathodes <= "00100001"; -- "9" + when "11010" => cathodes <= "00010001"; -- "A" + when "11011" => cathodes <= "00000111"; -- "B" + when "11100" => cathodes <= "10001101"; -- "C" + when "11101" => cathodes <= "01000011"; -- "D" + when "11110" => cathodes <= "00001101"; -- "E" + when "11111" => cathodes <= "00011101"; -- "F" when others => cathodes <= "11111111"; -- "Off" end case; end process; diff --git a/soc/peripheral/peripherals.vhd b/soc/peripheral/peripherals.vhd index e5cd15d..390f41b 100644 --- a/soc/peripheral/peripherals.vhd +++ b/soc/peripheral/peripherals.vhd @@ -73,6 +73,22 @@ package lt16soc_peripherals is ); end component; + component wb_segment_adv is + generic( + memaddr : generic_addr_type; --:= CFG_BADR_SEG; + addrmask : generic_mask_type --:= CFG_BADR_SEG; + ); + port( + clk : in std_logic; + rst : in std_logic; + wslvi : in wb_slv_in_type; + wslvo : out wb_slv_out_type; + + anodes : out std_logic_vector(7 downto 0); + cathodes : out std_logic_vector(7 downto 0) + ); + end component; + end lt16soc_peripherals; package body lt16soc_peripherals is diff --git a/soc/peripheral/seven_segment_display_adv.vhd b/soc/peripheral/seven_segment_display_adv.vhd new file mode 100644 index 0000000..9b21f5d --- /dev/null +++ b/soc/peripheral/seven_segment_display_adv.vhd @@ -0,0 +1,178 @@ +-- See the file "LICENSE" for the full license governing this code. -- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use work.lt16x32_global.all; +use work.wishbone.all; +use work.config.all; + +entity wb_segment_adv is + generic( + memaddr : generic_addr_type; --:= CFG_BADR_SEG; + addrmask : generic_mask_type --:= CFG_MADR_SEG; + ); + port( + clk : in std_logic; + rst : in std_logic; + wslvi : in wb_slv_in_type; + wslvo : out wb_slv_out_type; + + anodes : out std_logic_vector(7 downto 0); + cathodes : out std_logic_vector(7 downto 0) + ); +end wb_segment_adv; + +architecture Behavioral of wb_segment_adv is + + signal ack : std_logic; + + signal hex_register : std_logic_vector(63 downto 0); + signal data_out : std_logic_vector(63 downto 0); + signal data_in : std_logic_vector(31 downto 0); + signal data_in_changed : std_logic; + + signal hex : std_logic_vector(4 downto 0); + + signal timer_overflow : std_logic; + signal overflow_counter : integer range 0 to 7; + + component hex2physical + port( + hex : in std_logic_vector(4 downto 0); + cathodes : out std_logic_vector(7 downto 0) + ); + end component; + + component simple_timer + generic( + timer_start : std_logic_vector (31 downto 0) + ); + port( + clk : in std_logic; + rst : in std_logic; + timer_overflow : out std_logic + ); + end component; + +begin + + converter : hex2physical + port map( + hex => hex, + cathodes => cathodes + ); + + timer: simple_timer + generic map (timer_start => x"00000008") + port map( + clk => clk, + rst => rst, + timer_overflow => timer_overflow + ); + + process(clk) + begin + if clk'event and clk='1' then + if rst = '1' then + ack <= '0'; + data_out <= (others=>'0'); + data_in <= (others=>'0'); + data_in_changed <= '0'; + else + data_out <= (others=>'0'); + data_in <= (others=>'0'); + data_in_changed <= '0'; + + if wslvi.stb = '1' and wslvi.cyc = '1' then + if wslvi.we='0' then + data_out <= hex_register; + else + -- Write enable + data_in <= dec_wb_dat(wslvi.sel,wslvi.dat); + data_in_changed <= '1'; + end if; + + if ack = '0' then + ack <= '1'; + else + ack <= '0'; + end if; + else + ack <= '0'; + end if; + end if; + end if; + end process; + + process(clk) + variable v_data : std_logic_vector(3 downto 0); + variable v_off : std_logic; + variable v_write : std_logic; + variable v_clear : std_logic; + variable v_shift : std_logic; + begin + if clk'event and clk='1' then + if rst = '1' then + hex_register <= (others=>'0'); + else + if data_in_changed = '1' and ack = '1' then -- only check if ack was just raised + v_data := data_in(3 downto 0); + v_off := data_in(4); + v_write := data_in(8); + v_clear := data_in(16); + v_shift := data_in(24); + + -- No special care has to be taken to support + -- writing and shifting at the same time. + + if v_shift = '1' then + hex_register(63 downto 56) <= (others => '0'); + hex_register(55 downto 0) <= hex_register(63 downto 8); + end if; + + if v_write = '1' then + hex_register(59 downto 56) <= v_data; + hex_register(60) <= not v_off; -- unclear if this should only be set when write is 1 + end if; + + if v_clear = '1' then + hex_register <= (others => '0'); + end if; + end if; + end if; + end if; + end process; + + process(clk) + begin + if clk'event and clk='1' then + if rst = '1' then + hex <= hex_register(4 downto 0); + anodes <= (others => '0'); + overflow_counter <= 0; + else + if timer_overflow = '1' then + if overflow_counter = 7 then + overflow_counter <= 0; + else + overflow_counter <= overflow_counter + 1; + end if; + + anodes <= (others => '0'); + anodes(overflow_counter) <= '1'; + + hex <= hex_register(overflow_counter * 8 + 4 downto overflow_counter * 8); + end if; + end if; + end if; + end process; + + wslvo.dat <= + data_out(31 downto 0) when wslvi.adr(2) = '0' else + data_out(63 downto 32) when wslvi.adr(2) = '1'; + + wslvo.ack <= ack; + wslvo.wbcfg <= wb_membar(memaddr, addrmask); + +end Behavioral; diff --git a/soc/testbench/segment_adv_tb.vhd b/soc/testbench/segment_adv_tb.vhd new file mode 100644 index 0000000..75491d7 --- /dev/null +++ b/soc/testbench/segment_adv_tb.vhd @@ -0,0 +1,125 @@ +-- See the file "LICENSE" for the full license governing this code. -- +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE ieee.numeric_std.ALL; + +LIBRARY work; +USE work.lt16soc_peripherals.ALL; +USE work.wishbone.ALL; +USE work.wb_tp.ALL; +USE work.config.ALL; + +ENTITY segment_adv_tb IS +END ENTITY; + +ARCHITECTURE sim OF segment_adv_tb IS + + constant CLK_PERIOD : time := 10 ns; + + signal clk : std_logic := '0'; + signal rst : std_logic; + signal data : std_logic_vector(31 downto 0); + + signal anodes : std_logic_vector(7 downto 0); + signal cathodes : std_logic_vector(7 downto 0); + + signal slvi : wb_slv_in_type; + signal slvo : wb_slv_out_type; + +BEGIN + + SIM_SLV: wb_segment_adv + generic map( + memaddr => CFG_BADR_SEG, + addrmask => CFG_MADR_SEG + ) + port map( + clk => clk, + rst => rst, + wslvi => slvi, + wslvo => slvo, + + anodes => anodes, + cathodes => cathodes + ); + + clk_gen: process + begin + clk <= not clk; + wait for CLK_PERIOD/2; + end process clk_gen; + + stimuli: process + begin + rst <= '1'; + wait for CLK_PERIOD; + rst <= '0'; + + data <= (others => '0'); + data(24) <= '0'; -- shift + data(16) <= '0'; -- clear + data(8) <= '1'; -- write + data(4) <= '0'; -- off + data(3 downto 0) <= x"F"; -- data + generate_sync_wb_single_write(slvi,slvo,clk,data); + + wait for 1 us; + data <= (others => '0'); + data(24) <= '1'; -- shift + data(16) <= '0'; -- clear + data(8) <= '0'; -- write + data(4) <= '0'; -- off + data(3 downto 0) <= x"0"; -- data + generate_sync_wb_single_write(slvi,slvo,clk,data); + + wait for 1 us; + data <= (others => '0'); + data(24) <= '1'; -- shift + data(16) <= '0'; -- clear + data(8) <= '1'; -- write + data(4) <= '0'; -- off + data(3 downto 0) <= x"A"; -- data + generate_sync_wb_single_write(slvi,slvo,clk,data); + + wait for 1 us; + data <= (others => '0'); + data(24) <= '1'; -- shift + data(16) <= '0'; -- clear + data(8) <= '1'; -- write + data(4) <= '0'; -- off + data(3 downto 0) <= x"B"; -- data + generate_sync_wb_single_write(slvi,slvo,clk,data); + + wait for 1 us; + data <= (others => '0'); + data(24) <= '1'; -- shift + data(16) <= '0'; -- clear + data(8) <= '1'; -- write + data(4) <= '0'; -- off + data(3 downto 0) <= x"C"; -- data + generate_sync_wb_single_write(slvi,slvo,clk,data); + + wait for 1 us; + data <= (others => '0'); + data(24) <= '1'; -- shift + data(16) <= '0'; -- clear + data(8) <= '1'; -- write + data(4) <= '1'; -- off + data(3 downto 0) <= x"0"; -- data + generate_sync_wb_single_write(slvi,slvo,clk,data); + + wait for 1 us; + data <= (others => '0'); + data(24) <= '0'; -- shift + data(16) <= '1'; -- clear + data(8) <= '0'; -- write + data(4) <= '0'; -- off + data(3 downto 0) <= x"0"; -- data + generate_sync_wb_single_write(slvi,slvo,clk,data); + + wait for 1 us; + + assert false report "Simulation terminated!" severity failure; + end process stimuli; + +END ARCHITECTURE; diff --git a/soc/top/top.vhd b/soc/top/top.vhd index 46736d8..e0667cb 100644 --- a/soc/top/top.vhd +++ b/soc/top/top.vhd @@ -204,7 +204,7 @@ begin clk,rst_gen,slvi(CFG_TIMER),slvo(CFG_TIMER), irq_lines(3) ); - segmentdev : wb_segment + segmentdev : wb_segment_adv generic map( memaddr => CFG_BADR_SEG, addrmask => CFG_MADR_SEG diff --git a/soc/top/top.xdc b/soc/top/top.xdc index 5db47d8..4f4e3fc 100644 --- a/soc/top/top.xdc +++ b/soc/top/top.xdc @@ -53,22 +53,22 @@ set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { led[7] #set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports { LED17_R }]; #IO_L11N_T1_SRCC_14 Sch=led17_r ##7 segment display -#set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { CA }]; #IO_L24N_T3_A00_D16_14 Sch=ca -#set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { CB }]; #IO_25_14 Sch=cb -#set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { CC }]; #IO_25_15 Sch=cc -#set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { CD }]; #IO_L17P_T2_A26_15 Sch=cd -#set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { CE }]; #IO_L13P_T2_MRCC_14 Sch=ce -#set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { CF }]; #IO_L19P_T3_A10_D26_14 Sch=cf -#set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { CG }]; #IO_L4P_T0_D04_14 Sch=cg -#set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { DP }]; #IO_L19N_T3_A21_VREF_15 Sch=dp -#set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { AN[0] }]; #IO_L23P_T3_FOE_B_15 Sch=an[0] -#set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { AN[1] }]; #IO_L23N_T3_FWE_B_15 Sch=an[1] -#set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { AN[2] }]; #IO_L24P_T3_A01_D17_14 Sch=an[2] -#set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { AN[3] }]; #IO_L19P_T3_A22_15 Sch=an[3] -#set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { AN[4] }]; #IO_L8N_T1_D12_14 Sch=an[4] -#set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { AN[5] }]; #IO_L14P_T2_SRCC_14 Sch=an[5] -#set_property -dict { PACKAGE_PIN K2 IOSTANDARD LVCMOS33 } [get_ports { AN[6] }]; #IO_L23P_T3_35 Sch=an[6] -#set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { AN[7] }]; #IO_L23N_T3_A02_D18_14 Sch=an[7] +set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { cathodes[0] }]; #IO_L24N_T3_A00_D16_14 Sch=ca +set_property -dict { PACKAGE_PIN R10 IOSTANDARD LVCMOS33 } [get_ports { cathodes[1] }]; #IO_25_14 Sch=cb +set_property -dict { PACKAGE_PIN K16 IOSTANDARD LVCMOS33 } [get_ports { cathodes[2] }]; #IO_25_15 Sch=cc +set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { cathodes[3] }]; #IO_L17P_T2_A26_15 Sch=cd +set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { cathodes[4] }]; #IO_L13P_T2_MRCC_14 Sch=ce +set_property -dict { PACKAGE_PIN T11 IOSTANDARD LVCMOS33 } [get_ports { cathodes[5] }]; #IO_L19P_T3_A10_D26_14 Sch=cf +set_property -dict { PACKAGE_PIN L18 IOSTANDARD LVCMOS33 } [get_ports { cathodes[6] }]; #IO_L4P_T0_D04_14 Sch=cg +set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { cathodes[7] }]; #IO_L19N_T3_A21_VREF_15 Sch=dp +set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { anodes[0] }]; #IO_L23P_T3_FOE_B_15 Sch=an[0] +set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { anodes[1] }]; #IO_L23N_T3_FWE_B_15 Sch=an[1] +set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { anodes[2] }]; #IO_L24P_T3_A01_D17_14 Sch=an[2] +set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { anodes[3] }]; #IO_L19P_T3_A22_15 Sch=an[3] +set_property -dict { PACKAGE_PIN P14 IOSTANDARD LVCMOS33 } [get_ports { anodes[4] }]; #IO_L8N_T1_D12_14 Sch=an[4] +set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { anodes[5] }]; #IO_L14P_T2_SRCC_14 Sch=an[5] +set_property -dict { PACKAGE_PIN K2 IOSTANDARD LVCMOS33 } [get_ports { anodes[6] }]; #IO_L23P_T3_35 Sch=an[6] +set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { anodes[7] }]; #IO_L23N_T3_A02_D18_14 Sch=an[7] ##Buttons set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { rst }]; #IO_L3P_T0_DQS_AD1P_15 Sch=cpu_resetn