From 3ac1dbc737332ab5ea1e205ed55d8d62662e6b2d Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Tue, 10 Sep 2019 16:40:11 +0100 Subject: [PATCH] Share soc.vhdl between FPGA and sim Signed-off-by: Benjamin Herrenschmidt --- Makefile | 3 +- core_tb.vhdl | 101 +++++---------------------------- fpga/toplevel.vhdl | 3 +- microwatt.core | 18 +++--- sim_uart.vhdl | 68 ++++++++++++---------- simple_ram_behavioural.vhdl | 12 ++-- simple_ram_behavioural_tb.vhdl | 4 +- fpga/soc.vhdl => soc.vhdl | 81 ++++++++++++++++---------- 8 files changed, 126 insertions(+), 164 deletions(-) rename fpga/soc.vhdl => soc.vhdl (65%) diff --git a/Makefile b/Makefile index 506cb29..02d3416 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ all: $(all) $(GHDL) -a $(GHDLFLAGS) $< common.o: decode_types.o -core_tb.o: common.o wishbone_types.o core.o simple_ram_behavioural.o sim_uart.o +core_tb.o: common.o core.o soc.o core.o: common.o wishbone_types.o fetch1.o fetch2.o decode1.o decode2.o register_file.o cr_file.o execute1.o execute2.o loadstore1.o loadstore2.o multiply.o writeback.o wishbone_arbiter.o cr_file.o: common.o crhelpers.o: common.o @@ -41,6 +41,7 @@ simple_ram_behavioural.o: wishbone_types.o simple_ram_behavioural_helpers.o wishbone_arbiter.o: wishbone_types.o wishbone_types.o: writeback.o: common.o +soc.o: wishbone_types.o simple_ram_behavioural.o sim_uart.o fpga/soc_reset_tb.o: fpga/soc_reset.o diff --git a/core_tb.vhdl b/core_tb.vhdl index 501cbfb..cb11d08 100644 --- a/core_tb.vhdl +++ b/core_tb.vhdl @@ -13,88 +13,23 @@ end core_tb; architecture behave of core_tb is signal clk, rst: std_logic; - signal wishbone_dcore_in : wishbone_slave_out; - signal wishbone_dcore_out : wishbone_master_out; - - signal wishbone_icore_in : wishbone_slave_out; - signal wishbone_icore_out : wishbone_master_out; - - signal wishbone_core_in : wishbone_slave_out; - signal wishbone_core_out : wishbone_master_out; - - signal wishbone_ram_in : wishbone_slave_out; - signal wishbone_ram_out : wishbone_master_out; - - signal wishbone_uart_in : wishbone_slave_out; - signal wishbone_uart_out : wishbone_master_out; - - signal registers : regfile; - signal terminate : std_ulogic; - -- testbench signals constant clk_period : time := 10 ns; begin - core_0: entity work.core - generic map (SIM => true) - port map (clk => clk, rst => rst, - wishbone_insn_in => wishbone_icore_in, - wishbone_insn_out => wishbone_icore_out, - wishbone_data_in => wishbone_dcore_in, - wishbone_data_out => wishbone_dcore_out, - registers => registers, terminate_out => terminate); - - simple_ram_0: entity work.simple_ram_behavioural - generic map ( filename => "simple_ram_behavioural.bin", size => 524288) - port map (clk => clk, rst => rst, wishbone_in => wishbone_ram_out, wishbone_out => wishbone_ram_in); - - simple_uart_0: entity work.sim_uart - port map ( clk => clk, reset => rst, wishbone_in => wishbone_uart_out, wishbone_out => wishbone_uart_in); - - wishbone_arbiter_0: entity work.wishbone_arbiter - port map (clk => clk, rst => rst, - wb1_in => wishbone_dcore_out, wb1_out => wishbone_dcore_in, - wb2_in => wishbone_icore_out, wb2_out => wishbone_icore_in, - wb_out => wishbone_core_out, wb_in => wishbone_core_in); - - bus_process: process(wishbone_core_out, wishbone_ram_in, wishbone_uart_in) - -- Selected slave - type slave_type is (SLAVE_UART, SLAVE_MEMORY, SLAVE_NONE); - variable slave : slave_type; - begin - -- Simple address decoder - slave := SLAVE_NONE; - if wishbone_core_out.adr(31 downto 24) = x"00" then - slave := SLAVE_MEMORY; - elsif wishbone_core_out.adr(31 downto 24) = x"c0" then - if wishbone_core_out.adr(15 downto 12) = x"2" then - slave := SLAVE_UART; - end if; - end if; - - -- Wishbone muxing: - -- Start with all master signals to all slaves, then override - -- cyc and stb accordingly - wishbone_ram_out <= wishbone_core_out; - wishbone_uart_out <= wishbone_core_out; - if slave = SLAVE_MEMORY then - wishbone_core_in <= wishbone_ram_in; - else - wishbone_ram_out.cyc <= '0'; - wishbone_ram_out.stb <= '0'; - end if; - if slave = SLAVE_UART then - wishbone_core_in <= wishbone_uart_in; - else - wishbone_uart_out.cyc <= '0'; - wishbone_uart_out.stb <= '0'; - end if; - if slave = SLAVE_NONE then - wishbone_core_in.dat <= (others => '1'); - wishbone_core_in.ack <= wishbone_core_out.cyc and - wishbone_core_out.stb; - end if; - end process; + soc0: entity work.soc + generic map( + SIM => true, + MEMORY_SIZE => 524288, + RAM_INIT_FILE => "simple_ram_behavioural.bin", + RESET_LOW => false + ) + port map( + rst => rst, + system_clk => clk, + uart0_rxd => '0', + uart0_txd => open + ); clk_process: process begin @@ -111,14 +46,4 @@ begin rst <= '0'; wait; end process; - - dump_registers: process(all) - begin - if terminate = '1' then - loop_0: for i in 0 to 31 loop - report "REG " & to_hstring(registers(i)); - end loop loop_0; - assert false report "end of test" severity failure; - end if; - end process; end; diff --git a/fpga/toplevel.vhdl b/fpga/toplevel.vhdl index 6ad5c9b..489080b 100644 --- a/fpga/toplevel.vhdl +++ b/fpga/toplevel.vhdl @@ -55,7 +55,8 @@ begin generic map( MEMORY_SIZE => MEMORY_SIZE, RAM_INIT_FILE => RAM_INIT_FILE, - RESET_LOW => RESET_LOW + RESET_LOW => RESET_LOW, + SIM => false ) port map ( system_clk => system_clk, diff --git a/microwatt.core b/microwatt.core index f1bd8f0..58485a7 100644 --- a/microwatt.core +++ b/microwatt.core @@ -24,19 +24,23 @@ filesets: - loadstore2.vhdl - multiply.vhdl - writeback.vhdl - - wishbone_arbiter.vhdl - insn_helpers.vhdl - core.vhdl file_type : vhdlSource-2008 soc: + files: + - wishbone_arbiter.vhdl + - soc.vhdl + file_type : vhdlSource-2008 + + fpga: files: - fpga/pp_fifo.vhd - fpga/mw_soc_memory.vhdl - fpga/soc_reset.vhdl - fpga/pp_soc_uart.vhd - fpga/pp_utilities.vhd - - fpga/soc.vhdl - fpga/toplevel.vhdl - fpga/firmware.hex : {copyto : firmware.hex, file_type : user} file_type : vhdlSource-2008 @@ -64,7 +68,7 @@ filesets: targets: nexys_a7: default_tool: vivado - filesets: [core, nexys_a7, soc] + filesets: [core, nexys_a7, soc, fpga] parameters : [memory_size, ram_init_file] tools: vivado: {part : xc7a100tcsg324-1} @@ -72,7 +76,7 @@ targets: nexys_video: default_tool: vivado - filesets: [core, nexys_video, soc] + filesets: [core, nexys_video, soc, fpga] parameters : [memory_size, ram_init_file] tools: vivado: {part : xc7a200tsbg484-1} @@ -80,7 +84,7 @@ targets: arty_a7-35: default_tool: vivado - filesets: [core, arty_a7-35, soc] + filesets: [core, arty_a7-35, soc, fpga] parameters : [memory_size, ram_init_file] tools: vivado: {part : xc7a35ticsg324-1L} @@ -88,14 +92,14 @@ targets: cmod_a7-35: default_tool: vivado - filesets: [core, cmod_a7-35, soc] + filesets: [core, cmod_a7-35, soc, fpga] parameters : [memory_size, ram_init_file, reset_low=false] tools: vivado: {part : xc7a35tcpg236-1} toplevel : toplevel synth: - filesets: [core] + filesets: [core, soc] tools: vivado: {pnr : none} toplevel: core diff --git a/sim_uart.vhdl b/sim_uart.vhdl index c52a8bc..5881560 100644 --- a/sim_uart.vhdl +++ b/sim_uart.vhdl @@ -31,18 +31,30 @@ use work.sim_console.all; --! enable register. The following bits are available: --! - Bit 0: data received (receive buffer not empty) --! - Bit 1: ready to send data (transmit buffer empty) -entity sim_uart is +entity pp_soc_uart is + generic( + FIFO_DEPTH : natural := 64 --Unused + ); port( clk : in std_logic; reset : in std_logic; + -- UART ports: + txd : out std_logic; + rxd : in std_logic; + -- Wishbone ports: - wishbone_in : in wishbone_master_out; - wishbone_out : out wishbone_slave_out + wb_adr_in : in std_logic_vector(11 downto 0); + wb_dat_in : in std_logic_vector( 7 downto 0); + wb_dat_out : out std_logic_vector( 7 downto 0); + wb_we_in : in std_logic; + wb_cyc_in : in std_logic; + wb_stb_in : in std_logic; + wb_ack_out : out std_logic ); -end entity sim_uart; +end entity pp_soc_uart; -architecture behaviour of sim_uart is +architecture behaviour of pp_soc_uart is signal sample_clk_divisor : std_logic_vector(7 downto 0); @@ -56,7 +68,7 @@ architecture behaviour of sim_uart is begin - wishbone_out.ack <= wb_ack and wishbone_in.cyc and wishbone_in.stb; + wb_ack_out <= wb_ack and wb_cyc_in and wb_stb_in; wishbone: process(clk) variable sim_tmp : std_logic_vector(63 downto 0); @@ -71,42 +83,40 @@ begin else case wb_state is when IDLE => - if wishbone_in.cyc = '1' and wishbone_in.stb = '1' then - if wishbone_in.we = '1' then -- Write to register - if wishbone_in.adr(11 downto 0) = x"000" then - report "FOO !"; - sim_console_write(wishbone_in.dat); - elsif wishbone_in.adr(11 downto 0) = x"018" then - sample_clk_divisor <= wishbone_in.dat(7 downto 0); - elsif wishbone_in.adr(11 downto 0) = x"020" then - irq_recv_enable <= wishbone_in.dat(0); - irq_tx_ready_enable <= wishbone_in.dat(1); + if wb_cyc_in = '1' and wb_stb_in = '1' then + if wb_we_in = '1' then -- Write to register + if wb_adr_in(11 downto 0) = x"000" then + sim_console_write(x"00000000000000" & wb_dat_in); + elsif wb_adr_in(11 downto 0) = x"018" then + sample_clk_divisor <= wb_dat_in; + elsif wb_adr_in(11 downto 0) = x"020" then + irq_recv_enable <= wb_dat_in(0); + irq_tx_ready_enable <= wb_dat_in(1); end if; wb_ack <= '1'; wb_state <= WRITE_ACK; else -- Read from register - if wishbone_in.adr(11 downto 0) = x"008" then + if wb_adr_in(11 downto 0) = x"008" then sim_console_read(sim_tmp); - wishbone_out.dat <= sim_tmp; - elsif wishbone_in.adr(11 downto 0) = x"010" then + wb_dat_out <= sim_tmp(7 downto 0); + elsif wb_adr_in(11 downto 0) = x"010" then sim_console_poll(sim_tmp); - wishbone_out.dat <= x"000000000000000" & '0' & - sim_tmp(0) & '1' & not sim_tmp(0); - elsif wishbone_in.adr(11 downto 0) = x"018" then - wishbone_out.dat <= x"00000000000000" & sample_clk_divisor; - elsif wishbone_in.adr(11 downto 0) = x"020" then - wishbone_out.dat <= (0 => irq_recv_enable, - 1 => irq_tx_ready_enable, - others => '0'); + wb_dat_out <= "00000" & sim_tmp(0) & '1' & not sim_tmp(0); + elsif wb_adr_in(11 downto 0) = x"018" then + wb_dat_out <= sample_clk_divisor; + elsif wb_adr_in(11 downto 0) = x"020" then + wb_dat_out <= (0 => irq_recv_enable, + 1 => irq_tx_ready_enable, + others => '0'); else - wishbone_out.dat <= (others => '0'); + wb_dat_out <= (others => '0'); end if; wb_ack <= '1'; wb_state <= READ_ACK; end if; end if; when WRITE_ACK|READ_ACK => - if wishbone_in.stb = '0' then + if wb_stb_in = '0' then wb_ack <= '0'; wb_state <= IDLE; end if; diff --git a/simple_ram_behavioural.vhdl b/simple_ram_behavioural.vhdl index 6d76d76..2ccee79 100644 --- a/simple_ram_behavioural.vhdl +++ b/simple_ram_behavioural.vhdl @@ -7,10 +7,10 @@ library work; use work.wishbone_types.all; use work.simple_ram_behavioural_helpers.all; -entity simple_ram_behavioural is +entity mw_soc_memory is generic ( - FILENAME : string; - SIZE : integer + RAM_INIT_FILE : string; + MEMORY_SIZE : integer ); port ( @@ -20,14 +20,14 @@ entity simple_ram_behavioural is wishbone_in : in wishbone_master_out; wishbone_out : out wishbone_slave_out ); -end simple_ram_behavioural; +end mw_soc_memory; -architecture behave of simple_ram_behavioural is +architecture behave of mw_soc_memory is type wishbone_state_t is (IDLE, ACK); signal state : wishbone_state_t := IDLE; signal ret_ack : std_ulogic := '0'; - signal identifier : integer := behavioural_initialize(filename => FILENAME, size => SIZE); + signal identifier : integer := behavioural_initialize(filename => RAM_INIT_FILE, size => MEMORY_SIZE); signal reload : integer := 0; begin wishbone_process: process(clk) diff --git a/simple_ram_behavioural_tb.vhdl b/simple_ram_behavioural_tb.vhdl index 823c1b6..9523cd1 100644 --- a/simple_ram_behavioural_tb.vhdl +++ b/simple_ram_behavioural_tb.vhdl @@ -17,8 +17,8 @@ architecture behave of simple_ram_behavioural_tb is signal w_in : wishbone_slave_out; signal w_out : wishbone_master_out; begin - simple_ram_0: entity work.simple_ram_behavioural - generic map ( filename => "simple_ram_behavioural_tb.bin", size => 16 ) + simple_ram_0: entity work.mw_soc_memory + generic map ( RAM_INIT_FILE => "simple_ram_behavioural_tb.bin", MEMORY_SIZE => 16 ) port map (clk => clk, rst => rst, wishbone_out => w_in, wishbone_in => w_out); clock: process diff --git a/fpga/soc.vhdl b/soc.vhdl similarity index 65% rename from fpga/soc.vhdl rename to soc.vhdl index 73907a2..0b8614c 100644 --- a/fpga/soc.vhdl +++ b/soc.vhdl @@ -2,7 +2,10 @@ library ieee; use ieee.std_logic_1164.all; use ieee.math_real.all; +use std.textio.all; + library work; +use work.common.all; use work.wishbone_types.all; @@ -12,7 +15,8 @@ entity soc is generic ( MEMORY_SIZE : positive; RAM_INIT_FILE : string; - RESET_LOW : boolean + RESET_LOW : boolean; + SIM : boolean ); port( rst : in std_ulogic; @@ -37,30 +41,35 @@ architecture behaviour of soc is signal wb_master_out : wishbone_master_out; -- UART0 signals: - signal uart0_adr_in : std_logic_vector(11 downto 0); - signal uart0_dat_in : std_logic_vector( 7 downto 0); - signal uart0_dat_out : std_logic_vector( 7 downto 0); - signal uart0_cyc_in : std_logic; - signal uart0_stb_in : std_logic; - signal uart0_we_in : std_logic; - signal uart0_ack_out : std_logic; + signal wb_uart0_in : wishbone_master_out; + signal wb_uart0_out : wishbone_slave_out; + signal uart_dat8 : std_logic_vector(7 downto 0); -- Main memory signals: signal wb_bram_in : wishbone_master_out; signal wb_bram_out : wishbone_slave_out; constant mem_adr_bits : positive := positive(ceil(log2(real(MEMORY_SIZE)))); + -- Debug signals (used in SIM only) + signal registers : regfile; + signal terminate : std_ulogic; + begin -- Processor core processor: entity work.core + generic map( + SIM => SIM + ) port map( clk => system_clk, rst => rst, wishbone_insn_in => wishbone_icore_in, wishbone_insn_out => wishbone_icore_out, wishbone_data_in => wishbone_dcore_in, - wishbone_data_out => wishbone_dcore_out + wishbone_data_out => wishbone_dcore_out, + registers => registers, + terminate_out => terminate ); -- Wishbone bus master arbiter & mux @@ -77,8 +86,7 @@ begin ); -- Wishbone slaves address decoder & mux - slave_intercon: process(wb_master_out, wb_bram_out, - uart0_ack_out, uart0_dat_out) + slave_intercon: process(wb_master_out, wb_bram_out, wb_uart0_out) -- Selected slave type slave_type is (SLAVE_UART, SLAVE_MEMORY, @@ -98,22 +106,42 @@ begin -- Wishbone muxing. Defaults: wb_bram_in <= wb_master_out; wb_bram_in.cyc <= '0'; - uart0_cyc_in <= '0'; + wb_uart0_in <= wb_master_out; + wb_uart0_in.cyc <= '0'; case slave is when SLAVE_MEMORY => wb_bram_in.cyc <= wb_master_out.cyc; wb_master_in <= wb_bram_out; when SLAVE_UART => - uart0_cyc_in <= wb_master_out.cyc; - wb_master_in.ack <= uart0_ack_out; - wb_master_in.dat <= x"00000000000000" & uart0_dat_out; + wb_uart0_in.cyc <= wb_master_out.cyc; + wb_master_in <= wb_uart0_out; when others => wb_master_in.dat <= (others => '1'); wb_master_in.ack <= wb_master_out.stb and wb_master_out.cyc; end case; end process slave_intercon; + -- Simulated memory and UART + sim_terminate_test: if SIM generate + + -- Dump registers if core terminates + dump_registers: process(all) + begin + if terminate = '1' then + loop_0: for i in 0 to 31 loop + report "REG " & to_hstring(registers(i)); + end loop loop_0; + assert false report "end of test" severity failure; + end if; + end process; + + end generate; + -- UART0 wishbone slave + -- XXX FIXME: Need a proper wb64->wb8 adapter that + -- converts SELs into low address bits and muxes + -- data accordingly (either that or rejects large + -- cycles). uart0: entity work.pp_soc_uart generic map( FIFO_DEPTH => 32 @@ -123,22 +151,15 @@ begin reset => rst, txd => uart0_txd, rxd => uart0_rxd, - wb_adr_in => uart0_adr_in, - wb_dat_in => uart0_dat_in, - wb_dat_out => uart0_dat_out, - wb_cyc_in => uart0_cyc_in, - wb_stb_in => uart0_stb_in, - wb_we_in => uart0_we_in, - wb_ack_out => uart0_ack_out + wb_adr_in => wb_uart0_in.adr(11 downto 0), + wb_dat_in => wb_uart0_in.dat(7 downto 0), + wb_dat_out => uart_dat8, + wb_cyc_in => wb_uart0_in.cyc, + wb_stb_in => wb_uart0_in.stb, + wb_we_in => wb_uart0_in.we, + wb_ack_out => wb_uart0_out.ack ); - -- Wire it up: XXX FIXME: Need a proper wb64->wb8 adapter that - -- converts SELs into low address bits and muxes - -- data accordingly (either that or rejects large - -- cycles). - uart0_adr_in <= wb_master_out.adr(uart0_adr_in'range); - uart0_dat_in <= wb_master_out.dat(7 downto 0); - uart0_we_in <= wb_master_out.we; - uart0_stb_in <= wb_master_out.stb; + wb_uart0_out.dat <= x"00000000000000" & uart_dat8; -- BRAM Memory slave bram0: entity work.mw_soc_memory