From 308d96c9c5f16d1d1d447b59aa72fcfd0296d8bd Mon Sep 17 00:00:00 2001
From: "Wesley W. Terpstra" <w.terpstra@gsi.de>
Date: Mon, 5 Mar 2012 13:57:15 +0100
Subject: [PATCH] Fix bugs:   record count is 16 bit   index aliased decription
 (to avoid overflow)

Added feature:
  make it easy to relocate a device to a new address

Checks added:
  confirm address ranges to not overlap during synthesis
  check wbd_begin/end addresses for compatability with the crossbar
---
 modules/wishbone/wb_crossbar/sdwb_rom.vhd     | 22 ++++++-------
 modules/wishbone/wb_crossbar/xwb_crossbar.vhd | 23 +++++++++++--
 .../wb_crossbar/xwb_sdwb_crossbar.vhd         | 33 +++++++++++++++----
 modules/wishbone/wishbone_pkg.vhd             | 21 ++++++++++++
 4 files changed, 80 insertions(+), 19 deletions(-)

diff --git a/modules/wishbone/wb_crossbar/sdwb_rom.vhd b/modules/wishbone/wb_crossbar/sdwb_rom.vhd
index 248894e6..4a264147 100644
--- a/modules/wishbone/wb_crossbar/sdwb_rom.vhd
+++ b/modules/wishbone/wb_crossbar/sdwb_rom.vhd
@@ -41,16 +41,16 @@ architecture rtl of sdwb_rom is
     variable res : t_rom := (others => (others => '0'));
     variable sdwb_device : std_logic_vector(0 to c_sdwb_device_length-1) := (others => '0');
   begin
-    sdwb_device(  0 to 127) := not x"40f6e98c29eae24c7e6461ae8d2af247";          -- magic
-    sdwb_device(128 to 191) := std_logic_vector(g_bus_end);                      -- bus_end
-    sdwb_device(192 to 207) := std_logic_vector(to_unsigned(c_used_entries, 8)); -- sdwb_records
-    sdwb_device(208 to 215) := x"01";                                            -- sdwb_ver_major
-    sdwb_device(216 to 223) := x"00";                                            -- sdwb_ver_minor
-    sdwb_device(224 to 255) := x"00000651";                                      -- bus_vendor (GSI)
-    sdwb_device(256 to 287) := x"00000004";                                      -- bus_device
-    sdwb_device(288 to 319) := std_logic_vector(to_unsigned(c_version, 32));     -- bus_version
-    sdwb_device(320 to 351) := std_logic_vector(to_unsigned(c_date,    32));     -- bus_date
-    sdwb_device(352 to 383) := x"00000000";                                      -- bus_flags
+    sdwb_device(  0 to 127) := not x"40f6e98c29eae24c7e6461ae8d2af247";           -- magic
+    sdwb_device(128 to 191) := std_logic_vector(g_bus_end);                       -- bus_end
+    sdwb_device(192 to 207) := std_logic_vector(to_unsigned(c_used_entries, 16)); -- sdwb_records
+    sdwb_device(208 to 215) := x"01";                                             -- sdwb_ver_major
+    sdwb_device(216 to 223) := x"00";                                             -- sdwb_ver_minor
+    sdwb_device(224 to 255) := x"00000651";                                       -- bus_vendor (GSI)
+    sdwb_device(256 to 287) := x"eef0b198";                                       -- bus_device
+    sdwb_device(288 to 319) := std_logic_vector(to_unsigned(c_version, 32));      -- bus_version
+    sdwb_device(320 to 351) := std_logic_vector(to_unsigned(c_date,    32));      -- bus_date
+    sdwb_device(352 to 383) := x"00000000";                                       -- bus_flags
     for i in 1 to 16 loop
       sdwb_device(376+i*8 to 383+i*8) := 
         std_logic_vector(to_unsigned(character'pos(c_rom_description(i)), 8));
@@ -77,7 +77,7 @@ architecture rtl of sdwb_rom is
       for i in 1 to 16 loop
         -- string to ascii
         sdwb_device(376+i*8 to 383+i*8) := 
-          std_logic_vector(to_unsigned(character'pos(g_layout(slave).description(i)), 8));
+          std_logic_vector(to_unsigned(character'pos(c_layout(slave).description(i)), 8));
       end loop;
       
       for i in 0 to c_sdwb_words-1 loop
diff --git a/modules/wishbone/wb_crossbar/xwb_crossbar.vhd b/modules/wishbone/wb_crossbar/xwb_crossbar.vhd
index 14ed1ddf..266fc2f7 100644
--- a/modules/wishbone/wb_crossbar/xwb_crossbar.vhd
+++ b/modules/wishbone/wb_crossbar/xwb_crossbar.vhd
@@ -73,6 +73,27 @@ architecture rtl of xwb_crossbar is
   alias c_address : t_wishbone_address_array(g_num_slaves-1 downto 0) is g_address;
   alias c_mask    : t_wishbone_address_array(g_num_slaves-1 downto 0) is g_mask;
 
+  -- Confirm that no address ranges overlap
+  function f_ranges_ok
+    return boolean
+  is
+    variable zero : t_wishbone_address := (others => '0');
+  begin
+    for i in 0 to g_num_slaves-2 loop
+      for j in i+1 to g_num_slaves-1 loop
+        assert not (((g_mask(i) and g_mask(j)) and (g_address(i) xor g_address(j))) = zero)
+        report "Address ranges must be distinct (slaves " & 
+	       Integer'image(i) & "[" & Integer'image(to_integer(unsigned(g_address(i)))) & "/" &
+	                                Integer'image(to_integer(unsigned(g_mask(i)))) & "] & " & 
+	       Integer'image(j) & "[" & Integer'image(to_integer(unsigned(g_address(j)))) & "/" &
+	                                Integer'image(to_integer(unsigned(g_mask(j)))) & "])"
+        severity Failure;
+      end loop;
+    end loop;
+    return true;
+  end f_ranges_ok;
+  constant c_ok : boolean := f_ranges_ok;
+
   -- Crossbar connection matrix
   type matrix is array (g_num_masters-1 downto 0, g_num_slaves downto 0) of std_logic;
   
@@ -363,6 +384,4 @@ begin
   master_matrix : for master in g_num_masters-1 downto 0 generate
     slave_o(master) <= master_logic(master, granted, master_ie);
   end generate;
-  
-  -- !!! check for overlap
 end rtl;
diff --git a/modules/wishbone/wb_crossbar/xwb_sdwb_crossbar.vhd b/modules/wishbone/wb_crossbar/xwb_sdwb_crossbar.vhd
index 52bc97aa..b820a1c2 100644
--- a/modules/wishbone/wb_crossbar/xwb_sdwb_crossbar.vhd
+++ b/modules/wishbone/wb_crossbar/xwb_sdwb_crossbar.vhd
@@ -65,11 +65,21 @@ architecture rtl of xwb_sdwb_crossbar is
   
   function f_addresses return t_wishbone_address_array is
     variable result : t_wishbone_address_array(g_layout'range);
+    variable extend : unsigned(63 downto 0) := (others => '0');
   begin
     for i in g_layout'range loop
       result(i) := std_logic_vector(g_layout(i).wbd_begin(c_wishbone_address_width-1 downto 0));
-      -- !!! report if address is too big
-      -- !!! report if end < begin
+      
+      -- Range must be valid
+      assert g_layout(i).wbd_begin <= g_layout(i).wbd_end
+      report "Wishbone slave device #" & Integer'image(i) & " (" & g_layout(i).description & ") wbd_begin address must precede wbd_end address."
+      severity Failure;
+      
+      -- Address must fit
+      extend(c_wishbone_address_width-1 downto 0) := unsigned(result(i));
+      assert g_layout(i).wbd_begin = extend
+      report "Wishbone slave device #" & Integer'image(i) & " (" & g_layout(i).description & ") wbd_begin does not fit in t_wishbone_address."
+      severity Failure;
     end loop;
     return result;
   end f_addresses;
@@ -77,12 +87,23 @@ architecture rtl of xwb_sdwb_crossbar is
   function f_masks return t_wishbone_address_array is
     variable result : t_wishbone_address_array(g_layout'range);
     variable size : unsigned(63 downto 0);
+    variable zero : unsigned(63 downto 0) := (others => '0');
   begin
     for i in g_layout'range loop
-      size := (g_layout(i).wbd_end - g_layout(i).wbd_begin);
-      -- !!! report if size not a power of 2
-      -- !!! report if address is misaligned
-      result(i) := std_logic_vector(c_bus_bits - size);
+      size := g_layout(i).wbd_end - g_layout(i).wbd_begin;
+      
+      -- size must be of the form 000000...00001111...1
+      assert (size and (size + to_unsigned(1, 64))) = zero
+      report "Wishbone slave device #" & Integer'image(i) & " (" & g_layout(i).description & ") has an address range size that is not a power of 2 minus one (" & Integer'image(to_integer(size)) & "). This is not supported by this crossbar."
+      severity Failure;
+      
+      -- the base address must be aligned to the size
+      assert (g_layout(i).wbd_begin and size) = zero
+      report "Wishbone slave device #" & Integer'image(i) & " (" & g_layout(i).description & ") wbd_begin address is not aligned. This is not supported by this crossbar."
+      severity Failure;
+      
+      size := c_bus_bits - size;
+      result(i) := std_logic_vector(size(c_wishbone_address_width-1 downto 0));
     end loop;
     return result;
   end f_masks;
diff --git a/modules/wishbone/wishbone_pkg.vhd b/modules/wishbone/wishbone_pkg.vhd
index 04811c54..3a6e02ca 100644
--- a/modules/wishbone/wishbone_pkg.vhd
+++ b/modules/wishbone/wishbone_pkg.vhd
@@ -88,6 +88,10 @@ package wishbone_pkg is
     description        : string(1 to 16);
   end record t_sdwb_device;
   type t_sdwb_device_array is array(natural range <>) of t_sdwb_device;
+  
+  -- Used to configure a device at a certain address
+  function f_sdwb_set_address(device : t_sdwb_device; address : t_wishbone_address)
+    return t_sdwb_device;
 
 ------------------------------------------------------------------------------
 -- Components declaration
@@ -543,3 +547,20 @@ package wishbone_pkg is
       irq_master_o : out std_logic);
   end component;
 end wishbone_pkg;
+
+package body wishbone_pkg is
+  -- Used to configure a device at a certain address
+  function f_sdwb_set_address(device : t_sdwb_device; address : t_wishbone_address)
+    return t_sdwb_device
+  is
+    variable result : t_sdwb_device;
+  begin
+    result := device;
+    result.wbd_begin := (others => '0');
+    
+    result.wbd_begin(c_wishbone_address_width-1 downto 0) := unsigned(address);
+    result.wbd_end := result.wbd_begin + (device.wbd_end - device.wbd_begin);
+    
+    return result;
+  end;
+end wishbone_pkg;
-- 
GitLab