Commit deb62f42 authored by Tristan Gingold's avatar Tristan Gingold

Add wishbone/wb_indirect.

parent 4fedd474
......@@ -27,6 +27,7 @@ modules = { "local" : [
"wb_metadata",
"wb_split",
"wb16_to_wb32",
"wb_indirect",
"wbgen2",
"wbgenplus",
]}
......
files = ["xwb_indirect.vhd", "wb_indirect_regs.vhd"]
memory-map:
bus: wb-32-be
name: wb_indirect_regs
description: Indirect access to a wishbone bus
x-hdl:
busgroup: True
children:
- reg:
name: addr
description: address to use on the wishbone bus
width: 32
access: rw
x-hdl:
write-strobe: True
type: wire
- reg:
name: data
description: data word to be read or written
width: 32
access: rw
x-hdl:
write-strobe: True
read-strobe: True
write-ack: True
read-ack: True
type: wire
-- Do not edit. Generated on Mon Apr 20 10:08:30 2020 by gingold
-- With Cheby 1.4.dev0 and these options:
-- -i wb_indirect_regs.cheby --gen-hdl=wb_indirect_regs.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
entity wb_indirect_regs is
port (
rst_n_i : in std_logic;
clk_i : in std_logic;
wb_i : in t_wishbone_slave_in;
wb_o : out t_wishbone_slave_out;
-- address to use on the wishbone bus
addr_i : in std_logic_vector(31 downto 0);
addr_o : out std_logic_vector(31 downto 0);
addr_wr_o : out std_logic;
-- data word to be read or written
data_i : in std_logic_vector(31 downto 0);
data_o : out std_logic_vector(31 downto 0);
data_wr_o : out std_logic;
data_rd_o : out std_logic;
data_wack_i : in std_logic;
data_rack_i : in std_logic
);
end wb_indirect_regs;
architecture syn of wb_indirect_regs is
signal adr_int : std_logic_vector(2 downto 2);
signal rd_req_int : std_logic;
signal wr_req_int : std_logic;
signal rd_ack_int : std_logic;
signal wr_ack_int : std_logic;
signal wb_en : std_logic;
signal ack_int : std_logic;
signal wb_rip : std_logic;
signal wb_wip : std_logic;
signal addr_wreq : std_logic;
signal data_wreq : std_logic;
signal rd_ack_d0 : std_logic;
signal rd_dat_d0 : std_logic_vector(31 downto 0);
signal wr_req_d0 : std_logic;
signal wr_adr_d0 : std_logic_vector(2 downto 2);
signal wr_dat_d0 : std_logic_vector(31 downto 0);
signal wr_sel_d0 : std_logic_vector(3 downto 0);
begin
-- WB decode signals
adr_int <= wb_i.adr(2 downto 2);
wb_en <= wb_i.cyc and wb_i.stb;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wb_rip <= '0';
else
wb_rip <= (wb_rip or (wb_en and not wb_i.we)) and not rd_ack_int;
end if;
end if;
end process;
rd_req_int <= (wb_en and not wb_i.we) and not wb_rip;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wb_wip <= '0';
else
wb_wip <= (wb_wip or (wb_en and wb_i.we)) and not wr_ack_int;
end if;
end if;
end process;
wr_req_int <= (wb_en and wb_i.we) and not wb_wip;
ack_int <= rd_ack_int or wr_ack_int;
wb_o.ack <= ack_int;
wb_o.stall <= not ack_int and wb_en;
wb_o.rty <= '0';
wb_o.err <= '0';
-- pipelining for wr-in+rd-out
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
rd_ack_int <= '0';
wr_req_d0 <= '0';
else
rd_ack_int <= rd_ack_d0;
wb_o.dat <= rd_dat_d0;
wr_req_d0 <= wr_req_int;
wr_adr_d0 <= adr_int;
wr_dat_d0 <= wb_i.dat;
wr_sel_d0 <= wb_i.sel;
end if;
end if;
end process;
-- Register addr
addr_o <= wr_dat_d0;
addr_wr_o <= addr_wreq;
-- Register data
data_o <= wr_dat_d0;
data_wr_o <= data_wreq;
-- Process for write requests.
process (wr_adr_d0, wr_req_d0, data_wack_i) begin
addr_wreq <= '0';
data_wreq <= '0';
case wr_adr_d0(2 downto 2) is
when "0" =>
-- Reg addr
addr_wreq <= wr_req_d0;
wr_ack_int <= wr_req_d0;
when "1" =>
-- Reg data
data_wreq <= wr_req_d0;
wr_ack_int <= data_wack_i;
when others =>
wr_ack_int <= wr_req_d0;
end case;
end process;
-- Process for read requests.
process (adr_int, rd_req_int, addr_i, data_rack_i, data_i) begin
-- By default ack read requests
rd_dat_d0 <= (others => 'X');
data_rd_o <= '0';
case adr_int(2 downto 2) is
when "0" =>
-- Reg addr
rd_ack_d0 <= rd_req_int;
rd_dat_d0 <= addr_i;
when "1" =>
-- Reg data
data_rd_o <= rd_req_int;
rd_ack_d0 <= data_rack_i;
rd_dat_d0 <= data_i;
when others =>
rd_ack_d0 <= rd_req_int;
end case;
end process;
end syn;
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General cores: Indirect Wishbone Slave
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: xwb_indirect
--
-- description: This design is a wishbone slave that drivers a wishbone master.
-- As a slave, it has 2 registers: address and data. An access to the data
-- register starts a transaction on the WB master side using the address of
-- the address register. At the end of the transaction, the address
-- register is incremented by 4.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2020
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
-- in compliance with the License. You may obtain a copy of the License at
-- http://solderpad.org/licenses/SHL-2.0.
-- Unless required by applicable law or agreed to in writing, software,
-- hardware and materials distributed under this License is distributed on an
-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-- or implied. See the License for the specific language governing permissions
-- and limitations under the License.
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
entity xwb_indirect is
generic (
mode : t_wishbone_interface_mode := PIPELINED
);
port (
rst_n_i : in std_logic;
clk_i : in std_logic;
wb_i : in t_wishbone_slave_in;
wb_o : out t_wishbone_slave_out;
master_wb_i : in t_wishbone_master_in;
master_wb_o : out t_wishbone_master_out
);
end xwb_indirect;
architecture arch of xwb_indirect is
-- Address register. Use a specific register to auto-increment it.
signal addr : std_logic_vector(31 downto 0);
signal addr_out : std_logic_vector(31 downto 0);
signal addr_wr_out : std_logic;
signal data : std_logic_vector(31 downto 0);
signal data_out : std_logic_vector(31 downto 0);
signal data_wr_out : std_logic;
signal data_rd_out : std_logic;
signal data_wack_in : std_logic;
signal data_rack_in : std_logic;
type t_state is (IDLE, READ, WRITE);
signal state : t_state;
signal stb : std_logic;
signal we : std_logic;
begin
process (clk_i)
begin
if rising_edge (clk_i) then
if rst_n_i = '0' then
state <= IDLE;
data_wack_in <= '0';
data_rack_in <= '0';
data <= (others => '0');
addr <= (others => '0');
stb <= '0';
we <= '0';
else
data_wack_in <= '0';
data_rack_in <= '0';
-- Write to the address register.
if addr_wr_out = '1' then
addr <= addr_out;
end if;
case state is
when IDLE =>
if data_wr_out = '1' then
we <= '1';
stb <= '1';
-- Capture the data.
data <= data_out;
state <= WRITE;
elsif data_rd_out = '1' then
we <= '1';
stb <= '1';
state <= READ;
end if;
when WRITE
| READ =>
if mode = PIPELINED then
-- STB is asserted for one cycle in piplined mode.
stb <= '0';
end if;
if master_wb_i.ack = '1'
or master_wb_i.err = '1'
or master_wb_i.rty = '1'
then
-- End of transaction (for classic mode).
stb <= '0';
-- Ack the master.
if state = WRITE then
data_wack_in <= '1';
else
-- Capture the data.
data <= master_wb_i.dat;
data_rack_in <= '1';
end if;
addr <= std_logic_vector(unsigned(addr) + 4);
state <= IDLE;
end if;
end case;
end if;
end if;
end process;
master_wb_o <= (cyc => stb,
stb => stb,
adr => addr,
sel => "1111",
we => we,
dat => data);
inst_regs: entity work.wb_indirect_regs
port map (
rst_n_i => rst_n_i,
clk_i => clk_i,
wb_i => wb_i,
wb_o => wb_o,
addr_i => addr,
addr_o => addr_out,
addr_wr_o => addr_wr_out,
data_i => data,
data_o => data_out,
data_wr_o => data_wr_out,
data_rd_o => data_rd_out,
data_wack_i => data_wack_in,
data_rack_i => data_rack_in);
end arch;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment