Commit 59928100 authored by A. Hahn's avatar A. Hahn

merged with master

parents 4cde26be 258eb8e0
# SPDX-License-Identifier: CC0-1.0
#
# SPDX-FileCopyrightText: 2019 CERN
---
variables:
KOJI_TARGET: 'ohwr7'
KOJI_DISTTAG: '.el7.cern'
DIST_PATH: distribution
BUILD_PATH: distribution/rpmbuild
SRPM_PATH: distribution/rpmbuild/SRPMS/dkms-${CI_PROJECT_NAME}*src.rpm
stages:
- static-analysis
- build
- srpm
- kscratch
- kbuild
reuse:
stage: static-analysis
image: fsfe/reuse:latest
script:
- reuse lint
allow_failure: true
build:
stage: build
script:
- yum install -y kernel-devel git
- export LINUX=/usr/src/kernels/*/
- make -C software
build-dkms:
stage: build
script:
- yum install -y kernel-devel lua git dkms
- export LINUX=/usr/src/kernels/*/
- export PREFIX=$(mktemp -d)
- make -C software/ -f dkms.mk dkms_install
- make -C ${PREFIX}/usr/src/${CI_PROJECT_NAME}*/
build_srpm:
stage: srpm
script:
- yum-builddep -y ${DIST_PATH}/*.spec
- export LINUX=/usr/src/kernels/*/
- make -C distribution rpmbuild-source
artifacts:
paths:
- ${SRPM_PATH}
expire_in: 1 day
.koji_deps_template: &koji_deps
before_script:
- yum install -y koji krb5-workstation rpm-build
- echo ${OHWR_PASSWORD} | kinit ${OHWR_USER}
kscratch:
<<: *koji_deps
stage: kscratch
script:
- koji --config=.koji build --wait --scratch ${KOJI_TARGET} ${SRPM_PATH}
kbuild-ohwr:
<<: *koji_deps
stage: kbuild
only:
- /^v[0-9]+\.[0-9]+\.[0-9]+$/
except:
- branches
script:
- koji --config=.koji build --wait ${KOJI_TARGET} ${SRPM_PATH}
# SPDX-License-Identifier: CC0-1.0
#
# SPDX-FileCopyrightText: 2019 CERN
[koji]
server = https://kojihub.cern.ch/kojihub
weburl = https://koji.cern.ch/
topurl = https://koji.cern.ch/kojifiles
krb_canon_host = no
krb_rdns = False
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [1.0.0] - 2019-10-21
### Added
- First release of general-cores.
[Unreleased]: https://www.ohwr.org/project/general-cores/compare/v1.0.0...proposed_master
[1.0.0]: https://www.ohwr.org/project/general-cores/tags/v1.0.0
..
SPDX-License-Identifier: CC0-1.0
SPDX-FileCopyrightText: 2019-2020 CERN
==========
Change Log
==========
- Format inspired by: `Keep a Changelog <https://keepachangelog.com/en/1.0.0/>`_
- Versioning scheme follows: `Semantic Versioning <https://semver.org/spec/v2.0.0.html>`_
1.1.0 - 2020-07-24
==================
https://www.ohwr.org/project/general-cores/tags/v1.1.0
Added
-----
- hdl: New indirect wishbone master (driven by an address and data register).
- hdl: New memory wrapper for Cheby.
- hdl: Provide a simple vhdl package to generate WB transactions.
- hdl: New wb_xc7_fw_update module.
- bld: Introduce gen_sourceid.py script to generate a package with the source id.
Changed
-------
- bld: gen_buildinfo.py now adds tag and dirty flag.
Fixed
-----
- hdl: regression to gc_sync_ffs introduced by v1.0.4.
- hdl: add dummy generic to generic_dpram in altera.
- hdl: add missing generics to generic_sync_fifo in genram_pkg.
- hdl: avoid f_log2() circular dependencies in gc_extend_pulse.
1.0.4 - 2020-03-26
==================
https://www.ohwr.org/project/general-cores/tags/v1.0.4
Added
-----
- [hdl] VHDL functions to convert characters and strings to upper/lower case.
- [sw][i2c] Support for kernel greater than 4.7.
- [hdl] Separate synchroniser and edge detection modules.
- [hdl] 8b10b encoder.
Changed
-------
- [hdl] Rewritten the WB master interface used in simulations.
- [hdl] Reimplement gc_sync_ffs using new synchroniser and edge detectors.
Fixed
-----
- [sw][spi] Align polarity and phase for Rx and Tx.
- [hdl][i2c] Fix reset lock for I2C master.
- [hdl] Avoid cyclic dependencies for log2 ceiling functions.
1.0.3 - 2020-01-15
==================
https://www.ohwr.org/project/general-cores/tags/v1.0.3
Changed
-----
- [sw] add more file to .gitignore
1.0.2 - 2019-10-24
==================
https://www.ohwr.org/project/general-cores/tags/v1.0.2
Fixed
-----
- [ci] forgot rule to publish RPMs
1.0.1 - 2019-10-24
==================
https://www.ohwr.org/project/general-cores/tags/v1.0.1
Added
-----
- [ci] building and publish RPMs automatically on new releases
Changed
-------
- [sw] Makefiles have been changed to better support RPM generation
1.0.0 - 2019-10-21
==================
https://www.ohwr.org/project/general-cores/tags/v1.0.0
Added
-----
- First release of general-cores.
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.
This diff is collapsed.
......@@ -13,13 +13,23 @@ In [modules/common](modules/common) there are general purpose cores:
* The package [matrix_pkg](modules/common/matrix_pkg.vhd) declares a 2d
array of std_logic, and some subprograms to handle it.
* Edge detectors are provided by [gc_posedge](modules/common/gc_posedge.vhd),
[gc_negedge](modules/common/gc_negedge.vhd), and
[gc_edge_detect](modules/common/gc_edge_detect.vhd).
* For clock-domain crossing or asynchronous signal register, use
[gc_sync_ffs](modules/common/gc_sync_ffs.vhd). It also has an edge
detector.
[gc_sync](modules/common/gc_sync.vhd). This is the basic synchronizer.
If you also need an edge detector, use
[gc_sync_ffs](modules/common/gc_sync_ffs.vhd).
The other synchronizer [gc_sync_register](modules/common/gc_sync_register.vhd)
is deprecated. It can synchronize multiple signals at the same time but
doesn't ensure coherency between these signals.
The module [gc_sync_edge](modules/common/gc_sync_edge.vhd) provides a
synchronizer with an (positive or negative) edge detector. The signal
edge is always detected on the rising edge of the clock. This module is
simpler than the gc_sync_ffs module.
To pass words from one clock domain to another, you can use the module
[gc_sync_word_wr](modules/common/gc_sync_word_wr.vhd) for writing data,
and [gc_sync_word_rd](modules/common/gc_sync_word_rd.vhd) for reading
......@@ -186,6 +196,8 @@ Directory [modules/wishbone](modules/wishbone) contains modules for wishbone.
- [wb_vic](modules/wishbone/wb_vic) is the vectored interrupt controller.
- [wb_ds182x_readout](modules/wishbone/wb_ds182x_readout) is a direct
interface to the digital thermometer.
- [wb_xc7_fw_update](modules/wishbone/wb_xc7_fw_update) is an SPI interface
to drive the xc7 bitstream spi flash (using the ht-flash tool).
* There are utilities to handle a wishbone bus:
- [wb_clock_crossing](modules/wishbone/wb_clock_crossing) handle clock domain
......@@ -197,6 +209,15 @@ Directory [modules/wishbone](modules/wishbone) contains modules for wishbone.
AT91SAM9x CPU external bus interface.
- [wb_axi4lite_bridge](modules/wishbone/wb_axi4lite_bridge) is an axi4lite
to wishbone bridge
- [wb16_to_wb32](modules/wishbone/wb16_to_wb32) is an adapter from a
16 data bit wishbone master to a 32 data bit wishbone slave. It uses
an intermediate register. Refer to the module for how to use it.
* There are modules for axi4 bus
- [axi4lite32_axi4full64_bridge](modules/axi/axi4lite32_axi4full64_bridge) is
a bridge from axi4full64 to axi4lite32. It was defined to interface with
the Vivado PCI-e bridge and doesn't support all the axi4full features
(in particular the burst accesses).
* There a modules to build a bus hierarchy:
- [wb_bus_fanout](modules/wishbone/wb_bus_fanout) is a simple master to
......@@ -210,3 +231,5 @@ Directory [modules/wishbone](modules/wishbone) contains modules for wishbone.
superseeded by the crossbar.
- [wb_metadata](modules/wishbone/wb_metadata) is a little helper to
create metadata for the convention.
- [wb_indirect](modules/wishbone/wb_indirect) provides a wishbone
master driven by an address and a data registers.
# SPDX-License-Identifier: CC0-1.0
#
# SPDX-FileCopyrightText: 2019 CERN
PREFIX ?= /
GIT_VERSION := $(shell git describe --always --dirty --long --tags)
VERSION := $(shell git describe --tags --abbrev=0 | tr -d 'v')
GCORES_SW := $(GCORES)/software
# SPDX-License-Identifier: CC0-1.0
#
# SPDX-FileCopyrightText: 2019 CERN
rpmbuild
# SPDX-License-Identifier: CC0-1.0
#
# SPDX-FileCopyrightText: 2019 CERN
TOPDIR ?= $(shell pwd)/../
TRTL ?= $(TOPDIR)
include $(TRTL)/common.mk
NAME := general-cores
SPEC_RPM := $(NAME).spec
DEST := rpmbuild
tar-post = \
$(eval tmpdir := $(shell mktemp -d)) \
tar --extract -C $(tmpdir)/ -f $(1) \
$(2)/common.mk && \
sed -e "s,^GIT_VERSION.*$$,GIT_VERSION := "$(GIT_VERSION)"," \
-e "s,^VERSION.*$$,VERSION := "$(VERSION)"," \
-i $(tmpdir)/$(2)/common.mk && \
tar --update -C $(tmpdir) -f $(1) \
$(2)/common.mk && \
rm -rf $(tmpdir)
all: rpmbuild-all
clean: rpmbuild-clean
include rpmbuild.mk
.PHONY: all clean
# SPDX-License-Identifier: GPL-3.0-or-later
#
# SPDX-FileCopyrightText: 2019 CERN
%define project_name general-cores
Summary: General Cores Drivers
Name: dkms-%{project_name}
Version: %{?_build_version}
License: GPL-2.0
Release: 1%{?dist}
URL: https://www.ohwr.org/projects/general-cores/
BuildRequires: make, gcc, git
Requires: dkms
Source0: %{project_name}-%{version}.tar.gz
Source1: CHANGELOG
%description
This package installs all general-cores drivers
%prep
%autosetup -n %{project_name}-%{version}
%build
%install
make -C software PREFIX=%{buildroot}/ -f dkms.mk dkms_install
%post
dkms add -m %{project_name} -v %{version} --rpm_safe_upgrade
dkms build -m %{project_name} -v %{version} --rpm_safe_upgrade
dkms install -m %{project_name} -v %{version} --rpm_safe_upgrade
%preun
dkms remove -m %{project_name} -v %{version} --rpm_safe_upgrade --all ||:
%files
%license LICENSES/CC0-1.0.txt
%license LICENSES/GPL-2.0.txt
/usr/src/%{project_name}-%{version}/*
%changelog
%include %{SOURCE1}
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2019 CERN
# Author: Federico Vaga <federico.vaga@cern.ch>
#
# Required Project Variables And Functions
#
ifndef TOPDIR
$(error "Define project top-level directory: TOPDIR")
endif
ifndef NAME
$(error "Define project name: NAME")
endif
ifndef VERSION
$(error "Define project version: VERSION")
endif
ifndef SPEC_RPM
$(error "Define RPM spec file: SPEC_RPM")
endif
#
# Internal Variables
#
FULL_NAME := $(NAME)-$(VERSION)
DEST ?= rpmbuild
RPMBUILD := $(shell /bin/pwd)/$(DEST)
SOURCES := $(RPMBUILD)/SOURCES
SRC_TAR := $(SOURCES)/$(FULL_NAME).tar
SRC_TAR_GZ := $(SOURCES)/$(FULL_NAME).tar.gz
CHANGELOG := $(SOURCES)/CHANGELOG
SPEC := $(RPMBUILD)/SPECS/$(FULL_NAME).spec
#
# Requirements
# - git (if this is a git repository)
#
GIT ?= git
ifeq (,$(shell which $(GIT)))
$(error "The tool 'git' is required to process '$@'")
endif
#
# Targets
#
# Prepare working directories
$(RPMBUILD):
@mkdir -p $@/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
# Build a tar with all sources with the assumption that sources
# are handled with a git repository. Otherwise, rewrite this rule
# in order to get get a clean tar.
$(SRC_TAR): $(RPMBUILD)
@cd $(TOPDIR) && \
$(GIT) archive --format=tar -o $@ --prefix=$(FULL_NAME)/ HEAD
ifdef tar-post
# Extra processing on the tar file.
# Modify this target according to project needs, if you do not use git-archive
# then do everything right while you are building your tar file
$(warning "Post processing tar file")
@$(call tar-post,$@,$(FULL_NAME))
endif
# Compress sources (optional)
$(SRC_TAR_GZ): $(SRC_TAR) $(RPMBUILD)
@rm -f $@ # remove any previous archive
@gzip $<
# Create an RPM compatible CHANGELOG from the project format
# (see https://keepachangelog.com/en/1.0.0/)
$(CHANGELOG): $(SRC_TAR_GZ)
$(eval $@_pattern := ^\[([0-9]+\.[0-9]+\.[0-9]+)\]\s-\s([0-9]{4}-[0-9]{2}-[0-9]{2})$)
$(eval $@_replace := echo -e "\n"\\* `date --date="\2" "+%a %b %d %Y"` "\1")
@tar -C $(SOURCES) -xf $< $(FULL_NAME)/CHANGELOG.rst
@mv $(SOURCES)/$(FULL_NAME)/CHANGELOG.rst $(CHANGELOG)
@rmdir $(SOURCES)/$(FULL_NAME)
@sed -r -i -e "1,+10d" -e "/^(=|-|\s)*$$/d" $(CHANGELOG)
@sed -r -i -e 's,$($@_pattern),$($@_replace),e' $(CHANGELOG)
# Put all necessary sources in the source directory
sources: $(SRC_TAR_GZ) $(CHANGELOG) $(RPMBUILD)
# Build the RPM spec file to embed in the .src.rpm file for a specific version
$(SPEC): $(SPEC_RPM) $(RPMBUILD)
@cp $< $@
@sed -i -e "s/%{?_build_version}/$(VERSION)/" $@
# rpmbuild targets
rpmbuild: $(SPEC) sources $(RPMBUILD)
rpmbuild-source: rpmbuild
@rpmbuild -bs --define "_topdir $(RPMBUILD)" $(SPEC)
rpmbuild-binary: rpmbuild
@rpmbuild -bb --define "_topdir $(RPMBUILD)" $(SPEC)
rpmbuild-all: rpmbuild
@rpmbuild -ba --define "_topdir $(RPMBUILD)" $(SPEC)
rpmbuild-clean:
@rm -rf $(RPMBUILD)
.PHONY: srpm sources $(SRC_TAR_GZ) $(SRC_TAR) $(CHANGELOG) $(SPEC)
modules = { "local" : [
"z7_axi_gpio_expander",
"axi4lite_wb_bridge",
"axi4lite32_axi4full64_bridge",
]}
files = [
......
files = [
"axi4lite32_axi4full64_bridge.vhd",
];
......@@ -11,6 +11,11 @@ files = [
"gc_serial_dac.vhd",
"gc_sync_ffs.vhd",
"gc_arbitrated_mux.vhd",
"gc_sync_register.vhd",
"gc_sync.vhd",
"gc_posedge.vhd",
"gc_negedge.vhd",
"gc_edge_detect.vhd",
"gc_pulse_synchronizer.vhd",
"gc_pulse_synchronizer2.vhd",
"gc_frequency_meter.vhd",
......@@ -19,13 +24,13 @@ files = [
"gc_prio_encoder.vhd",
"gc_word_packer.vhd",
"gc_i2c_slave.vhd",
"gc_simple_spi_master.vhd",
"gc_glitch_filt.vhd",
"gc_dyn_glitch_filt.vhd",
"gc_comparator.vhd",
"gc_big_adder.vhd",
"gc_fsm_watchdog.vhd",
"gc_bicolor_led_ctrl.vhd",
"gc_sync_register.vhd",
"gc_single_reset_gen.vhd",
"gc_async_signals_input_stage.vhd",
"gc_dyn_extend_pulse.vhd",
......
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: gc_edge_detect
--
-- description: Simple edge detector. Combinatorial.
--
--------------------------------------------------------------------------------
-- 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;
entity gc_edge_detect is
generic(
g_ASYNC_RST : boolean := FALSE;
-- Positive/negative edge detection for pulse_o output.
-- Valid values are "positive" and "negative".
g_PULSE_EDGE : string := "positive";
-- Clock edge sensitivity of edge detection flip-flop.
-- Valid values are "positive" and "negative".
g_CLOCK_EDGE : string := "positive");
port(
clk_i : in std_logic; -- clock
rst_n_i : in std_logic; -- reset
data_i : in std_logic; -- input
pulse_o : out std_logic); -- positive edge detect output
end entity gc_edge_detect;
architecture arch of gc_edge_detect is
signal dff : std_logic;
begin
assert g_PULSE_EDGE = "positive" or g_PULSE_EDGE = "negative" severity FAILURE;
assert g_CLOCK_EDGE = "positive" or g_CLOCK_EDGE = "negative" severity FAILURE;
gen_pos_pulse : if g_PULSE_EDGE = "positive" generate
pulse_o <= data_i and not dff;
end generate gen_pos_pulse;
gen_neg_pulse : if g_PULSE_EDGE = "negative" generate
pulse_o <= not data_i and dff;
end generate gen_neg_pulse;
gen_async_rst : if g_ASYNC_RST = TRUE generate
sync_posedge : if g_CLOCK_EDGE = "positive" generate
process (clk_i, rst_n_i)
begin
if rst_n_i = '0' then
dff <= '0';
elsif rising_edge (clk_i) then
dff <= data_i;
end if;
end process;
end generate sync_posedge;
sync_negedge : if g_CLOCK_EDGE = "negative" generate
process (clk_i, rst_n_i)
begin
if rst_n_i = '0' then
dff <= '0';
elsif falling_edge (clk_i) then
dff <= data_i;
end if;
end process;
end generate sync_negedge;
end generate gen_async_rst;
gen_sync_rst : if g_ASYNC_RST = FALSE generate
sync_posedge : if g_CLOCK_EDGE = "positive" generate
process (clk_i)
begin
if rising_edge (clk_i) then
if rst_n_i = '0' then
dff <= '0';
else
dff <= data_i;
end if;
end if;
end process;
end generate sync_posedge;
sync_negedge : if g_CLOCK_EDGE = "negative" generate
process (clk_i)
begin
if falling_edge (clk_i) then
if rst_n_i = '0' then
dff <= '0';
else
dff <= data_i;
end if;
end if;
end process;
end generate sync_negedge;
end generate gen_sync_rst;
end architecture arch;
This diff is collapsed.
......@@ -6,7 +6,7 @@
-- Author : Tomasz Wlostowski
-- Company : CERN
-- Created : 2009-09-01
-- Last update: 2012-06-19
-- Last update: 2020-03-30
-- Platform : FPGA-generic
-- Standard : VHDL '93
-------------------------------------------------------------------------------
......@@ -41,7 +41,6 @@ use ieee.NUMERIC_STD.all;
library work;
use work.gencores_pkg.all;
use work.genram_pkg.all;
entity gc_extend_pulse is
......@@ -60,7 +59,7 @@ end gc_extend_pulse;
architecture rtl of gc_extend_pulse is
signal cntr : unsigned(f_log2_size(g_width)-1 downto 0);
signal cntr : unsigned(f_log2_ceil(g_width)-1 downto 0);
signal extended_int : std_logic;
begin -- rtl
......
......@@ -22,6 +22,21 @@
-- and limitations under the License.
--------------------------------------------------------------------------------
-- Principle of operation:
--
-- This block counts the number of pulses on CLK_IN_I during a period.
-- At the end of the period, the value is saved and the counter reset.
-- The saved value is available on FREQ_O, which is synchronized with
-- CLK_SYS_I if G_SYNC_OUT is True.
-- The width of the counter is defined by G_COUNTER_BITS.
--
-- - If g_WITH_INTERNAL_TIMEBASE is True:
-- The period is defined by an internal counter that generates a pulse
-- every G_CLK_SYS_FREQ CLK_SYS_I ticks.
--
-- - If g_WITH_INTERNAL_TIMEBASE is False:
-- The period is defined by PPS_P1_I
library ieee;
use ieee.std_logic_1164.all;
......
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: gc_negedge
--
-- description: Simple falling edge detector. Combinatorial.
--
--------------------------------------------------------------------------------
-- 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;
entity gc_negedge is
generic(
g_ASYNC_RST : boolean := FALSE;
-- Clock edge sensitivity of edge detection flip-flop.
-- Valid values are "positive" and "negative".
g_CLOCK_EDGE : string := "positive");
port(
clk_i : in std_logic; -- clock
rst_n_i : in std_logic; -- reset
data_i : in std_logic; -- input
pulse_o : out std_logic); -- falling edge detect output
end entity gc_negedge;
architecture arch of gc_negedge is
begin
inst_gc_edge_detect : entity work.gc_edge_detect
generic map (
g_ASYNC_RST => g_ASYNC_RST,
g_PULSE_EDGE => "negative",
g_CLOCK_EDGE => g_CLOCK_EDGE)
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
data_i => data_i,
pulse_o => pulse_o);
end architecture arch;
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: gc_posedge
--
-- description: Simple rising edge detector. Combinatorial.
--
--------------------------------------------------------------------------------
-- 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;
entity gc_posedge is
generic(
g_ASYNC_RST : boolean := FALSE;
-- Clock edge sensitivity of edge detection flip-flop.
-- Valid values are "positive" and "negative".
g_CLOCK_EDGE : string := "positive");
port(
clk_i : in std_logic; -- clock
rst_n_i : in std_logic; -- reset
data_i : in std_logic; -- input
pulse_o : out std_logic); -- positive edge detect output
end entity gc_posedge;
architecture arch of gc_posedge is
begin
inst_gc_edge_detect : entity work.gc_edge_detect
generic map (
g_ASYNC_RST => g_ASYNC_RST,
g_PULSE_EDGE => "positive",
g_CLOCK_EDGE => g_CLOCK_EDGE)
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
data_i => data_i,
pulse_o => pulse_o);
end architecture arch;
......@@ -40,9 +40,10 @@ entity gc_pulse_synchronizer2 is
-- pulse input ready (clk_in_i domain). When HI, a pulse
-- coming to d_p_i will be correctly transferred to q_p_o.
d_ready_o : out std_logic;
-- last pulse input acknowledged. This is an alternative
-- status flag to d_ready_o for applications that work better
-- with a pulsed ACK instead of a "ready" flag.
-- last pulse input acknowledged (clk_in_i domain).
-- This is an alternative status flag to d_ready_o for
-- applications that work better with a pulsed ACK
-- instead of a "ready" flag.
d_ack_p_o : out std_logic;
-- pulse input (clk_in_i domain)
d_p_i : in std_logic;
......@@ -63,23 +64,27 @@ architecture rtl of gc_pulse_synchronizer2 is
begin -- rtl
cmp_in2out_sync : gc_sync_ffs
cmp_in2out_sync : gc_sync
port map (
clk_i => clk_out_i,
rst_n_i => rst_out_n_i,
data_i => in_ext,
synced_o => out_ext,
npulse_o => open,
ppulse_o => q_p_o);
cmp_out2in_sync : gc_sync_ffs
clk_i => clk_out_i,
rst_n_a_i => rst_out_n_i,
d_i => in_ext,
q_o => out_ext);
cmp_pulse_out : gc_edge_detect
port map (
clk_i => clk_out_i,
rst_n_i => rst_out_n_i,
data_i => out_ext,
pulse_o => q_p_o);
cmp_out2in_sync : gc_sync
port map (
clk_i => clk_in_i,
rst_n_i => rst_in_n_i,
data_i => out_ext,
synced_o => out_feedback,
npulse_o => open,
ppulse_o => open);
clk_i => clk_in_i,
rst_n_a_i => rst_in_n_i,
d_i => out_ext,
q_o => out_feedback);
p_input_ack : process(clk_in_i)
begin
......@@ -89,12 +94,18 @@ begin -- rtl
d_ack_d0 <= d_ack;
if ready = '1' and d_p_i = '1' and d_p_d0 = '0'then
-- Incoming pulse detected and the system is ready.
-- Transfer it.
in_ext <= '1';
-- Clear ack and ready!
d_ack <= '0';
ready <= '0';
elsif in_ext = '1' and out_feedback = '1' then
-- Pulse has been transfered, clear the input.
in_ext <= '0';
elsif in_ext = '0' and out_feedback = '0' then
-- Clear transfered. Done.
-- This is also the steady state.
d_ack <= '1';
ready <= '1';
end if;
......
-----------------------------------------------------------------------------
-- Title : SPI Bus Master
-- Project : Simple VME64x FMC Carrier (SVEC)
-------------------------------------------------------------------------------
-- File : gc_simple_spi_master.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN
-- Created : 2011-08-24
-- Last update: 2013-01-25
-- Platform : FPGA-generic
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: Just a simple SPI master (bus-less).
-------------------------------------------------------------------------------
--
-- Copyright (c) 2011-2013 CERN / BE-CO-HT
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE. See the GNU Lesser General Public License for more
-- details.
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity gc_simple_spi_master is
generic(
-- clock division ratio (SCLK = clk_sys_i / (2 ** g_div_ratio_log2).
g_div_ratio_log2 : integer := 2;
-- number of data bits per transfer
g_num_data_bits : integer := 2);
port (
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
-- state of the Chip select line (1 = CS active). External control
-- allows for multi-transfer commands (SPI master itself does not
-- control the state of spi_cs_n_o)
cs_i : in std_logic;
-- 1: start next transfer (using CPOL, DATA and SEL from the inputs below)
start_i : in std_logic;
-- Clock polarity: 1: slave clocks in the data on rising SCLK edge, 0: ...
-- on falling SCLK edge
cpol_i : in std_logic;
-- TX Data input
data_i : in std_logic_vector(g_num_data_bits - 1 downto 0);
-- 1: data_o contains the result of last read operation. Core is ready to initiate
-- another transfer.
ready_o : out std_logic;
-- data read from selected slave, valid when ready_o == 1.
data_o : out std_logic_vector(g_num_data_bits - 1 downto 0);
-- these are obvious
spi_cs_n_o : out std_logic;
spi_sclk_o : out std_logic;
spi_mosi_o : out std_logic;
spi_miso_i : in std_logic
);
end gc_simple_spi_master;
architecture behavioral of gc_simple_spi_master is
signal divider : unsigned(11 downto 0);
signal tick : std_logic;
signal sreg : std_logic_vector(g_num_data_bits-1 downto 0);
signal rx_sreg : std_logic_vector(g_num_data_bits-1 downto 0);
type t_state is (IDLE, TX_CS, TX_DAT1, TX_DAT2, TX_SCK1, TX_SCK2, TX_CS2, TX_GAP);
signal state : t_state;
signal sclk : std_logic;
signal counter : unsigned(4 downto 0);
begin -- rtl
-- Simple clock divder. Produces a 'tick' signal which defines the timing for
-- the main state machine transitions.
p_divide_spi_clock: process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
divider <= (others => '0');
else
if(start_i = '1' or tick = '1') then
divider <= (others => '0');
else
divider <= divider + 1;
end if;
end if;
end if;
end process;
tick <= divider(g_div_ratio_log2);
-- Main state machine. Executes SPI transfers
p_main_fsm: process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
state <= IDLE;
sclk <= '0';
sreg <= (others => '0');
rx_sreg <= (others => '0');
spi_mosi_o <= '0';
counter <= (others => '0');
else
case state is
-- Waits for start of transfer command
when IDLE =>
sclk <= '0';
counter <= (others => '0');
if(start_i = '1') then
sreg <= data_i;
state <= TX_CS;
spi_mosi_o <= data_i(sreg'high);
end if;
-- Generates a gap between the externally asserted Chip Select and
-- the beginning of data transfer
when TX_CS =>
if tick = '1' then
state <= TX_DAT1;
end if;
-- Outputs subsequent bits to MOSI line.
when TX_DAT1 =>
if(tick = '1') then
spi_mosi_o <= sreg(sreg'high);
sreg <= sreg(sreg'high-1 downto 0) & '0';
state <= TX_SCK1;
end if;
-- Flips the SCLK (active edge)
when TX_SCK1 =>
if(tick = '1') then
sclk <= not sclk;
counter <= counter + 1;
state <= TX_DAT2;
end if;
-- Shifts in bits read from the slave
when TX_DAT2 =>
if(tick = '1') then
rx_sreg <= rx_sreg(rx_sreg'high-1 downto 0) & spi_miso_i;
state <= TX_SCK2;
end if;
-- Flips the SCLK (inactive edge). Checks if all bits have been
-- transferred.
when TX_SCK2 =>
if(tick = '1') then
sclk <= not sclk;
if(counter = g_num_data_bits) then
state <= TX_CS2;
else
state <= TX_DAT1;
end if;
end if;
-- Generates a gap for de-assertoin of CS line
when TX_CS2 =>
if(tick = '1') then
state <= TX_GAP;
data_o <= rx_sreg;
end if;
when TX_GAP =>
if (tick = '1') then
state <= IDLE;
end if;
end case;
end if;
end if;
end process;
ready_o <= '1' when (state = IDLE and start_i = '0') else '0';
-- SCLK polarity control
spi_sclk_o <= sclk xor cpol_i;
spi_cs_n_o <= not cs_i;
end behavioral;
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- General Cores Library
-- https://www.ohwr.org/projects/general-cores
--------------------------------------------------------------------------------
--
-- unit name: gc_sync
--
-- description: Elementary synchronizer chain using two flip-flops.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2014-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;
entity gc_sync is
generic(
-- valid values are "positive" and "negative"
g_SYNC_EDGE : string := "positive");
port (
clk_i : in std_logic;
rst_n_a_i : in std_logic;
d_i : in std_logic;
q_o : out std_logic);
end gc_sync;
-- make Altera Quartus quiet regarding unknown attributes:
-- altera message_off 10335
architecture arch of gc_sync is
-- Use an intermediate signal with a particular name and a keep attribute
-- so that it can be referenced in the constraints in order to ignore
-- timing (TIG) on that signal.
signal gc_sync_ffs_in : std_logic;
signal sync0, sync1 : std_logic;
attribute rloc : string;
attribute rloc of sync0 : signal is "X0Y0";
attribute rloc of sync1 : signal is "X0Y0";
attribute shreg_extract : string;
attribute shreg_extract of sync0 : signal is "no";
attribute shreg_extract of sync1 : signal is "no";
attribute keep : string;
attribute keep of gc_sync_ffs_in : signal is "true";
attribute keep of sync0 : signal is "true";
attribute keep of sync1 : signal is "true";
attribute keep_hierarchy : string;
attribute keep_hierarchy of arch : architecture is "true";
attribute async_reg : string;
attribute async_reg of sync0 : signal is "true";
attribute async_reg of sync1 : signal is "true";
begin
assert g_SYNC_EDGE = "positive" or g_SYNC_EDGE = "negative" severity failure;
gc_sync_ffs_in <= d_i;
sync_posedge : if (g_SYNC_EDGE = "positive") generate
process(clk_i, rst_n_a_i)
begin
if rst_n_a_i = '0' then
sync1 <= '0';
sync0 <= '0';
elsif rising_edge(clk_i) then
sync0 <= gc_sync_ffs_in;
sync1 <= sync0;
end if;
end process;
end generate sync_posedge;
sync_negedge : if(g_SYNC_EDGE = "negative") generate
process(clk_i, rst_n_a_i)
begin
if rst_n_a_i = '0' then
sync1 <= '0';
sync0 <= '0';
elsif falling_edge(clk_i) then
sync0 <= gc_sync_ffs_in;
sync1 <= sync0;
end if;
end process;
end generate sync_negedge;
q_o <= sync1;
end arch;
......@@ -10,7 +10,7 @@
-- All the registers in the chain are cleared at reset.
--
--------------------------------------------------------------------------------
-- Copyright CERN 2010-2018
-- Copyright CERN 2010-2020
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
......@@ -28,90 +28,80 @@ use ieee.std_logic_1164.all;
entity gc_sync_ffs is
generic(
g_sync_edge : string := "positive");
-- valid values are "positive" and "negative"
g_SYNC_EDGE : string := "positive");
port(
clk_i : in std_logic; -- clock from the destination clock domain
rst_n_i : in std_logic; -- reset
rst_n_i : in std_logic; -- async reset
data_i : in std_logic; -- async input
synced_o : out std_logic; -- synchronized output
npulse_o : out std_logic; -- negative edge detect output
ppulse_o : out std_logic); -- positive edge detect output
end entity gc_sync_ffs;
-- make Altera Quartus quiet regarding unknown attributes:
-- altera message_off 10335
architecture arch of gc_sync_ffs is
signal sync0, sync1, sync2 : std_logic;
signal gc_sync_ffs_in : std_logic;
attribute shreg_extract : string;
attribute shreg_extract of sync0 : signal is "no";
attribute shreg_extract of sync1 : signal is "no";
attribute shreg_extract of sync2 : signal is "no";
attribute keep : string;
attribute keep of sync0 : signal is "true";
attribute keep of sync1 : signal is "true";
attribute rloc : string;
attribute rloc of sync0 : signal is "X0Y0";
attribute rloc of sync1 : signal is "X0Y0";
attribute keep of gc_sync_ffs_in : signal is "true";
-- synchronizer attribute for Vivado
attribute ASYNC_REG : string;
attribute ASYNC_REG of sync0 : signal is "true";
attribute ASYNC_REG of sync1 : signal is "true";
attribute ASYNC_REG of sync2 : signal is "true";
signal sync, npulse, ppulse : std_logic;
begin
-- rename data_i to something we can use as wildcard
-- in timing constraints
gc_sync_ffs_in <= data_i;
sync_posedge : if (g_sync_edge = "positive") generate
cmp_gc_sync : entity work.gc_sync
generic map (
g_SYNC_EDGE => g_SYNC_EDGE)
port map (
clk_i => clk_i,
rst_n_a_i => rst_n_i,
d_i => data_i,
q_o => sync);
cmp_gc_posedge : entity work.gc_edge_detect
generic map (
g_ASYNC_RST => TRUE,
g_PULSE_EDGE => "positive",
g_CLOCK_EDGE => g_SYNC_EDGE)
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
data_i => sync,
pulse_o => ppulse);
cmp_gc_negedge : entity work.gc_edge_detect
generic map (
g_ASYNC_RST => TRUE,
g_PULSE_EDGE => "negative",
g_CLOCK_EDGE => g_SYNC_EDGE)
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
data_i => sync,
pulse_o => npulse);
sync_posedge : if (g_SYNC_EDGE = "positive") generate
process(clk_i, rst_n_i)
begin
if(rst_n_i = '0') then
sync0 <= '0';
sync1 <= '0';
sync2 <= '0';
synced_o <= '0';
npulse_o <= '0';
ppulse_o <= '0';
elsif rising_edge(clk_i) then
sync0 <= gc_sync_ffs_in;
sync1 <= sync0;
sync2 <= sync1;
synced_o <= sync1;
npulse_o <= sync2 and not sync1;
ppulse_o <= not sync2 and sync1;
synced_o <= sync;
npulse_o <= npulse;
ppulse_o <= ppulse;
end if;
end process;
end generate sync_posedge;
sync_negedge : if(g_sync_edge = "negative") generate
sync_negedge : if(g_SYNC_EDGE = "negative") generate
process(clk_i, rst_n_i)
begin
if(rst_n_i = '0') then
sync0 <= '0';
sync1 <= '0';
sync2 <= '0';
synced_o <= '0';
npulse_o <= '0';
ppulse_o <= '0';
elsif falling_edge(clk_i) then
sync0 <= gc_sync_ffs_in;
sync1 <= sync0;
sync2 <= sync1;
synced_o <= sync1;
npulse_o <= sync2 and not sync1;
ppulse_o <= not sync2 and sync1;
synced_o <= sync;
npulse_o <= npulse;
ppulse_o <= ppulse;
end if;
end process;
end generate sync_negedge;
......
......@@ -53,7 +53,10 @@ architecture rtl of gc_sync_register is
attribute keep of gc_sync_register_in : signal is "true";
attribute keep of sync0 : signal is "true";
attribute keep of sync1 : signal is "true";
attribute keep_hierarchy : string;
attribute keep_hierarchy of rtl : architecture is "true";
attribute async_reg : string;
attribute async_reg of gc_sync_register_in : signal is "true";
attribute async_reg of sync0 : signal is "true";
......
......@@ -37,7 +37,7 @@ use work.gencores_pkg.all;
entity gc_sync_word_wr is
generic (
-- automatically write next word when not busy
-- Automatically write next word when not busy.
g_AUTO_WR : boolean := FALSE;
g_WIDTH : positive := 8);
port (
......@@ -47,16 +47,18 @@ entity gc_sync_word_wr is
-- Output clock and reset
clk_out_i : in std_logic;
rst_out_n_i : in std_logic;
-- Input data
-- Input data (from clk_in_i domain)
data_i : in std_logic_vector (g_WIDTH - 1 downto 0);
-- Input control and status
-- Input control (from clk_in_i domain)
-- wr_i is ignored if g_AUTO_WR is set
wr_i : in std_logic := '0';
-- Transfer in progress (clk_in_i domain).
busy_o : out std_logic;
-- Input wr_i has been used (clk_in_i domain).
ack_o : out std_logic;
-- Output data
data_o : out std_logic_vector (g_WIDTH - 1 downto 0);
-- Output status
-- Output status. Pulse set when the data has been transfered (clk_out_i domain).
wr_o : out std_logic);
end entity;
......
......@@ -27,10 +27,60 @@ library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.genram_pkg.all;
package gencores_pkg is
--============================================================================
-- Procedures and functions
--============================================================================
procedure f_rr_arbitrate (
signal req : in std_logic_vector;
signal pre_grant : in std_logic_vector;
signal grant : out std_logic_vector);
function f_onehot_decode(x : std_logic_vector; size : integer) return std_logic_vector;
function f_big_ripple(a, b : std_logic_vector; c : std_logic) return std_logic_vector;
function f_gray_encode(x : std_logic_vector) return std_logic_vector;
function f_gray_decode(x : std_logic_vector; step : natural) return std_logic_vector;
function f_log2_ceil(N : natural) return positive;
-- kept for backwards compatibility, same as f_log2_ceil()
function log2_ceil(N : natural) return positive;
function f_bool2int (b : boolean) return natural;
function f_int2bool (n : natural) return boolean;
-- Convert a boolean to std_logic ('1' for True, '0' for False).
function f_to_std_logic(b : boolean) return std_logic;
-- Reduce-OR an std_logic_vector to std_logic
function f_reduce_or (x : std_logic_vector) return std_logic;
-- Character/String to std_logic_vector
function f_to_std_logic_vector (c : character) return std_logic_vector;
function f_to_std_logic_vector (s : string) return std_logic_vector;
-- Functions for short-hand if assignments
function f_pick (cond : boolean; if_1 : std_logic; if_0 : std_logic)
return std_logic;
function f_pick (cond : boolean; if_1 : std_logic_vector; if_0 : std_logic_vector)
return std_logic_vector;
function f_pick (cond : std_logic; if_1 : std_logic; if_0 : std_logic)
return std_logic;
function f_pick (cond : std_logic; if_1 : std_logic_vector; if_0 : std_logic_vector)
return std_logic_vector;
-- Functions to convert characters and strings to upper/lower case
function to_upper(c : character) return character;
function to_lower(c : character) return character;
function to_upper(s : string) return string;
function to_lower(s : string) return string;
-- Bit reversal function
function f_reverse_vector (a : in std_logic_vector) return std_logic_vector;
--============================================================================
-- Component instantiations
--============================================================================
......@@ -188,7 +238,7 @@ package gencores_pkg is
------------------------------------------------------------------------------
component gc_sync_ffs
generic (
g_sync_edge : string := "positive");
g_SYNC_EDGE : string := "positive");
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
......@@ -196,7 +246,54 @@ package gencores_pkg is
synced_o : out std_logic;
npulse_o : out std_logic;
ppulse_o : out std_logic);
end component;
end component gc_sync_ffs;
component gc_sync is
generic (
g_SYNC_EDGE : string := "positive");
port (
clk_i : in std_logic;
rst_n_a_i : in std_logic;
d_i : in std_logic;
q_o : out std_logic);
end component gc_sync;
------------------------------------------------------------------------------
-- Edge detectors
------------------------------------------------------------------------------
component gc_edge_detect is
generic (
g_ASYNC_RST : boolean := FALSE;
g_PULSE_EDGE : string := "positive";
g_CLOCK_EDGE : string := "positive");
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
data_i : in std_logic;
pulse_o : out std_logic);
end component gc_edge_detect;
component gc_negedge is
generic (
g_ASYNC_RST : boolean := FALSE;
g_CLOCK_EDGE : string := "positive");
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
data_i : in std_logic;
pulse_o : out std_logic);
end component gc_negedge;
component gc_posedge is
generic (
g_ASYNC_RST : boolean := FALSE;
g_CLOCK_EDGE : string := "positive");
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
data_i : in std_logic;
pulse_o : out std_logic);
end component gc_posedge;
------------------------------------------------------------------------------
-- Pulse synchroniser
......@@ -295,7 +392,7 @@ package gencores_pkg is
d_req_o : out std_logic_vector(g_num_inputs-1 downto 0);
q_o : out std_logic_vector(g_width-1 downto 0);
q_valid_o : out std_logic;
q_input_id_o : out std_logic_vector(f_log2_size(g_num_inputs)-1 downto 0));
q_input_id_o : out std_logic_vector(f_log2_ceil(g_num_inputs)-1 downto 0));
end component;
------------------------------------------------------------------------------
......@@ -690,42 +787,6 @@ package gencores_pkg is
counter_o : out std_logic_vector(g_bits downto 0));
end component gc_async_counter_diff;
--============================================================================
-- Procedures and functions
--============================================================================
procedure f_rr_arbitrate (
signal req : in std_logic_vector;
signal pre_grant : in std_logic_vector;
signal grant : out std_logic_vector);
function f_onehot_decode(x : std_logic_vector; size : integer) return std_logic_vector;
function f_big_ripple(a, b : std_logic_vector; c : std_logic) return std_logic_vector;
function f_gray_encode(x : std_logic_vector) return std_logic_vector;
function f_gray_decode(x : std_logic_vector; step : natural) return std_logic_vector;
function log2_ceil(N : natural) return positive;
function f_bool2int (b : boolean) return natural;
function f_int2bool (n : natural) return boolean;
-- Convert a boolean to std_logic ('1' for True, '0' for False).
function f_to_std_logic(b : boolean) return std_logic;
-- Reduce-OR an std_logic_vector to std_logic
function f_reduce_or (x : std_logic_vector) return std_logic;
-- Character/String to std_logic_vector
function f_to_std_logic_vector (c : character) return std_logic_vector;
function f_to_std_logic_vector (s : string) return std_logic_vector;
-- Functions for short-hand if assignments
function f_pick (cond : boolean; if_1 : std_logic; if_0 : std_logic)
return std_logic;
function f_pick (cond : boolean; if_1 : std_logic_vector; if_0 : std_logic_vector)
return std_logic_vector;
function f_pick (cond : std_logic; if_1 : std_logic; if_0 : std_logic)
return std_logic;
function f_pick (cond : std_logic; if_1 : std_logic_vector; if_0 : std_logic_vector)
return std_logic_vector;
end package;
package body gencores_pkg is
......@@ -827,17 +888,22 @@ package body gencores_pkg is
------------------------------------------------------------------------------
-- Returns log of 2 of a natural number
------------------------------------------------------------------------------
function log2_ceil(N : natural) return positive is
function f_log2_ceil(N : natural) return positive is
begin
if N <= 2 then
return 1;
elsif N mod 2 = 0 then
return 1 + log2_ceil(N/2);
return 1 + f_log2_ceil(N/2);
else
return 1 + log2_ceil((N+1)/2);
return 1 + f_log2_ceil((N+1)/2);
end if;
end;
-- kept for backwards compatibility
function log2_ceil(N : natural) return positive is
begin
return f_log2_ceil(N);
end;
------------------------------------------------------------------------------
-- Converts a boolean to natural integer (false -> 0, true -> 1)
......@@ -954,4 +1020,59 @@ package body gencores_pkg is
return f_pick (f_to_std_logic(cond), if_1, if_0);
end function f_pick;
------------------------------------------------------------------------------
-- Functions to convert characters and strings to upper/lower case
------------------------------------------------------------------------------
function to_upper(c : character) return character is
variable i : integer;
begin
i := character'pos(c);
if (i > 96 and i < 123) then
i := i - 32;
end if;
return character'val(i);
end function to_upper;
function to_lower(c : character) return character is
variable i : integer;
begin
i := character'pos(c);
if (i > 64 and i < 91) then
i := i + 32;
end if;
return character'val(i);
end function to_lower;
function to_upper(s : string) return string is
variable uppercase : string (s'range);
begin
for i in s'range loop
uppercase(i) := to_upper(s(i));
end loop;
return uppercase;
end to_upper;
function to_lower(s : string) return string is
variable lowercase : string (s'range);
begin
for i in s'range loop
lowercase(i) := to_lower(s(i));
end loop;
return lowercase;
end to_lower;
------------------------------------------------------------------------------
-- Vector bit reversal
------------------------------------------------------------------------------
function f_reverse_vector (a : in std_logic_vector) return std_logic_vector is
variable v_result : std_logic_vector(a'reverse_range);
begin
for i in a'range loop
v_result(i) := a(i);
end loop;
return v_result;
end function f_reverse_vector;
end gencores_pkg;
files = [
"genram_pkg.vhd",
"memory_loader_pkg.vhd"];
# Be sure 'target' is defined.
try:
target
except NameError:
target = ""
if (target == "altera"):
modules = {"local" : ["altera", "generic", "common"]}
elif (target == "xilinx" and syn_device[0:4].upper()=="XC6V"):
modules = {"local" : ["xilinx", "xilinx/virtex6", "common"]}
elif (target == "xilinx"):
modules = {"local" : ["xilinx", "generic", "common"]}
# Target specific modules.
if target == "altera":
modules = {"local": ["altera", "generic"]}
elif target == "xilinx":
if syn_device[0:4].upper()=="XC6V":
modules = {"local": ["xilinx", "xilinx/virtex6"]}
else:
modules = {"local": ["xilinx", "generic"]}
else:
modules = {"local" : ["generic", "common"]}
modules = {"local" : ["generic"]}
modules["local"].extend(["common", "cheby"])
......@@ -43,8 +43,8 @@ entity generic_dpram is
g_with_byte_enable : boolean := false;
g_addr_conflict_resolution : string := "dont_care";
g_init_file : string := "none";
g_dual_clock : boolean := true;
g_fail_if_file_not_found : boolean := false);
g_fail_if_file_not_found : boolean := true; -- dummy (exists in Xilinx/generic)
g_dual_clock : boolean := true);
port(
rst_n_i : in std_logic := '1'; -- synchronous reset, active LO
......
files = [
"cheby_pkg.vhd",
"cheby_dpssram.vhd"
]
-------------------------------------------------------------------------------
-- Title : Cheby components
-- Project : General Cores
-------------------------------------------------------------------------------
-- File : cheby_dpssram.vhd
-- Company : CERN
-- Platform : FPGA-generics
-- Standard : VHDL '93
-------------------------------------------------------------------------------
-- Copyright (c) 2020 CERN
--
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 0.51 (the "License") (which enables you, at your option,
-- to treat this file as licensed under the Apache License 2.0); 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-0.51.
-- 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;
-- This entity is instantiated by cheby when a dual-port RAM is used.
-- This is just a wrapper that could be changed by users.
-- The generics only use integers/logic to be compatible with verilog.
entity cheby_dpssram is
generic (
g_data_width : natural := 32;
g_size : natural := 1024;
g_addr_width : natural := 10;
g_dual_clock : std_logic := '1';
g_use_bwsel : std_logic := '1');
port (
clk_a_i : in std_logic;
clk_b_i : in std_logic;
addr_a_i : in std_logic_vector(g_addr_width-1 downto 0);
addr_b_i : in std_logic_vector(g_addr_width-1 downto 0);
data_a_i : in std_logic_vector(g_data_width-1 downto 0);
data_b_i : in std_logic_vector(g_data_width-1 downto 0);
data_a_o : out std_logic_vector(g_data_width-1 downto 0);
data_b_o : out std_logic_vector(g_data_width-1 downto 0);
bwsel_a_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
bwsel_b_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
rd_a_i : in std_logic;
rd_b_i : in std_logic;
wr_a_i : in std_logic;
wr_b_i : in std_logic
);
end cheby_dpssram;
architecture syn of cheby_dpssram is
begin
wrapped_dpram: entity work.generic_dpram
generic map (
g_data_width => g_data_width,
g_size => g_size,
g_with_byte_enable => g_use_bwsel = '1',
g_dual_clock => g_dual_clock = '1')
port map (
rst_n_i => '1',
clka_i => clk_a_i,
bwea_i => bwsel_a_i,
wea_i => wr_a_i,
aa_i => addr_a_i,
da_i => data_a_i,
qa_o => data_a_o,
clkb_i => clk_b_i,
bweb_i => bwsel_b_i,
web_i => wr_b_i,
ab_i => addr_b_i,
db_i => data_b_i,
qb_o => data_b_o);
end syn;
-------------------------------------------------------------------------------
-- Title : Cheby components
-- Project : General Cores
-------------------------------------------------------------------------------
-- File : cheby_pkg.vhd
-- Company : CERN
-- Platform : FPGA-generics
-- Standard : VHDL '93
-------------------------------------------------------------------------------
-- Copyright (c) 2020 CERN
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE. See the GNU Lesser General Public License for more
-- details.
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.gnu.org/licenses/lgpl-2.1.html
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
package cheby_pkg is
component cheby_dpssram
generic (
g_data_width : natural;
g_size : natural;
g_addr_width : natural;
g_dual_clock : std_logic;
g_use_bwsel : std_logic);
port (
clk_a_i : in std_logic;
clk_b_i : in std_logic;
addr_a_i : in std_logic_vector(g_addr_width-1 downto 0);
addr_b_i : in std_logic_vector(g_addr_width-1 downto 0);
data_a_i : in std_logic_vector(g_data_width-1 downto 0);
data_b_i : in std_logic_vector(g_data_width-1 downto 0);
data_a_o : out std_logic_vector(g_data_width-1 downto 0);
data_b_o : out std_logic_vector(g_data_width-1 downto 0);
bwsel_a_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
bwsel_b_i : in std_logic_vector((g_data_width+7)/8-1 downto 0);
rd_a_i : in std_logic;
rd_b_i : in std_logic;
wr_a_i : in std_logic;
wr_b_i : in std_logic);
end component;
end cheby_pkg;
......@@ -83,6 +83,10 @@ entity inferred_async_fifo is
rd_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0)
);
attribute keep_hierarchy : string;
attribute keep_hierarchy of
inferred_async_fifo : entity is "true";
end inferred_async_fifo;
......
......@@ -74,6 +74,10 @@ entity inferred_async_fifo_dual_rst is
rd_count_o : out std_logic_vector(f_log2_size(g_size)-1 downto 0)
);
attribute keep_hierarchy : string;
attribute keep_hierarchy of
inferred_async_fifo_dual_rst : entity is "true";
end inferred_async_fifo_dual_rst;
......
......@@ -12,7 +12,7 @@
-- - configurable full/empty/almost full/almost empty/word count signals
--
--------------------------------------------------------------------------------
-- Copyright CERN 2011-2018
-- Copyright CERN 2011-2020
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
......@@ -38,6 +38,12 @@ entity inferred_sync_fifo is
g_size : natural;
g_show_ahead : boolean := false;
-- Previously, the full flag was asserted at g_size-1 when using g_show_ahead.
-- The new implementation solves this. However, for backward compatibility,
-- the default is to still use the previous behaviour. Set this to false to
-- switch to the new one.
g_show_ahead_legacy_mode : boolean := true;
-- Read-side flag selection
g_with_empty : boolean := true; -- with empty flag
g_with_full : boolean := true; -- with full flag
......@@ -72,18 +78,24 @@ end inferred_sync_fifo;
architecture syn of inferred_sync_fifo is
constant c_pointer_width : integer := f_log2_size(g_size);
signal rd_ptr, wr_ptr, wr_ptr_d0, rd_ptr_muxed : unsigned(c_pointer_width-1 downto 0);
signal usedw : unsigned(c_pointer_width downto 0);
signal full, empty : std_logic;
signal q_int : std_logic_vector(g_data_width-1 downto 0);
signal we_int, rd_int : std_logic;
signal guard_bit : std_logic;
constant c_pointer_width : integer := f_log2_size(g_size);
signal rd_ptr, wr_ptr, rd_ptr_muxed : unsigned(c_pointer_width-1 downto 0);
signal usedw : unsigned(c_pointer_width downto 0);
signal full, empty : std_logic;
signal we_int, rd_int : std_logic;
signal guard_bit : std_logic;
signal q_comb : std_logic_vector(g_data_width-1 downto 0);
begin -- syn
legacy_mode_check: assert g_show_ahead = false or g_show_ahead_legacy_mode = false
report legacy_mode_check'instance_name & ": show-ahead enabled for sync FIFO in " &
"legacy mode. In this mode, the full flag is asserted at g_SIZE-1. if you want the " &
"full flag to be asserted at g_SIZE, then disable g_SHOW_AHEAD_LEGACY_MODE."
severity NOTE;
we_int <= we_i and not full;
rd_int <= rd_i and not empty;
......@@ -135,7 +147,8 @@ begin -- syn
end if;
end process;
gen_comb_flags_showahead : if(g_show_ahead = true) generate
gen_comb_flags_showahead_legacy : if g_show_ahead = true and
g_show_ahead_legacy_mode = true generate
process(clk_i)
begin
......@@ -149,6 +162,34 @@ begin -- syn
end process;
full <= '1' when (wr_ptr + 1 = rd_ptr) else '0';
end generate gen_comb_flags_showahead_legacy;
gen_comb_flags_showahead : if g_show_ahead = true and
g_show_ahead_legacy_mode = false generate
process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
guard_bit <= '0';
empty <= '1';
else
if wr_ptr = rd_ptr_muxed and guard_bit = '0' then
empty <= '1';
else
empty <= '0';
end if;
if(wr_ptr + 1 = rd_ptr and we_int = '1') then
guard_bit <= '1';
elsif(rd_i = '1') then
guard_bit <= '0';
end if;
end if;
end if;
end process;
full <= '1' when (wr_ptr = rd_ptr and guard_bit = '1') else '0';
end generate gen_comb_flags_showahead;
gen_comb_flags : if(g_register_flag_outputs = false and g_show_ahead = false) generate
......
......@@ -12,7 +12,7 @@
-- - configurable full/empty/almost full/almost empty/word count signals
--
--------------------------------------------------------------------------------
-- Copyright CERN 2011-2018
-- Copyright CERN 2011-2020
--------------------------------------------------------------------------------
-- Copyright and related rights are licensed under the Solderpad Hardware
-- License, Version 2.0 (the "License"); you may not use this file except
......@@ -38,15 +38,21 @@ entity generic_sync_fifo is
g_size : natural;
g_show_ahead : boolean := false;
-- Read-side flag selection
-- Previously, the full flag was asserted at g_size-1 when using g_show_ahead.
-- The new implementation solves this. However, for backward compatibility,
-- the default is to still use the previous behaviour. Set this to false to
-- switch to the new one.
g_show_ahead_legacy_mode : boolean := true;
-- Read-side flag selection
g_with_empty : boolean := true; -- with empty flag
g_with_full : boolean := true; -- with full flag
g_with_almost_empty : boolean := false;
g_with_almost_full : boolean := false;
g_with_count : boolean := false; -- with words counter
g_almost_empty_threshold : integer; -- threshold for almost empty flag
g_almost_full_threshold : integer; -- threshold for almost full flag
g_almost_empty_threshold : integer := 0; -- threshold for almost empty flag
g_almost_full_threshold : integer := 0; -- threshold for almost full flag
g_register_flag_outputs : boolean := true
);
......@@ -76,6 +82,7 @@ architecture syn of generic_sync_fifo is
g_data_width : natural;
g_size : natural;
g_show_ahead : boolean;
g_show_ahead_legacy_mode : boolean;
g_with_empty : boolean;
g_with_full : boolean;
g_with_almost_empty : boolean;
......@@ -105,6 +112,7 @@ begin -- syn
g_data_width => g_data_width,
g_size => g_size,
g_show_ahead => g_show_ahead,
g_show_ahead_legacy_mode => g_show_ahead_legacy_mode,
g_with_empty => g_with_empty,
g_with_full => g_with_full,
g_with_almost_empty => g_with_almost_empty,
......
......@@ -26,6 +26,9 @@ library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.gencores_pkg.all;
package genram_pkg is
function f_log2_size (A : natural) return natural;
......@@ -247,13 +250,15 @@ package genram_pkg is
g_data_width : natural;
g_size : natural;
g_show_ahead : boolean := false;
g_show_ahead_legacy_mode : boolean := true;
g_with_empty : boolean := true;
g_with_full : boolean := true;
g_with_almost_empty : boolean := false;
g_with_almost_full : boolean := false;
g_with_count : boolean := false;
g_almost_empty_threshold : integer := 0;
g_almost_full_threshold : integer := 0);
g_almost_full_threshold : integer := 0;
g_register_flag_outputs : boolean := true);
port (
rst_n_i : in std_logic := '1';
clk_i : in std_logic;
......@@ -289,14 +294,10 @@ end genram_pkg;
package body genram_pkg is
-- kept for backwards compatibility
function f_log2_size (A : natural) return natural is
begin
for I in 1 to 64 loop -- Works for up to 64 bits
if (2**I >= A) then
return(I);
end if;
end loop;
return(63);
return f_log2_ceil(A);
end function f_log2_size;
function f_gen_dummy_vec (val : std_logic; size : natural) return std_logic_vector is
......
......@@ -118,17 +118,12 @@ architecture syn of generic_dpram_dualclock is
return false;
-- synthesis translate_on
return true;
end f_is_synthesis;
end f_is_synthesis;
shared variable ram : t_ram_type := f_file_to_ramtype;
signal s_we_a : std_logic_vector(c_num_bytes-1 downto 0);
signal s_ram_in_a : std_logic_vector(g_data_width-1 downto 0);
signal s_we_b : std_logic_vector(c_num_bytes-1 downto 0);
signal s_ram_in_b : std_logic_vector(g_data_width-1 downto 0);
signal clka_int : std_logic;
signal clkb_int : std_logic;
signal wea_rep, web_rep : std_logic_vector(c_num_bytes-1 downto 0);
......@@ -177,7 +172,7 @@ begin
end loop;
end if;
end process;
......@@ -266,6 +261,6 @@ begin
end if;
end process;
end generate gen_without_byte_enable_nochange;
end syn;
......@@ -123,9 +123,7 @@ architecture syn of generic_dpram_sameclock is
shared variable ram : t_ram_type := f_file_to_ramtype;
signal s_we_a : std_logic_vector(c_num_bytes-1 downto 0);
signal s_ram_in_a : std_logic_vector(g_data_width-1 downto 0);
signal s_we_b : std_logic_vector(c_num_bytes-1 downto 0);
signal s_ram_in_b : std_logic_vector(g_data_width-1 downto 0);
signal wea_rep, web_rep : std_logic_vector(c_num_bytes-1 downto 0);
......
modules = { "local" : [
"wb_async_bridge",
"wb_axi4lite_bridge",
......@@ -26,8 +25,11 @@ modules = { "local" : [
"wb_ds182x_readout",
"wb_metadata",
"wb_split",
"wb16_to_wb32",
"wb_indirect",
"wbgen2",
"wbgenplus",
"wb_xc7_fw_update",
]}
files = [
......
--------------------------------------------------------------------------------
-- CERN BE-CO-HT
-- WR2RF_VME core
-- https://ohwr.org/project/vme-rf-wr-bobr
--------------------------------------------------------------------------------
--
-- unit name: wb16_to_wb32
--
-- description: Bridge wishbone data width by using a register for the upper 16
-- bits.
-- In order to atomically read a 32 bit word at address ADDR:
-- * read the 16 LSB word at address ADDR
-- * read the 16 MSB word at address ADDR+2
-- In order to atomically write a 32 bit word at address ADDR:
-- * write the 16 MSB word at address ADDR+2
-- * write the 16 LSB word at address ADDR
--
--------------------------------------------------------------------------------
-- Copyright (c) 2019 CERN (home.cern)
--------------------------------------------------------------------------------
-- 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 work.wishbone_pkg.all;
entity wb16_to_wb32 is
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
wb16_i : in t_wishbone_slave_in;
wb16_o : out t_wishbone_slave_out;
wb32_i : in t_wishbone_master_in;
wb32_o : out t_wishbone_master_out
);
end;
architecture arch of wb16_to_wb32 is
signal datah : std_logic_vector(15 downto 0);
signal stall : std_logic;
signal we : std_logic;
signal ack : std_logic;
begin
wb16_o.stall <= stall or ack;
wb32_o.dat (31 downto 16) <= datah;
wb16_o.rty <= '0';
wb16_o.err <= '0';
wb16_o.ack <= ack;
process (clk_i) is
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
datah <= (others => '0');
stall <= '0';
ack <= '0';
wb32_o.cyc <= '0';
wb32_o.stb <= '0';
else
if stall = '0' then
-- Ready.
ack <= '0';
if wb16_i.stb = '1' and wb16_i.cyc = '1' and ack = '0' then
if wb16_i.adr(1) = '1' then
-- Access to DATAH.
if wb16_i.we = '1' then
-- Write.
if wb16_i.sel(0) = '1' then
datah (7 downto 0) <= wb16_i.dat(7 downto 0);
end if;
if wb16_i.sel(1) = '1' then
datah (15 downto 8) <= wb16_i.dat(15 downto 8);
end if;
else
-- Read
wb16_o.dat(15 downto 0) <= datah;
end if;
ack <= '1';
else
-- Access to the device.
stall <= '1';
we <= wb16_i.we;
wb32_o.cyc <= '1';
wb32_o.stb <= '1';
wb32_o.adr <= wb16_i.adr(31 downto 2) & "00";
wb32_o.dat (15 downto 0) <= wb16_i.dat(15 downto 0);
wb32_o.we <= wb16_i.we;
wb32_o.sel <= "11" & wb16_i.sel (1 downto 0); -- Humm...
end if;
end if;
else
-- Stall = 1, waiting for the answer.
if wb32_i.ack = '1' then
wb16_o.dat (15 downto 0) <= wb32_i.dat (15 downto 0);
if we = '0' then
datah <= wb32_i.dat (31 downto 16);
end if;
wb32_o.cyc <= '0';
wb32_o.stb <= '0';
ack <= '1';
stall <= '0';
end if;
end if;
end if;
end if;
end process;
end arch;
......@@ -157,7 +157,7 @@ architecture structural of i2c_master_top is
signal sr : std_logic_vector(7 downto 0); -- status register
-- internal reset signal
signal rst_i : std_logic;
signal arst_n : std_logic;
-- wishbone write access
signal wb_wacc : std_logic;
......@@ -190,7 +190,7 @@ architecture structural of i2c_master_top is
begin
-- generate internal reset signal
rst_i <= not wb_rst_i; --arst_i xor ARST_LVL;
arst_n <= arst_i xor ARST_LVL;
-- generate acknowledge output signal
gen_ack_o : process(wb_clk_i)
......@@ -228,9 +228,9 @@ begin
-- generate registers (CR, SR see below)
gen_regs: process(rst_i, wb_clk_i)
gen_regs: process(arst_n, wb_clk_i)
begin
if (rst_i = '0') then
if (arst_n = '0') then
prer <= (others => '1');
ctr <= (others => '0');
txr <= (others => '0');
......@@ -268,9 +268,9 @@ begin
-- generate command register
gen_cr: process(rst_i, wb_clk_i)
gen_cr: process(arst_n, wb_clk_i)
begin
if (rst_i = '0') then
if (arst_n = '0') then
cr <= (others => '0');
elsif (wb_clk_i'event and wb_clk_i = '1') then
if (wb_rst_i = '1') then
......@@ -309,7 +309,7 @@ begin
port map (
clk => wb_clk_i,
rst => wb_rst_i,
nReset => rst_i,
nReset => arst_n,
ena => core_en,
clk_cnt => prer,
start => sta,
......@@ -346,9 +346,9 @@ begin
st_irq_block : block
begin
-- generate status register bits
gen_sr_bits: process (wb_clk_i, rst_i)
gen_sr_bits: process (arst_n, wb_clk_i)
begin
if (rst_i = '0') then
if (arst_n = '0') then
al <= '0';
rxack <= '0';
tip <= '0';
......@@ -371,9 +371,9 @@ begin
end process gen_sr_bits;
-- generate interrupt request signals
gen_irq: process (wb_clk_i, rst_i)
gen_irq: process (arst_n, wb_clk_i)
begin
if (rst_i = '0') then
if (arst_n = '0') then
inta_o <= '0';
elsif (wb_clk_i'event and wb_clk_i = '1') then
if (wb_rst_i = '1') then
......
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;
files = ["wb_xc7_fw_update_regs.vhd",
"xwb_xc7_fw_update.vhd",
]
memory-map:
bus: wb-32-be
name: wb_xc7_fw_update_regs
description: System Control Registers
x-hdl:
busgroup: True
children:
- reg:
name: far
width: 32
access: rw
comment: Flash Access Register
description: Provides direct access to the SPI flash memory containing the bitstream.
x-hdl:
type: wire
write-strobe: true
children:
- field:
name: data
range: 7-0
comment: SPI Data
description: Data to be written / read to/from the flash SPI controller.
- field:
name: xfer
range: 8
comment: SPI Start Transfer
description: "write 1: initiate an SPI transfer with an 8-bit data word taken from the DATA field. write 0: no effect"
- field:
name: ready
range: 9
comment: SPI Ready
description: "read 1: Core is ready to initiate another transfer. DATA field contains the data read during previous transaction. read 0: core is busy"
- field:
name: cs
range: 10
comment: SPI Chip Select
description: "write 1: Enable target SPI controller. write 0: Disable target SPI controller"
-- Do not edit. Generated on Tue May 19 11:16:59 2020 by tgingold
-- With Cheby 1.4.dev0 and these options:
-- -i wb_xc7_fw_update_regs.cheby --gen-hdl wb_xc7_fw_update_regs.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
entity wb_xc7_fw_update_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;
-- Flash Access Register
-- SPI Data
far_data_i : in std_logic_vector(7 downto 0);
far_data_o : out std_logic_vector(7 downto 0);
-- SPI Start Transfer
far_xfer_i : in std_logic;
far_xfer_o : out std_logic;
-- SPI Ready
far_ready_i : in std_logic;
far_ready_o : out std_logic;
-- SPI Chip Select
far_cs_i : in std_logic;
far_cs_o : out std_logic;
far_wr_o : out std_logic
);
end wb_xc7_fw_update_regs;
architecture syn of wb_xc7_fw_update_regs is
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 far_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_dat_d0 : std_logic_vector(31 downto 0);
signal wr_sel_d0 : std_logic_vector(3 downto 0);
begin
-- WB decode signals
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_dat_d0 <= wb_i.dat;
wr_sel_d0 <= wb_i.sel;
end if;
end if;
end process;
-- Register far
far_data_o <= wr_dat_d0(7 downto 0);
far_xfer_o <= wr_dat_d0(8);
far_ready_o <= wr_dat_d0(9);
far_cs_o <= wr_dat_d0(10);
far_wr_o <= far_wreq;
-- Process for write requests.
process (wr_req_d0) begin
far_wreq <= '0';
-- Reg far
far_wreq <= wr_req_d0;
wr_ack_int <= wr_req_d0;
end process;
-- Process for read requests.
process (rd_req_int, far_data_i, far_xfer_i, far_ready_i, far_cs_i) begin
-- By default ack read requests
rd_dat_d0 <= (others => 'X');
-- Reg far
rd_ack_d0 <= rd_req_int;
rd_dat_d0(7 downto 0) <= far_data_i;
rd_dat_d0(8) <= far_xfer_i;
rd_dat_d0(9) <= far_ready_i;
rd_dat_d0(10) <= far_cs_i;
rd_dat_d0(31 downto 11) <= (others => '0');
end process;
end syn;
library ieee;
use ieee.std_logic_1164.all;
library unisim;
use unisim.vcomponents.all;
use work.wishbone_pkg.all;
entity xwb_xc7_fw_update is
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
wb_i : in t_wishbone_slave_in;
wb_o : out t_wishbone_slave_out;
flash_cs_n_o : out std_logic;
flash_mosi_o : out std_logic;
flash_miso_i : in std_logic
);
end xwb_xc7_fw_update;
architecture rtl of xwb_xc7_fw_update is
signal far_data_in : std_logic_vector(7 downto 0);
signal far_data_out : std_logic_vector(7 downto 0);
signal far_xfer_out : std_logic;
signal far_ready_in : std_logic;
signal far_cs_out : std_logic;
signal far_wr_out : std_logic;
signal flash_spi_cs : std_logic;
signal flash_spi_start : std_logic;
signal flash_spi_wdata : std_logic_vector(7 downto 0);
signal flash_sclk : std_logic;
begin
inst_regs: entity work.wb_xc7_fw_update_regs
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
wb_i => wb_i,
wb_o => wb_o,
far_data_i => far_data_in,
far_data_o => far_data_out,
far_xfer_i => '0',
far_xfer_o => far_xfer_out,
far_ready_i => far_ready_in,
far_ready_o => open,
far_cs_i => '0',
far_cs_o => far_cs_out,
far_wr_o => far_wr_out
);
-- Need to capture cs and data_out, and need to delay start.
p_host_spi_registers : process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
flash_spi_start <= '0';
flash_spi_wdata <= (others => '0');
flash_spi_cs <= '0';
elsif far_wr_out = '1' then
flash_spi_wdata <= far_data_out;
flash_spi_start <= far_xfer_out;
flash_spi_cs <= far_cs_out;
else
-- Pulse for start.
flash_spi_start <= '0';
end if;
end if;
end process;
U_SPI_Master : entity work.gc_simple_spi_master
generic map (
g_div_ratio_log2 => 0,
g_num_data_bits => 8)
port map (
clk_sys_i => clk_i,
rst_n_i => rst_n_i,
cs_i => flash_spi_cs,
start_i => flash_spi_start,
cpol_i => '0',
data_i => flash_spi_wdata,
ready_o => far_ready_in,
data_o => far_data_in,
spi_cs_n_o => flash_cs_n_o,
spi_sclk_o => flash_sclk,
spi_mosi_o => flash_mosi_o,
spi_miso_i => flash_miso_i);
STARTUPE2_inst : STARTUPE2
generic map (
PROG_USR => "FALSE", -- Activate program event security feature. Requires encrypted bitstreams.
SIM_CCLK_FREQ => 0.0 -- Set the Configuration Clock Frequency(ns) for simulation.
)
port map (
CFGCLK => open, -- 1-bit output: Configuration main clock output
CFGMCLK => open, -- 1-bit output: Configuration internal oscillator clock output
EOS => open, -- 1-bit output: Active high output signal indicating the End Of Startup.
PREQ => open, -- 1-bit output: PROGRAM request to fabric output
CLK => '0', -- 1-bit input: User start-up clock input
GSR => '0', -- 1-bit input: Global Set/Reset input (GSR cannot be used for the port name)
GTS => '0', -- 1-bit input: Global 3-state input (GTS cannot be used for the port name)
KEYCLEARB => '0', -- 1-bit input: Clear AES Decrypter Key input from Battery-Backed RAM (BBRAM)
PACK => '0', -- 1-bit input: PROGRAM acknowledge input
USRCCLKO => flash_sclk, -- 1-bit input: User CCLK input
USRCCLKTS => '0', -- 1-bit input: User CCLK 3-state enable input
USRDONEO => '0', -- 1-bit input: User DONE pin output control
USRDONETS => '1' -- 1-bit input: User DONE 3-state enable output
);
end rtl;
......@@ -28,9 +28,6 @@ library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.genram_pkg.all;
package wishbone_pkg is
constant c_wishbone_address_width : integer := 32;
......
This diff is collapsed.
......@@ -9,12 +9,16 @@ virtual class CWishboneAccessor extends CBusAccessor;
protected wb_cycle_type_t m_cycle_type;
function new();
$display("NEW");
m_cycle_type = CLASSIC;
m_default_xfer_size = 4;
endfunction // new
virtual task set_mode(wb_cycle_type_t mode);
virtual task automatic set_mode(wb_cycle_type_t mode);
m_cycle_type = mode;
$display("SET MODE %d", mode );
endtask // set_mode
......@@ -29,18 +33,18 @@ virtual class CWishboneAccessor extends CBusAccessor;
// RANDOM - event occurs randomly with probability (prob)
// These two can be combined (random events occuring after a certain initial delay)
// DELAYED events can be repeated (rep_rate parameter)
virtual task add_event(wba_sim_event_t evt, wba_sim_behavior_t behv, int dly_start, real prob, int rep_rate);
virtual task automatic add_event(wba_sim_event_t evt, wba_sim_behavior_t behv, int dly_start, real prob, int rep_rate);
endtask // add_event
// [slave only] gets a cycle from the queue
virtual task get(ref wb_cycle_t xfer);
virtual task automatic get(ref wb_cycle_t xfer);
endtask // get
// [master only] executes a cycle and returns its result
virtual task put(ref wb_cycle_t xfer);
virtual task automatic put(ref wb_cycle_t xfer);
endtask // put
......@@ -49,7 +53,7 @@ virtual class CWishboneAccessor extends CBusAccessor;
endfunction // idle
// [master only] generic write(s), blocking
virtual task writem(uint64_t addr[], uint64_t data[], int size = 4, ref int result = _null);
virtual task automatic writem(uint64_t addr[], uint64_t data[], int size = 4, ref int result = _null);
wb_cycle_t cycle;
int i;
......@@ -74,11 +78,13 @@ virtual class CWishboneAccessor extends CBusAccessor;
endtask // write
// [master only] generic read(s), blocking
virtual task readm(uint64_t addr[], ref uint64_t data[],input int size = 4, ref int result = _null);
virtual task automatic readm(uint64_t addr[], ref uint64_t data[],input int size = 4, ref int result = _null);
wb_cycle_t cycle;
int i;
cycle.ctype = m_cycle_type;
$display("CYCLE CTYPE %d %d", cycle.ctype, m_cycle_type );
cycle.rw = 1'b0;
for(i=0;i < addr.size(); i++)
......@@ -99,7 +105,7 @@ virtual class CWishboneAccessor extends CBusAccessor;
endtask // readm
virtual task read(uint64_t addr, ref uint64_t data, input int size = 4, ref int result = _null);
virtual task automatic read(uint64_t addr, ref uint64_t data, input int size = 4, ref int result = _null);
uint64_t aa[], da[];
aa = new[1];
da = new[1];
......@@ -108,7 +114,7 @@ virtual class CWishboneAccessor extends CBusAccessor;
data = da[0];
endtask
virtual task write(uint64_t addr, uint64_t data, int size = 4, ref int result = _null);
virtual task automatic write(uint64_t addr, uint64_t data, int size = 4, ref int result = _null);
uint64_t aa[], da[];
aa = new[1];
da = new[1];
......
......@@ -24,10 +24,10 @@ virtual class CBusAccessor;
pure virtual task writem(uint64_t addr[], uint64_t data[], input int size, ref int result);
pure virtual task readm(uint64_t addr[], ref uint64_t data[], input int size, ref int result);
pure virtual task automatic writem(uint64_t addr[], uint64_t data[], input int size, ref int result);
pure virtual task automatic readm(uint64_t addr[], ref uint64_t data[], input int size, ref int result);
virtual task read(uint64_t addr, ref uint64_t data, input int size = m_default_xfer_size, ref int result = _null);
virtual task automatic read(uint64_t addr, ref uint64_t data, input int size = m_default_xfer_size, ref int result = _null);
int res;
uint64_t aa[1], da[];
......@@ -39,7 +39,7 @@ virtual class CBusAccessor;
endtask
virtual task write(uint64_t addr, uint64_t data, input int size = m_default_xfer_size, ref int result = _null);
virtual task automatic write(uint64_t addr, uint64_t data, input int size = m_default_xfer_size, ref int result = _null);
uint64_t aa[1], da[1];
aa[0] = addr;
da[0] = data;
......
files = [ 'sim_wishbone.vhd', 'sim_wishbone16.vhd']
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
package sim_wishbone is
-- PL: pipelined versions.
procedure write32_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : std_logic_vector (31 downto 0);
data : std_logic_vector (31 downto 0));
procedure read32_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : std_logic_vector (31 downto 0);
data : out std_logic_vector (31 downto 0));
procedure write32_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : std_logic_vector (31 downto 0));
procedure read32_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : out std_logic_vector (31 downto 0));
end sim_wishbone;
package body sim_wishbone is
-- Generate a strobe pulse.
procedure start_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in) is
begin
wb_o.stb <= '1';
loop
wait until rising_edge(clk);
exit when wb_i.stall = '0';
end loop;
wb_o.stb <= '0';
end start_pl;
procedure wait_ack (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in) is
begin
loop
exit when wb_i.ack = '1';
wait until rising_edge(clk);
end loop;
wb_o.cyc <= '0';
wb_o.adr <= (others => 'X');
wb_o.dat <= (others => 'X');
end wait_ack;
procedure write32_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : std_logic_vector (31 downto 0);
data : std_logic_vector (31 downto 0)) is
begin
wb_o.adr <= addr;
wb_o.dat <= data;
wb_o.sel <= "1111";
wb_o.we <= '1';
wb_o.cyc <= '1';
start_pl (clk, wb_o, wb_i);
wait_ack (clk, wb_o, wb_i);
end write32_pl;
procedure read32_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : std_logic_vector (31 downto 0);
data : out std_logic_vector (31 downto 0)) is
begin
wb_o.adr <= addr;
wb_o.we <= '0';
wb_o.cyc <= '1';
start_pl (clk, wb_o, wb_i);
wait_ack (clk, wb_o, wb_i);
data := wb_i.dat;
end read32_pl;
procedure write32_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : std_logic_vector (31 downto 0)) is
begin
write32_pl (clk, wb_o, wb_i, std_logic_vector (to_unsigned(addr, 32)), data);
end write32_pl;
procedure read32_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : out std_logic_vector (31 downto 0)) is
begin
read32_pl (clk, wb_o, wb_i, std_logic_vector (to_unsigned(addr, 32)), data);
end read32_pl;
end sim_wishbone;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
package sim_wishbone16 is
-- PL: pipelined versions.
procedure write16_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : std_logic_vector (15 downto 0));
procedure read16_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : out std_logic_vector (15 downto 0));
procedure write64be_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : std_logic_vector (63 downto 0));
procedure read64be_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : out std_logic_vector (63 downto 0));
end sim_wishbone16;
use work.sim_wishbone.all;
package body sim_wishbone16 is
procedure write16_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : std_logic_vector (15 downto 0)) is
begin
write32_pl(clk, wb_o, wb_i, addr, x"0000" & data);
end write16_pl;
procedure read16_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : out std_logic_vector (15 downto 0))
is
variable t : std_logic_vector(31 downto 0);
begin
read32_pl(clk, wb_o, wb_i, addr, t);
data := t(15 downto 0);
end read16_pl;
procedure write64be_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : std_logic_vector (63 downto 0)) is
begin
write32_pl(clk, wb_o, wb_i, addr + 0, x"0000" & data (63 downto 48));
write32_pl(clk, wb_o, wb_i, addr + 2, x"0000" & data (47 downto 32));
write32_pl(clk, wb_o, wb_i, addr + 4, x"0000" & data (31 downto 16));
write32_pl(clk, wb_o, wb_i, addr + 6, x"0000" & data (15 downto 00));
end write64be_pl;
procedure read64be_pl (signal clk : std_logic;
signal wb_o: out t_wishbone_master_out;
signal wb_i: in t_wishbone_master_in;
addr : natural;
data : out std_logic_vector (63 downto 0))
is
variable t : std_logic_vector(31 downto 0);
begin
read32_pl(clk, wb_o, wb_i, addr + 0, t);
data (63 downto 48) := t(15 downto 0);
read32_pl(clk, wb_o, wb_i, addr + 2, t);
data (47 downto 32) := t(15 downto 0);
read32_pl(clk, wb_o, wb_i, addr + 4, t);
data (31 downto 16) := t(15 downto 0);
read32_pl(clk, wb_o, wb_i, addr + 6, t);
data (15 downto 00) := t(15 downto 0);
end read64be_pl;
end sim_wishbone16;
......@@ -2,4 +2,9 @@
#
# SPDX-FileCopyrightText: 2019 CERN
Makefile.specific
\ No newline at end of file
Makefile.specific
*.mod.c
*.ko
*.cmd
Module.symvers
modules.order
\ No newline at end of file
-include Makefile.specific
# include parent_common.mk for buildsystem's defines
#use absolute path for REPO_PARENT
REPO_PARENT ?= $(shell /bin/pwd)/..
-include $(REPO_PARENT)/parent_common.mk
# SPDX-License-Identifier: CC0-1.0
#
# Copyright (C) 2019 CERN
DIRS := i2c-ocores
DIRS += spi-ocores
DIRS += htvic
.PHONY: all clean modules install modules_install
.PHONY: all clean modules install modules_install gtags
all: modules
install: modules_install
all clean modules install modules_install:
clean modules modules_install coccicheck:
for D in $(DIRS); do $(MAKE) -C $$D $@; done
gtags:
git ls-tree -r --name-only HEAD | grep -E '.*\.(c|h)$$' | gtags -f -
# SPDX-License-Identifier: CC0-1.0
#
# Copyright (C) 2019 CERN
PACKAGE_NAME="general-cores"
PACKAGE_VERSION="@PKGVER@"
CLEAN="make clean"
MAKE[0]="make KVERSION=$kernelver all"
BUILT_MODULE_NAME[0]="htvic"
BUILT_MODULE_NAME[1]="i2c-ocores"
BUILT_MODULE_NAME[2]="spi-ocores"
BUILT_MODULE_LOCATION[0]="htvic/driver"
BUILT_MODULE_LOCATION[1]="i2c-ocores/drivers/i2c/busses"
BUILT_MODULE_LOCATION[2]="spi-ocores/drivers/spi"
DEST_MODULE_LOCATION[0]="/updates"
DEST_MODULE_LOCATION[1]="/updates"
DEST_MODULE_LOCATION[2]="/updates"
AUTOINSTALL="yes"
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2016 CERN
* Author: Federico Vaga <federico.vaga@cern.ch>
......
/* SPDX-License-Identifier: GPL-2.0-or-later */
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2016 CERN
* Author: Federico Vaga <federico.vaga@cern.ch>
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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