---------------------------------------------------------------- -- Chapter 15 Case Study: System Design Using the Gumnut Core ---------------------------------------------------------------- ---------------------------------------------------------------- -- 15.1 Overview of the Gumnut ---------------------------------------------------------------- ---------------------------------------------------------------- -- 15.1.1 Instruction Set Architecture ---------------------------------------------------------------- ---------------------------------------------------------------- -- 15.1.2 External Interface ---------------------------------------------------------------- ---------------------------------------------------------------- -- The Gumnut Entity Declaration ---------------------------------------------------------------- -- Page 420 library ieee; use ieee.std_logic_1164.all, ieee.numeric_std.all; entity gumnut is generic ( debug : boolean := false ); port ( clk_i : in std_ulogic; rst_i : in std_ulogic; -- Instruction memory bus inst_cyc_o : out std_ulogic; inst_stb_o : out std_ulogic; inst_ack_i : in std_ulogic; inst_adr_o : out unsigned(11 downto 0); inst_dat_i : in std_ulogic_vector(17 downto 0); -- Data memory bus data_cyc_o : out std_ulogic; data_stb_o : out std_ulogic; data_we_o : out std_ulogic; data_ack_i : in std_ulogic; data_adr_o : out unsigned(7 downto 0); data_dat_o : out std_ulogic_vector(7 downto 0); data_dat_i : in std_ulogic_vector(7 downto 0); -- I/O port bus port_cyc_o : out std_ulogic; port_stb_o : out std_ulogic; port_we_o : out std_ulogic; port_ack_i : in std_ulogic; port_adr_o : out unsigned(7 downto 0); port_dat_o : out std_ulogic_vector(7 downto 0); port_dat_i : in std_ulogic_vector(7 downto 0); -- Interrupts int_req : in std_ulogic; int_ack : out std_ulogic ); end entity gumnut; ---------------------------------------------------------------- -- Instruction and Data Memories ---------------------------------------------------------------- -- Page 421 library ieee; use ieee.std_logic_1164.all, ieee.numeric_std.all; entity inst_mem is generic ( IMem_file_name : string := "gasm_text.dat" ); port ( clk_i : in std_ulogic; cyc_i : in std_ulogic; stb_i : in std_ulogic; ack_o : out std_ulogic; adr_i : in unsigned(11 downto 0); dat_o : out std_ulogic_vector(17 downto 0) ); end entity inst_mem; library ieee; use ieee.std_logic_1164.all, ieee.numeric_std.all; entity data_mem is generic ( DMem_file_name : string := "gasm_data.dat" ); port ( clk_i : in std_ulogic; cyc_i : in std_ulogic; stb_i : in std_ulogic; we_i : in std_ulogic; ack_o : out std_ulogic; adr_i : in unsigned(7 downto 0); dat_i : in std_ulogic_vector(7 downto 0); dat_o : out std_ulogic_vector(7 downto 0) ); end entity data_mem; -- Page 422 library ieee; use ieee.std_logic_1164.all, ieee.numeric_std.all; entity gumnut_with_mem is generic ( IMem_file_name : string := "gasm_text.dat"; DMem_file_name : string := "gasm_data.dat"; debug : boolean := false ); port ( clk_i : in std_ulogic; rst_i : in std_ulogic; -- I/O port bus port_cyc_o : out std_ulogic; port_stb_o : out std_ulogic; port_we_o : out std_ulogic; port_ack_i : in std_ulogic; port_adr_o : out unsigned(7 downto 0); port_dat_o : out std_ulogic_vector(7 downto 0); port_dat_i : in std_ulogic_vector(7 downto 0); -- Interrupts int_req : in std_ulogic; int_ack : out std_ulogic ); end entity gumnut_with_mem; -- Page 422 - 425 library ieee; use ieee.std_logic_1164.all, ieee.numeric_std.all; architecture struct of gumnut_with_mem is -- Instruction memory bus signal inst_cyc_o : std_ulogic; signal inst_stb_o : std_ulogic; signal inst_ack_i : std_ulogic; signal inst_adr_o : unsigned(11 downto 0); signal inst_dat_i : std_ulogic_vector(17 downto 0); -- Data memory bus signal data_cyc_o : std_ulogic; signal data_stb_o : std_ulogic; signal data_we_o : std_ulogic; signal data_ack_i : std_ulogic; signal data_adr_o : unsigned(7 downto 0); signal data_dat_o : std_ulogic_vector(7 downto 0); signal data_dat_i : std_ulogic_vector(7 downto 0); component gumnut is generic ( debug : boolean ); port ( clk_i : in std_ulogic; rst_i : in std_ulogic; -- Instruction memory bus inst_cyc_o : out std_ulogic; inst_stb_o : out std_ulogic; inst_ack_i : in std_ulogic; inst_adr_o : out unsigned(11 downto 0); inst_dat_i : in std_ulogic_vector(17 downto 0); -- Data memory bus data_cyc_o : out std_ulogic; data_stb_o : out std_ulogic; data_we_o : out std_ulogic; data_ack_i : in std_ulogic; data_adr_o : out unsigned(7 downto 0); data_dat_o : out std_ulogic_vector(7 downto 0); data_dat_i : in std_ulogic_vector(7 downto 0); -- I/O port bus port_cyc_o : out std_ulogic; port_stb_o : out std_ulogic; port_we_o : out std_ulogic; port_ack_i : in std_ulogic; port_adr_o : out unsigned(7 downto 0); port_dat_o : out std_ulogic_vector(7 downto 0); port_dat_i : in std_ulogic_vector(7 downto 0); -- Interrupts int_req : in std_ulogic; int_ack : out std_ulogic ); end component gumnut; component inst_mem is generic ( IMem_file_name : string ); port ( clk_i : in std_ulogic; cyc_i : in std_ulogic; stb_i : in std_ulogic; ack_o : out std_ulogic; adr_i : in unsigned(11 downto 0); dat_o : out std_ulogic_vector(17 downto 0) ); end component inst_mem; component data_mem is generic ( DMem_file_name : string ); port ( clk_i : in std_ulogic; cyc_i : in std_ulogic; stb_i : in std_ulogic; we_i : in std_ulogic; ack_o : out std_ulogic; adr_i : in unsigned(7 downto 0); dat_i : in std_ulogic_vector(7 downto 0); dat_o : out std_ulogic_vector(7 downto 0) ); end component data_mem; begin core : component gumnut generic map ( debug => debug ) port map ( clk_i => clk_i, rst_i => rst_i, inst_cyc_o => inst_cyc_o, inst_stb_o => inst_stb_o, inst_ack_i => inst_ack_i, inst_adr_o => inst_adr_o, inst_dat_i => inst_dat_i, data_cyc_o => data_cyc_o, data_stb_o => data_stb_o, data_we_o => data_we_o, data_ack_i => data_ack_i, data_adr_o => data_adr_o, data_dat_o => data_dat_o, data_dat_i => data_dat_i, port_cyc_o => port_cyc_o, port_stb_o => port_stb_o, port_we_o => port_we_o, port_ack_i => port_ack_i, port_adr_o => port_adr_o, port_dat_o => port_dat_o, port_dat_i => port_dat_i, int_req => int_req, int_ack => int_ack ); core_inst_mem : component inst_mem generic map ( IMem_file_name => IMem_file_name ) port map ( clk_i => clk_i, cyc_i => inst_cyc_o, stb_i => inst_stb_o, ack_o => inst_ack_i, adr_i => inst_adr_o, dat_o => inst_dat_i ); core_data_mem : component data_mem generic map ( DMem_file_name => DMem_file_name ) port map ( clk_i => clk_i, cyc_i => data_cyc_o, stb_i => data_stb_o, we_i => data_we_o, ack_o => data_ack_i, adr_i => data_adr_o, dat_i => data_dat_o, dat_o => data_dat_i ); end architecture struct; ---------------------------------------------------------------- -- 15.2 A Digital Alarm Clock ---------------------------------------------------------------- ---------------------------------------------------------------- -- 15.2.1 System Design ---------------------------------------------------------------- -- Page 427 library ieee; use ieee.std_logic_1164.all; entity alarm_clock is generic ( debug : boolean := false ); port ( clk : in std_ulogic; pb : in std_ulogic_vector(3 downto 0); sw : in std_ulogic_vector(7 downto 0); led : out std_ulogic_vector(7 downto 0); digit : out std_ulogic_vector(3 downto 0); seg : out std_ulogic_vector(7 downto 0) ); end entity alarm_clock ; -- Pages 427 - 430 library ieee; use ieee.numeric_std.all; architecture synth of alarm_clock is component gumnut_with_mem is generic ( debug : boolean := false ); port ( clk_i : in std_ulogic; rst_i : in std_ulogic; port_cyc_o : out std_ulogic; port_stb_o : out std_ulogic; port_we_o : out std_ulogic; port_ack_i : in std_ulogic; port_adr_o : out unsigned(7 downto 0); port_dat_o : out std_ulogic_vector(7 downto 0); port_dat_i : in std_ulogic_vector(7 downto 0); int_req : in std_ulogic; int_ack : out std_ulogic ); end component gumnut_with_mem; signal reset : std_ulogic; signal port_cyc_o : std_ulogic; signal port_stb_o : std_ulogic; signal port_we_o : std_ulogic; signal port_ack_i : std_ulogic; signal port_adr_o : unsigned(7 downto 0); signal port_dat_o : std_ulogic_vector(7 downto 0); signal port_dat_i : std_ulogic_vector(7 downto 0); signal int_req : std_ulogic; signal int_ack : std_ulogic; signal pb_synch : std_ulogic_vector(pb'range); signal sw_synch : std_ulogic_vector(sw'range); signal clk_1MHz : std_ulogic; begin -- reset generation reset_gen : reset <= '0'; -- processor core core : gumnut_with_mem generic map ( debug => debug ) port map ( clk_i => clk, rst_i => reset, port_cyc_o => port_cyc_o, port_stb_o => port_stb_o, port_we_o => port_we_o, port_ack_i => port_ack_i, port_adr_o => port_adr_o, port_dat_o => port_dat_o, port_dat_i => port_dat_i, int_req => int_req, int_ack => int_ack ); port_ack_i <= '1'; -- input port: -- push buttons 1 and 0 when port_addr = "-------0" -- switches when port_addr = "-------1" synch : process ( clk ) variable pb_tmp : std_ulogic_vector(pb'range); variable sw_tmp : std_ulogic_vector(sw'range); begin if rising_edge(clk) then pb_synch <= pb_tmp; sw_synch <= sw_tmp; pb_tmp := pb; sw_tmp := sw; end if; end process synch; with port_adr_o(0) select port_dat_i <= "0000" & pb_synch when '0', sw_synch when '1', "XXXXXXXX" when others; -- digit output port register (port_addr = "-------1") digit_reg : process (clk) begin if rising_edge(clk) then if reset = '1' then digit <= "1111"; elsif port_cyc_o = '1' and port_stb_o = '1' and port_we_o = '1' and port_adr_o(0) = '1' then digit <= not port_dat_o(3 downto 0); end if; end if; end process digit_reg; -- segment output port register (port_addr = "------1-") seg_reg : process (clk) begin if rising_edge(clk) then if reset = '1' then seg <= "11111111"; elsif port_cyc_o = '1' and port_stb_o = '1' and port_we_o = '1' and port_adr_o(1) = '1' then seg <= not port_dat_o; end if; end if; end process seg_reg; -- led output port register (port_addr = "-----1--") led_reg : process (clk, reset) begin if rising_edge(clk) then if reset = '1' then led <= "00000000"; elsif port_cyc_o = '1' and port_stb_o = '1' and port_we_o = '1' and port_adr_o(2) = '1' then led <= port_dat_o; end if; end if; end process led_reg; -- divide 50MHz clock down to 1MHz div_50 : process (clk) variable count : integer range 0 to 49; begin if rising_edge(clk) then if reset = '1' then clk_1MHz <= '0'; count := 49; elsif count = 0 then count := 49; clk_1Mhz <= '1'; else count := count - 1; clk_1Mhz <= '0'; end if; end if; end process div_50; -- timer (port_addr = "----1---") timer : process (clk) variable divisor, count : unsigned(7 downto 0); begin if rising_edge(clk) then if reset = '1' then divisor := X"00"; count := X"00"; int_req <= '0'; elsif port_cyc_o = '1' and port_stb_o = '1' and port_we_o = '1' and port_adr_o(3) = '1' then divisor := unsigned(port_dat_o); count := divisor; elsif clk_1MHz = '1' then if count = 0 then int_req <= '1'; count := divisor; else count := count - 1; end if; end if; if int_ack = '1' then int_req <= '0'; end if; end if; end process timer; end architecture synth; -- Pages 431 - 432 library ieee; use ieee.std_logic_1164.all; entity alarm_clock_top is generic ( debug : boolean := false ); port ( clk50in : in std_ulogic; pb_in : in std_ulogic_vector(3 downto 0); sw_in : in std_ulogic_vector(7 downto 0); led_out : out std_ulogic_vector(7 downto 0); digit_out : out std_ulogic_vector(3 downto 0); seg_out : out std_ulogic_vector(7 downto 0) ); end entity alarm_clock_top ; ---------------------------------------------------------------- library unisim; use unisim.vcomponents.all ; architecture struct of alarm_clock_top is signal clkint : std_ulogic; signal clk : std_ulogic; signal pb : std_ulogic_vector(pb_in'range); signal sw : std_ulogic_vector(sw_in'range); signal led : std_ulogic_vector(led_out'range); signal digit : std_ulogic_vector(digit_out'range); signal seg : std_ulogic_vector(seg_out'range); component alarm_clock is generic ( debug : boolean := false ); port ( clk : in std_ulogic; pb : in std_ulogic_vector(3 downto 0); sw : in std_ulogic_vector(7 downto 0); led : out std_ulogic_vector(7 downto 0); digit : out std_ulogic_vector(3 downto 0); seg : out std_ulogic_vector(7 downto 0) ); end component alarm_clock ; begin -- input/output and clock buffers clkin_ibuf : component ibufg_lvcmos33 port map ( i => clk50in, o => clkint ); clk_bufg : component bufg port map ( i => clkint, o => clk ) ; pb_buf_gen : for i in 0 to 3 generate pb_buf : component ibuf_lvcmos33 port map ( i => pb_in(i), o => pb(i) ); end generate pb_buf_gen; sw_buf_gen : for i in 0 to 7 generate sw_buf : component ibuf_lvcmos33 port map ( i => sw_in(i), o => sw(i) ); end generate sw_buf_gen; led_buf_gen : for i in 0 to 7 generate led_buf : component obuf_lvcmos33 port map ( i => led(i), o => led_out(i) ); end generate led_buf_gen; digit_buf_gen : for i in 0 to 3 generate digit_buf : component obuf_lvcmos33 port map ( i => digit(i), o => digit_out(i) ); end generate digit_buf_gen; seg_buf_gen : for i in 0 to 7 generate seg_buf : component obuf_lvcmos33 port map ( i => seg(i), o => seg_out(i) ); end generate seg_buf_gen; -- the alarm clock core alarm_clock_core : alarm_clock generic map ( debug => debug ) port map ( clk => clk, pb => pb, sw => sw, led => led, digit => digit, seg => seg ); end architecture struct; ---------------------------------------------------------------- -- 15.2.2 Synthesizing and Implementing the Alarm Clock ---------------------------------------------------------------- ---------------------------------------------------------------- -- Exercises ----------------------------------------------------------------