Rework wishbone slave address decoding
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 10 Sep 2019 13:52:23 +0000 (14:52 +0100)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 10 Sep 2019 15:50:49 +0000 (16:50 +0100)
Don't make it synchronous, no latches

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
fpga/soc.vhdl

index ea6e3e55edd0d6e20475dd0c6f447ed55b71e6e3..42f7d184557498e06f2e9427bb6bba28ed75341a 100644 (file)
@@ -27,22 +27,14 @@ end entity soc;
 architecture behaviour of soc is
 
     -- Wishbone master signals:
-    signal wishbone_proc_out: wishbone_master_out;
-    signal wishbone_proc_in: wishbone_slave_out;
     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;
 
-    -- Processor signals:
-    signal processor_adr_out : std_logic_vector(63 downto 0);
-    signal processor_sel_out : std_logic_vector(7 downto 0);
-    signal processor_cyc_out : std_logic;
-    signal processor_stb_out : std_logic;
-    signal processor_we_out  : std_logic;
-    signal processor_dat_out : std_logic_vector(63 downto 0);
-    signal processor_dat_in  : std_logic_vector(63 downto 0);
-    signal processor_ack_in  : std_logic;
+    -- Wishbone master (output of arbiter):
+    signal wb_master_in : wishbone_slave_out;
+    signal wb_master_out : wishbone_master_out;
 
     -- UART0 signals:
     signal uart0_adr_in  : std_logic_vector(11 downto 0);
@@ -63,71 +55,9 @@ architecture behaviour of soc is
     signal main_memory_we_in   : std_logic;
     signal main_memory_ack_out : std_logic;
 
-    -- Selected peripheral on the interconnect:
-    type intercon_peripheral_type is (
-       PERIPHERAL_UART0, PERIPHERAL_MAIN_MEMORY, PERIPHERAL_ERROR,
-       PERIPHERAL_NONE);
-    signal intercon_peripheral : intercon_peripheral_type := PERIPHERAL_NONE;
-
-    -- Interconnect address decoder state:
-    signal intercon_busy : boolean := false;
-
 begin
 
-    address_decoder: process(system_clk)
-    begin
-       if rising_edge(system_clk) then
-           if rst = '1' then
-               intercon_peripheral <= PERIPHERAL_NONE;
-               intercon_busy <= false;
-           else
-               if not intercon_busy then
-                   if processor_cyc_out = '1' then
-                       intercon_busy <= true;
-
-                       if processor_adr_out(31 downto 24) = x"00" then -- Main memory space
-                           intercon_peripheral <= PERIPHERAL_MAIN_MEMORY;
-                       elsif processor_adr_out(31 downto 24) = x"c0" then -- Peripheral memory space
-                           case processor_adr_out(15 downto 12) is
-                           when x"2" =>
-                               intercon_peripheral <= PERIPHERAL_UART0;
-                           when others => -- Invalid address - delegated to the error peripheral
-                               intercon_peripheral <= PERIPHERAL_ERROR;
-                           end case;
-                       else
-                           intercon_peripheral <= PERIPHERAL_ERROR;
-                       end if;
-                   else
-                       intercon_peripheral <= PERIPHERAL_NONE;
-                   end if;
-               else
-                   if processor_cyc_out = '0' then
-                       intercon_busy <= false;
-                       intercon_peripheral <= PERIPHERAL_NONE;
-                   end if;
-               end if;
-           end if;
-       end if;
-    end process address_decoder;
-
-    processor_intercon: process(all)
-    begin
-       case intercon_peripheral is
-       when PERIPHERAL_UART0 =>
-           processor_ack_in <= uart0_ack_out;
-           processor_dat_in <= x"00000000000000" & uart0_dat_out;
-       when PERIPHERAL_MAIN_MEMORY =>
-           processor_ack_in <= main_memory_ack_out;
-           processor_dat_in <= main_memory_dat_out;
-       when PERIPHERAL_NONE =>
-           processor_ack_in <= '0';
-           processor_dat_in <= (others => '0');
-       when others =>
-           processor_ack_in <= '0';
-           processor_dat_in <= (others => '0');
-       end case;
-    end process processor_intercon;
-
+    -- Processor core
     processor: entity work.core
        port map(
            clk => system_clk,
@@ -138,6 +68,7 @@ begin
            wishbone_data_out => wishbone_dcore_out
            );
 
+    -- Wishbone bus master arbiter & mux
     wishbone_arbiter_0: entity work.wishbone_arbiter
        port map(
            clk => system_clk,
@@ -146,18 +77,49 @@ begin
            wb1_out => wishbone_dcore_in,
            wb2_in => wishbone_icore_out,
            wb2_out => wishbone_icore_in,
-           wb_out => wishbone_proc_out,
-           wb_in => wishbone_proc_in
+           wb_out => wb_master_out,
+           wb_in => wb_master_in
            );
-    processor_adr_out <= wishbone_proc_out.adr;
-    processor_dat_out <= wishbone_proc_out.dat;
-    processor_sel_out <= wishbone_proc_out.sel;
-    processor_cyc_out <= wishbone_proc_out.cyc;
-    processor_stb_out <= wishbone_proc_out.stb;
-    processor_we_out <= wishbone_proc_out.we;
-    wishbone_proc_in.dat <= processor_dat_in;
-    wishbone_proc_in.ack <= processor_ack_in;
 
+    -- Wishbone slaves address decoder & mux
+    slave_intercon: process(wb_master_out,
+                           main_memory_ack_out, main_memory_dat_out,
+                           uart0_ack_out, uart0_dat_out)
+       -- Selected slave
+       type slave_type is (SLAVE_UART,
+                           SLAVE_MEMORY,
+                           SLAVE_NONE);
+       variable slave : slave_type;
+    begin
+       -- Simple address decoder
+       slave := SLAVE_NONE;
+       if wb_master_out.adr(63 downto 24) = x"0000000000" then
+           slave := SLAVE_MEMORY;
+       elsif wb_master_out.adr(63 downto 24) = x"00000000c0" then
+           if wb_master_out.adr(15 downto 12) = x"2" then
+               slave := SLAVE_UART;
+           end if;
+       end if;
+
+       -- Wishbone muxing. Defaults:
+       main_memory_cyc_in <= '0';
+       uart0_cyc_in <= '0';
+       case slave is
+       when SLAVE_MEMORY =>
+           main_memory_cyc_in <= wb_master_out.cyc;
+           wb_master_in.ack <= main_memory_ack_out;
+           wb_master_in.dat <= main_memory_dat_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;
+       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;
+
+    -- UART0 wishbone slave
     uart0: entity work.pp_soc_uart
        generic map(
            FIFO_DEPTH => 32
@@ -175,12 +137,16 @@ begin
            wb_we_in => uart0_we_in,
            wb_ack_out => uart0_ack_out
            );
-    uart0_adr_in <= processor_adr_out(uart0_adr_in'range);
-    uart0_dat_in <= processor_dat_out(7 downto 0);
-    uart0_we_in  <= processor_we_out;
-    uart0_cyc_in <= processor_cyc_out when intercon_peripheral = PERIPHERAL_UART0 else '0';
-    uart0_stb_in <= processor_stb_out when intercon_peripheral = PERIPHERAL_UART0 else '0';
-
+    -- 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;
+
+    -- BRAM Memory slave
     main_memory: entity work.pp_soc_memory
        generic map(
            MEMORY_SIZE   => MEMORY_SIZE,
@@ -198,13 +164,10 @@ begin
            wb_we_in => main_memory_we_in,
            wb_ack_out => main_memory_ack_out
            );
-    main_memory_adr_in <= processor_adr_out(main_memory_adr_in'range);
-    main_memory_dat_in <= processor_dat_out;
-    main_memory_we_in  <= processor_we_out;
-    main_memory_sel_in <= processor_sel_out;
-    main_memory_cyc_in <= processor_cyc_out when
-                         intercon_peripheral = PERIPHERAL_MAIN_MEMORY else '0';
-    main_memory_stb_in <= processor_stb_out when
-                         intercon_peripheral = PERIPHERAL_MAIN_MEMORY else '0';
+    main_memory_adr_in <= wb_master_out.adr(main_memory_adr_in'range);
+    main_memory_dat_in <= wb_master_out.dat;
+    main_memory_we_in  <= wb_master_out.we;
+    main_memory_sel_in <= wb_master_out.sel;
+    main_memory_stb_in <= wb_master_out.stb;
 
 end architecture behaviour;