mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-20 04:07:36 -04:00
fpu: ⬆️ Update FPU version (#1102)
Co-authored-by: Matteo Perotti <mperotti@iis.ee.ethz.ch> Co-authored-by: Matheus Cavalcante <matheusd@iis.ee.ethz.ch> Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
This commit is contained in:
parent
c1df1da568
commit
3833439fb7
97 changed files with 415 additions and 5812 deletions
40
Bender.yml
40
Bender.yml
|
@ -10,7 +10,7 @@ dependencies:
|
|||
axi: { git: "https://github.com/pulp-platform/axi.git", version: 0.31.0 }
|
||||
common_cells:
|
||||
{ git: "https://github.com/pulp-platform/common_cells", version: 1.23.0 }
|
||||
fpnew: { git: "https://github.com/pulp-platform/fpnew.git", version: 0.6.2 }
|
||||
fpnew: { git: "https://github.com/openhwgroup/cvfpu.git", version: 0.7.0 }
|
||||
tech_cells_generic:
|
||||
{
|
||||
git: "https://github.com/pulp-platform/tech_cells_generic.git",
|
||||
|
@ -103,25 +103,25 @@ sources:
|
|||
# - vendor/pulp-platform/common_cells/src/delta_counter.sv
|
||||
|
||||
# Floating point unit
|
||||
# - vendor/pulp-platform/fpnew/src/fpnew_pkg.sv
|
||||
# - vendor/pulp-platform/fpnew/src/fpnew_cast_multi.sv
|
||||
# - vendor/pulp-platform/fpnew/src/fpnew_classifier.sv
|
||||
# - vendor/pulp-platform/fpnew/src/fpnew_divsqrt_multi.sv
|
||||
# - vendor/pulp-platform/fpnew/src/fpnew_fma_multi.sv
|
||||
# - vendor/pulp-platform/fpnew/src/fpnew_fma.sv
|
||||
# - vendor/pulp-platform/fpnew/src/fpnew_noncomp.sv
|
||||
# - vendor/pulp-platform/fpnew/src/fpnew_opgroup_block.sv
|
||||
# - vendor/pulp-platform/fpnew/src/fpnew_opgroup_fmt_slice.sv
|
||||
# - vendor/pulp-platform/fpnew/src/fpnew_opgroup_multifmt_slice.sv
|
||||
# - vendor/pulp-platform/fpnew/src/fpnew_rounding.sv
|
||||
# - vendor/pulp-platform/fpnew/src/fpnew_top.sv
|
||||
# - vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/defs_div_sqrt_mvp.sv
|
||||
# - vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/control_mvp.sv
|
||||
# - vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/div_sqrt_top_mvp.sv
|
||||
# - vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/iteration_div_sqrt_mvp.sv
|
||||
# - vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/norm_div_sqrt_mvp.sv
|
||||
# - vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/nrbd_nrsc_mvp.sv
|
||||
# - vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/preprocess_mvp.sv
|
||||
# - vendor/openhwgroup/cvfpu/src/fpnew_pkg.sv
|
||||
# - vendor/openhwgroup/cvfpu/src/fpnew_cast_multi.sv
|
||||
# - vendor/openhwgroup/cvfpu/src/fpnew_classifier.sv
|
||||
# - vendor/openhwgroup/cvfpu/src/fpnew_divsqrt_multi.sv
|
||||
# - vendor/openhwgroup/cvfpu/src/fpnew_fma_multi.sv
|
||||
# - vendor/openhwgroup/cvfpu/src/fpnew_fma.sv
|
||||
# - vendor/openhwgroup/cvfpu/src/fpnew_noncomp.sv
|
||||
# - vendor/openhwgroup/cvfpu/src/fpnew_opgroup_block.sv
|
||||
# - vendor/openhwgroup/cvfpu/src/fpnew_opgroup_fmt_slice.sv
|
||||
# - vendor/openhwgroup/cvfpu/src/fpnew_opgroup_multifmt_slice.sv
|
||||
# - vendor/openhwgroup/cvfpu/src/fpnew_rounding.sv
|
||||
# - vendor/openhwgroup/cvfpu/src/fpnew_top.sv
|
||||
# - vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/defs_div_sqrt_mvp.sv
|
||||
# - vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/control_mvp.sv
|
||||
# - vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/div_sqrt_top_mvp.sv
|
||||
# - vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/iteration_div_sqrt_mvp.sv
|
||||
# - vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/norm_div_sqrt_mvp.sv
|
||||
# - vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/nrbd_nrsc_mvp.sv
|
||||
# - vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/preprocess_mvp.sv
|
||||
|
||||
# Top-level source files (not necessarily instantiated at the top of the cva6).
|
||||
- core/ariane.sv
|
||||
|
|
40
Flist.ariane
40
Flist.ariane
|
@ -28,7 +28,7 @@ vendor/pulp-platform/axi/src/axi_pkg.sv
|
|||
core/include/ariane_axi_pkg.sv
|
||||
core/include/wt_cache_pkg.sv
|
||||
core/include/axi_intf.sv
|
||||
vendor/pulp-platform/fpnew/src/fpnew_pkg.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpnew_pkg.sv
|
||||
core/include/cvxif_pkg.sv
|
||||
vendor/pulp-platform/common_cells/src/cf_math_pkg.sv
|
||||
core/include/instr_tracer_pkg.sv
|
||||
|
@ -132,25 +132,25 @@ corev_apu/fpga/src/axi_slice/src/axi_r_buffer.sv
|
|||
corev_apu/fpga/src/axi_slice/src/axi_aw_buffer.sv
|
||||
corev_apu/register_interface/src/apb_to_reg.sv
|
||||
corev_apu/register_interface/src/reg_intf.sv
|
||||
vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/defs_div_sqrt_mvp.sv
|
||||
vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/control_mvp.sv
|
||||
vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/div_sqrt_mvp_wrapper.sv
|
||||
vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/div_sqrt_top_mvp.sv
|
||||
vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/iteration_div_sqrt_mvp.sv
|
||||
vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/norm_div_sqrt_mvp.sv
|
||||
vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/nrbd_nrsc_mvp.sv
|
||||
vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/preprocess_mvp.sv
|
||||
vendor/pulp-platform/fpnew/src/fpnew_cast_multi.sv
|
||||
vendor/pulp-platform/fpnew/src/fpnew_classifier.sv
|
||||
vendor/pulp-platform/fpnew/src/fpnew_divsqrt_multi.sv
|
||||
vendor/pulp-platform/fpnew/src/fpnew_fma_multi.sv
|
||||
vendor/pulp-platform/fpnew/src/fpnew_fma.sv
|
||||
vendor/pulp-platform/fpnew/src/fpnew_noncomp.sv
|
||||
vendor/pulp-platform/fpnew/src/fpnew_opgroup_block.sv
|
||||
vendor/pulp-platform/fpnew/src/fpnew_opgroup_fmt_slice.sv
|
||||
vendor/pulp-platform/fpnew/src/fpnew_opgroup_multifmt_slice.sv
|
||||
vendor/pulp-platform/fpnew/src/fpnew_rounding.sv
|
||||
vendor/pulp-platform/fpnew/src/fpnew_top.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/defs_div_sqrt_mvp.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/control_mvp.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/div_sqrt_mvp_wrapper.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/div_sqrt_top_mvp.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/iteration_div_sqrt_mvp.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/norm_div_sqrt_mvp.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/nrbd_nrsc_mvp.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/preprocess_mvp.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpnew_cast_multi.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpnew_classifier.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpnew_divsqrt_multi.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpnew_fma_multi.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpnew_fma.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpnew_noncomp.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpnew_opgroup_block.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpnew_opgroup_fmt_slice.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpnew_opgroup_multifmt_slice.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpnew_rounding.sv
|
||||
vendor/openhwgroup/cvfpu/src/fpnew_top.sv
|
||||
core/pmp/src/pmp.sv
|
||||
core/pmp/src/pmp_entry.sv
|
||||
common/local/util/instr_tracer.sv
|
||||
|
|
|
@ -77,25 +77,25 @@ ${CVA6_REPO_DIR}/vendor/pulp-platform/common_cells/src/counter.sv
|
|||
${CVA6_REPO_DIR}/vendor/pulp-platform/common_cells/src/delta_counter.sv
|
||||
|
||||
// Floating point unit
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpnew/src/fpnew_pkg.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpnew/src/fpnew_cast_multi.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpnew/src/fpnew_classifier.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpnew/src/fpnew_divsqrt_multi.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpnew/src/fpnew_fma_multi.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpnew/src/fpnew_fma.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpnew/src/fpnew_noncomp.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpnew/src/fpnew_opgroup_block.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpnew/src/fpnew_opgroup_fmt_slice.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpnew/src/fpnew_opgroup_multifmt_slice.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpnew/src/fpnew_rounding.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpnew/src/fpnew_top.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/defs_div_sqrt_mvp.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/control_mvp.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/div_sqrt_top_mvp.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/iteration_div_sqrt_mvp.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/norm_div_sqrt_mvp.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/nrbd_nrsc_mvp.sv
|
||||
${CVA6_REPO_DIR}/vendor/pulp-platform/fpnew/src/fpu_div_sqrt_mvp/hdl/preprocess_mvp.sv
|
||||
${CVA6_REPO_DIR}/vendor/openhwgroup/cvfpu/src/fpnew_pkg.sv
|
||||
${CVA6_REPO_DIR}/vendor/openhwgroup/cvfpu/src/fpnew_cast_multi.sv
|
||||
${CVA6_REPO_DIR}/vendor/openhwgroup/cvfpu/src/fpnew_classifier.sv
|
||||
${CVA6_REPO_DIR}/vendor/openhwgroup/cvfpu/src/fpnew_divsqrt_multi.sv
|
||||
${CVA6_REPO_DIR}/vendor/openhwgroup/cvfpu/src/fpnew_fma_multi.sv
|
||||
${CVA6_REPO_DIR}/vendor/openhwgroup/cvfpu/src/fpnew_fma.sv
|
||||
${CVA6_REPO_DIR}/vendor/openhwgroup/cvfpu/src/fpnew_noncomp.sv
|
||||
${CVA6_REPO_DIR}/vendor/openhwgroup/cvfpu/src/fpnew_opgroup_block.sv
|
||||
${CVA6_REPO_DIR}/vendor/openhwgroup/cvfpu/src/fpnew_opgroup_fmt_slice.sv
|
||||
${CVA6_REPO_DIR}/vendor/openhwgroup/cvfpu/src/fpnew_opgroup_multifmt_slice.sv
|
||||
${CVA6_REPO_DIR}/vendor/openhwgroup/cvfpu/src/fpnew_rounding.sv
|
||||
${CVA6_REPO_DIR}/vendor/openhwgroup/cvfpu/src/fpnew_top.sv
|
||||
${CVA6_REPO_DIR}/vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/defs_div_sqrt_mvp.sv
|
||||
${CVA6_REPO_DIR}/vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/control_mvp.sv
|
||||
${CVA6_REPO_DIR}/vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/div_sqrt_top_mvp.sv
|
||||
${CVA6_REPO_DIR}/vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/iteration_div_sqrt_mvp.sv
|
||||
${CVA6_REPO_DIR}/vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/norm_div_sqrt_mvp.sv
|
||||
${CVA6_REPO_DIR}/vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/nrbd_nrsc_mvp.sv
|
||||
${CVA6_REPO_DIR}/vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/hdl/preprocess_mvp.sv
|
||||
|
||||
// Top-level source files (not necessarily instantiated at the top of the cva6).
|
||||
${CVA6_REPO_DIR}/core/cva6.sv
|
||||
|
|
|
@ -525,6 +525,7 @@ module fpu_wrap import ariane_pkg::*; (
|
|||
.int_fmt_i ( fpnew_pkg::int_format_e'(fpu_ifmt) ),
|
||||
.vectorial_op_i ( fpu_vec_op ),
|
||||
.tag_i ( fpu_tag ),
|
||||
.simd_mask_i ( 1'b1 ),
|
||||
.in_valid_i ( fpu_in_valid ),
|
||||
.in_ready_o ( fpu_in_ready ),
|
||||
.flush_i,
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
../../axi/src/axi_pkg.sv
|
||||
../../axi/src/axi_intf.sv
|
||||
../../axi/src/axi_test.sv
|
||||
../../../vendor/pulp-platform/fpnew/src/fpnew_pkg.sv
|
||||
../../../vendor/openhwgroup/cvfpu/src/fpnew_pkg.sv
|
||||
../../../core/include/ariane_pkg.sv
|
||||
../ariane_soc_pkg.sv
|
||||
../ariane_axi_soc_pkg.sv
|
||||
|
|
|
@ -17,7 +17,7 @@ set clk_period $PERIOD
|
|||
set input_delay $INPUT_DELAY
|
||||
set output_delay $OUTPUT_DELAY
|
||||
|
||||
set_app_var search_path "../../vendor/pulp-platform/fpnew/src/common_cells/include/ $search_path"
|
||||
set_app_var search_path "../../vendor/pulp-platform/common_cells/include/ $search_path"
|
||||
|
||||
sh rm -rf work
|
||||
sh mkdir work
|
||||
|
|
33
vendor/openhwgroup/cvfpu/CITATION.cff
vendored
Normal file
33
vendor/openhwgroup/cvfpu/CITATION.cff
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
cff-version: 1.2.0
|
||||
message: "If you use FPnew, please cite it as below."
|
||||
authors:
|
||||
- family-names: "Mach"
|
||||
given-names: "Stefan"
|
||||
orcid: "https://orcid.org/0000-0002-3476-8857"
|
||||
title: "FPnew: - New Floating-Point Unit with Transprecision Capabilities"
|
||||
version: 0.6.6
|
||||
url: "https://github.com/pulp-platform/fpnew"
|
||||
preferred-citation:
|
||||
type: article
|
||||
authors:
|
||||
- family-names: "Mach"
|
||||
given-names: "Stefan"
|
||||
orcid: "https://orcid.org/0000-0002-3476-8857"
|
||||
- family-names: "Schuiki"
|
||||
given-names: "Fabian"
|
||||
orcid: "https://orcid.org/0000-0002-9923-5031"
|
||||
- family-names: "Zaruba"
|
||||
given-names: "Florian"
|
||||
orcid: "https://orcid.org/0000-0002-8194-6521"
|
||||
- family-names: "Benini"
|
||||
given-names: "Luca"
|
||||
orcid: "https://orcid.org/0000-0001-8068-3806"
|
||||
doi: "10.1109/TVLSI.2020.3044752"
|
||||
journal: "IEEE Transactions on Very Large Scale Integration (VLSI) Systems"
|
||||
month: 12
|
||||
start: 774
|
||||
end: 787
|
||||
title: "FPnew: An Open-Source Multiformat Floating-Point Unit Architecture for Energy-Proportional Transprecision Computing"
|
||||
issue: 4
|
||||
volume: 29
|
||||
year: 2020
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
Parametric floating-point unit with support for standard RISC-V formats and operations as well as transprecision formats, written in SystemVerilog.
|
||||
|
||||
Maintainer: Stefan Mach <smach@iis.ee.ethz.ch>
|
||||
Maintainer: Luca Bertaccini <lbertaccini@iis.ee.ethz.ch>
|
||||
Principal Author: Stefan Mach <smach@iis.ee.ethz.ch>
|
||||
|
||||
## Features
|
||||
|
||||
|
@ -138,6 +139,32 @@ Furthermore, this repository tries to adhere to [SemVer](https://semver.org/), a
|
|||
|
||||
FPnew is released under the *SolderPad Hardware License*, which is a permissive license based on Apache 2.0. Please refer to the [license file](LICENSE) for further information.
|
||||
|
||||
|
||||
## Publication
|
||||
|
||||
If you use FPnew in your work, you can cite us:
|
||||
|
||||
<details>
|
||||
<summary>FPnew Publication</summary>
|
||||
<p>
|
||||
|
||||
```
|
||||
@article{mach2020fpnew,
|
||||
title={Fpnew: An open-source multiformat floating-point unit architecture for energy-proportional transprecision computing},
|
||||
author={Mach, Stefan and Schuiki, Fabian and Zaruba, Florian and Benini, Luca},
|
||||
journal={IEEE Transactions on Very Large Scale Integration (VLSI) Systems},
|
||||
volume={29},
|
||||
number={4},
|
||||
pages={774--787},
|
||||
year={2020},
|
||||
publisher={IEEE}
|
||||
}
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
|
||||
## Acknowledgement
|
||||
|
||||
This project has received funding from the European Union's Horizon 2020 research and innovation programme under grant agreement No 732631.
|
|
@ -8,6 +8,8 @@
|
|||
// 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.
|
||||
//
|
||||
// SPDX-License-Identifier: SHL-0.51
|
||||
|
||||
// Author: Stefan Mach <smach@iis.ee.ethz.ch>
|
||||
|
||||
|
@ -38,6 +40,7 @@ module fpnew_cast_multi #(
|
|||
input fpnew_pkg::fp_format_e dst_fmt_i,
|
||||
input fpnew_pkg::int_format_e int_fmt_i,
|
||||
input TagType tag_i,
|
||||
input logic mask_i,
|
||||
input AuxType aux_i,
|
||||
// Input Handshake
|
||||
input logic in_valid_i,
|
||||
|
@ -48,6 +51,7 @@ module fpnew_cast_multi #(
|
|||
output fpnew_pkg::status_t status_o,
|
||||
output logic extension_bit_o,
|
||||
output TagType tag_o,
|
||||
output logic mask_o,
|
||||
output AuxType aux_o,
|
||||
// Output handshake
|
||||
output logic out_valid_o,
|
||||
|
@ -114,6 +118,7 @@ module fpnew_cast_multi #(
|
|||
fpnew_pkg::fp_format_e [0:NUM_INP_REGS] inp_pipe_dst_fmt_q;
|
||||
fpnew_pkg::int_format_e [0:NUM_INP_REGS] inp_pipe_int_fmt_q;
|
||||
TagType [0:NUM_INP_REGS] inp_pipe_tag_q;
|
||||
logic [0:NUM_INP_REGS] inp_pipe_mask_q;
|
||||
AuxType [0:NUM_INP_REGS] inp_pipe_aux_q;
|
||||
logic [0:NUM_INP_REGS] inp_pipe_valid_q;
|
||||
// Ready signal is combinatorial for all stages
|
||||
|
@ -129,6 +134,7 @@ module fpnew_cast_multi #(
|
|||
assign inp_pipe_dst_fmt_q[0] = dst_fmt_i;
|
||||
assign inp_pipe_int_fmt_q[0] = int_fmt_i;
|
||||
assign inp_pipe_tag_q[0] = tag_i;
|
||||
assign inp_pipe_mask_q[0] = mask_i;
|
||||
assign inp_pipe_aux_q[0] = aux_i;
|
||||
assign inp_pipe_valid_q[0] = in_valid_i;
|
||||
// Input stage: Propagate pipeline ready signal to updtream circuitry
|
||||
|
@ -155,6 +161,7 @@ module fpnew_cast_multi #(
|
|||
`FFL(inp_pipe_dst_fmt_q[i+1], inp_pipe_dst_fmt_q[i], reg_ena, fpnew_pkg::fp_format_e'(0))
|
||||
`FFL(inp_pipe_int_fmt_q[i+1], inp_pipe_int_fmt_q[i], reg_ena, fpnew_pkg::int_format_e'(0))
|
||||
`FFL(inp_pipe_tag_q[i+1], inp_pipe_tag_q[i], reg_ena, TagType'('0))
|
||||
`FFL(inp_pipe_mask_q[i+1], inp_pipe_mask_q[i], reg_ena, '0)
|
||||
`FFL(inp_pipe_aux_q[i+1], inp_pipe_aux_q[i], reg_ena, AuxType'('0))
|
||||
end
|
||||
// Output stage: assign selected pipe outputs to signals for later use
|
||||
|
@ -328,6 +335,7 @@ module fpnew_cast_multi #(
|
|||
fpnew_pkg::fp_format_e [0:NUM_MID_REGS] mid_pipe_dst_fmt_q;
|
||||
fpnew_pkg::int_format_e [0:NUM_MID_REGS] mid_pipe_int_fmt_q;
|
||||
TagType [0:NUM_MID_REGS] mid_pipe_tag_q;
|
||||
logic [0:NUM_MID_REGS] mid_pipe_mask_q;
|
||||
AuxType [0:NUM_MID_REGS] mid_pipe_aux_q;
|
||||
logic [0:NUM_MID_REGS] mid_pipe_valid_q;
|
||||
// Ready signal is combinatorial for all stages
|
||||
|
@ -348,6 +356,7 @@ module fpnew_cast_multi #(
|
|||
assign mid_pipe_dst_fmt_q[0] = dst_fmt_q;
|
||||
assign mid_pipe_int_fmt_q[0] = int_fmt_q;
|
||||
assign mid_pipe_tag_q[0] = inp_pipe_tag_q[NUM_INP_REGS];
|
||||
assign mid_pipe_mask_q[0] = inp_pipe_mask_q[NUM_INP_REGS];
|
||||
assign mid_pipe_aux_q[0] = inp_pipe_aux_q[NUM_INP_REGS];
|
||||
assign mid_pipe_valid_q[0] = inp_pipe_valid_q[NUM_INP_REGS];
|
||||
// Input stage: Propagate pipeline ready signal to input pipe
|
||||
|
@ -380,6 +389,7 @@ module fpnew_cast_multi #(
|
|||
`FFL(mid_pipe_dst_fmt_q[i+1], mid_pipe_dst_fmt_q[i], reg_ena, fpnew_pkg::fp_format_e'(0))
|
||||
`FFL(mid_pipe_int_fmt_q[i+1], mid_pipe_int_fmt_q[i], reg_ena, fpnew_pkg::int_format_e'(0))
|
||||
`FFL(mid_pipe_tag_q[i+1], mid_pipe_tag_q[i], reg_ena, TagType'('0))
|
||||
`FFL(mid_pipe_mask_q[i+1], mid_pipe_mask_q[i], reg_ena, '0)
|
||||
`FFL(mid_pipe_aux_q[i+1], mid_pipe_aux_q[i], reg_ena, AuxType'('0))
|
||||
end
|
||||
// Output stage: assign selected pipe outputs to signals for later use
|
||||
|
@ -489,6 +499,7 @@ module fpnew_cast_multi #(
|
|||
logic [NUM_FORMATS-1:0] fmt_uf_after_round;
|
||||
|
||||
logic [NUM_INT_FORMATS-1:0][WIDTH-1:0] ifmt_pre_round_abs; // per format
|
||||
logic [NUM_INT_FORMATS-1:0] ifmt_of_after_round;
|
||||
|
||||
logic rounded_sign;
|
||||
logic [WIDTH-1:0] rounded_abs; // absolute value of result after rounding
|
||||
|
@ -573,14 +584,33 @@ module fpnew_cast_multi #(
|
|||
end
|
||||
end
|
||||
|
||||
// Classification after rounding select by destination format
|
||||
assign uf_after_round = fmt_uf_after_round[dst_fmt_q2];
|
||||
assign of_after_round = fmt_of_after_round[dst_fmt_q2];
|
||||
|
||||
// Negative integer result needs to be brought into two's complement
|
||||
assign rounded_int_res = rounded_sign ? unsigned'(-rounded_abs) : rounded_abs;
|
||||
assign rounded_int_res_zero = (rounded_int_res == '0);
|
||||
|
||||
// Detect integer overflows after rounding (only positives)
|
||||
for (genvar ifmt = 0; ifmt < int'(NUM_INT_FORMATS); ifmt++) begin : gen_int_overflow
|
||||
// Set up some constants
|
||||
localparam int unsigned INT_WIDTH = fpnew_pkg::int_width(fpnew_pkg::int_format_e'(ifmt));
|
||||
|
||||
if (IntFmtConfig[ifmt]) begin : active_format
|
||||
always_comb begin : detect_overflow
|
||||
ifmt_of_after_round[ifmt] = 1'b0;
|
||||
// Int result can overflow if we're at the max exponent
|
||||
if (!rounded_sign && input_exp_q == signed'(INT_WIDTH - 2 + op_mod_q2)) begin
|
||||
// Check whether the rounded MSB differs from unrounded MSB
|
||||
ifmt_of_after_round[ifmt] = ~rounded_int_res[INT_WIDTH-2+op_mod_q2];
|
||||
end
|
||||
end
|
||||
end else begin : inactive_format
|
||||
assign ifmt_of_after_round[ifmt] = fpnew_pkg::DONT_CARE;
|
||||
end
|
||||
end
|
||||
|
||||
// Classification after rounding select by destination format
|
||||
assign uf_after_round = fmt_uf_after_round[dst_fmt_q2];
|
||||
assign of_after_round = dst_is_int_q ? ifmt_of_after_round[int_fmt_q2] : fmt_of_after_round[dst_fmt_q2];
|
||||
|
||||
// -------------------------
|
||||
// FP Special case handling
|
||||
// -------------------------
|
||||
|
@ -664,7 +694,7 @@ module fpnew_cast_multi #(
|
|||
|
||||
// Detect special case from source format (inf, nan, overflow, nan-boxing or negative unsigned)
|
||||
assign int_result_is_special = info_q.is_nan | info_q.is_inf |
|
||||
of_before_round | ~info_q.is_boxed |
|
||||
of_before_round | of_after_round | ~info_q.is_boxed |
|
||||
(input_sign_q & op_mod_q2 & ~rounded_int_res_zero);
|
||||
|
||||
// All integer special cases are invalid
|
||||
|
@ -714,6 +744,7 @@ module fpnew_cast_multi #(
|
|||
fpnew_pkg::status_t [0:NUM_OUT_REGS] out_pipe_status_q;
|
||||
logic [0:NUM_OUT_REGS] out_pipe_ext_bit_q;
|
||||
TagType [0:NUM_OUT_REGS] out_pipe_tag_q;
|
||||
logic [0:NUM_OUT_REGS] out_pipe_mask_q;
|
||||
AuxType [0:NUM_OUT_REGS] out_pipe_aux_q;
|
||||
logic [0:NUM_OUT_REGS] out_pipe_valid_q;
|
||||
// Ready signal is combinatorial for all stages
|
||||
|
@ -724,6 +755,7 @@ module fpnew_cast_multi #(
|
|||
assign out_pipe_status_q[0] = status_d;
|
||||
assign out_pipe_ext_bit_q[0] = extension_bit;
|
||||
assign out_pipe_tag_q[0] = mid_pipe_tag_q[NUM_MID_REGS];
|
||||
assign out_pipe_mask_q[0] = mid_pipe_mask_q[NUM_MID_REGS];
|
||||
assign out_pipe_aux_q[0] = mid_pipe_aux_q[NUM_MID_REGS];
|
||||
assign out_pipe_valid_q[0] = mid_pipe_valid_q[NUM_MID_REGS];
|
||||
// Input stage: Propagate pipeline ready signal to inside pipe
|
||||
|
@ -745,6 +777,7 @@ module fpnew_cast_multi #(
|
|||
`FFL(out_pipe_status_q[i+1], out_pipe_status_q[i], reg_ena, '0)
|
||||
`FFL(out_pipe_ext_bit_q[i+1], out_pipe_ext_bit_q[i], reg_ena, '0)
|
||||
`FFL(out_pipe_tag_q[i+1], out_pipe_tag_q[i], reg_ena, TagType'('0))
|
||||
`FFL(out_pipe_mask_q[i+1], out_pipe_mask_q[i], reg_ena, '0)
|
||||
`FFL(out_pipe_aux_q[i+1], out_pipe_aux_q[i], reg_ena, AuxType'('0))
|
||||
end
|
||||
// Output stage: Ready travels backwards from output side, driven by downstream circuitry
|
||||
|
@ -754,6 +787,7 @@ module fpnew_cast_multi #(
|
|||
assign status_o = out_pipe_status_q[NUM_OUT_REGS];
|
||||
assign extension_bit_o = out_pipe_ext_bit_q[NUM_OUT_REGS];
|
||||
assign tag_o = out_pipe_tag_q[NUM_OUT_REGS];
|
||||
assign mask_o = out_pipe_mask_q[NUM_OUT_REGS];
|
||||
assign aux_o = out_pipe_aux_q[NUM_OUT_REGS];
|
||||
assign out_valid_o = out_pipe_valid_q[NUM_OUT_REGS];
|
||||
assign busy_o = (| {inp_pipe_valid_q, mid_pipe_valid_q, out_pipe_valid_q});
|
|
@ -8,6 +8,8 @@
|
|||
// 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.
|
||||
//
|
||||
// SPDX-License-Identifier: SHL-0.51
|
||||
|
||||
// Author: Stefan Mach <smach@iis.ee.ethz.ch>
|
||||
|
|
@ -8,6 +8,8 @@
|
|||
// 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.
|
||||
//
|
||||
// SPDX-License-Identifier: SHL-0.51
|
||||
|
||||
// Author: Stefan Mach <smach@iis.ee.ethz.ch>
|
||||
|
||||
|
@ -33,16 +35,22 @@ module fpnew_divsqrt_multi #(
|
|||
input fpnew_pkg::operation_e op_i,
|
||||
input fpnew_pkg::fp_format_e dst_fmt_i,
|
||||
input TagType tag_i,
|
||||
input logic mask_i,
|
||||
input AuxType aux_i,
|
||||
// Input Handshake
|
||||
input logic in_valid_i,
|
||||
output logic in_ready_o,
|
||||
output logic divsqrt_done_o,
|
||||
input logic simd_synch_done_i,
|
||||
output logic divsqrt_ready_o,
|
||||
input logic simd_synch_rdy_i,
|
||||
input logic flush_i,
|
||||
// Output signals
|
||||
output logic [WIDTH-1:0] result_o,
|
||||
output fpnew_pkg::status_t status_o,
|
||||
output logic extension_bit_o,
|
||||
output TagType tag_o,
|
||||
output logic mask_o,
|
||||
output AuxType aux_o,
|
||||
// Output handshake
|
||||
output logic out_valid_o,
|
||||
|
@ -82,6 +90,7 @@ module fpnew_divsqrt_multi #(
|
|||
fpnew_pkg::operation_e [0:NUM_INP_REGS] inp_pipe_op_q;
|
||||
fpnew_pkg::fp_format_e [0:NUM_INP_REGS] inp_pipe_dst_fmt_q;
|
||||
TagType [0:NUM_INP_REGS] inp_pipe_tag_q;
|
||||
logic [0:NUM_INP_REGS] inp_pipe_mask_q;
|
||||
AuxType [0:NUM_INP_REGS] inp_pipe_aux_q;
|
||||
logic [0:NUM_INP_REGS] inp_pipe_valid_q;
|
||||
// Ready signal is combinatorial for all stages
|
||||
|
@ -93,6 +102,7 @@ module fpnew_divsqrt_multi #(
|
|||
assign inp_pipe_op_q[0] = op_i;
|
||||
assign inp_pipe_dst_fmt_q[0] = dst_fmt_i;
|
||||
assign inp_pipe_tag_q[0] = tag_i;
|
||||
assign inp_pipe_mask_q[0] = mask_i;
|
||||
assign inp_pipe_aux_q[0] = aux_i;
|
||||
assign inp_pipe_valid_q[0] = in_valid_i;
|
||||
// Input stage: Propagate pipeline ready signal to updtream circuitry
|
||||
|
@ -115,6 +125,7 @@ module fpnew_divsqrt_multi #(
|
|||
`FFL(inp_pipe_op_q[i+1], inp_pipe_op_q[i], reg_ena, fpnew_pkg::FMADD)
|
||||
`FFL(inp_pipe_dst_fmt_q[i+1], inp_pipe_dst_fmt_q[i], reg_ena, fpnew_pkg::fp_format_e'(0))
|
||||
`FFL(inp_pipe_tag_q[i+1], inp_pipe_tag_q[i], reg_ena, TagType'('0))
|
||||
`FFL(inp_pipe_mask_q[i+1], inp_pipe_mask_q[i], reg_ena, '0)
|
||||
`FFL(inp_pipe_aux_q[i+1], inp_pipe_aux_q[i], reg_ena, AuxType'('0))
|
||||
end
|
||||
// Output stage: assign selected pipe outputs to signals for later use
|
||||
|
@ -152,20 +163,29 @@ module fpnew_divsqrt_multi #(
|
|||
// ------------
|
||||
// Control FSM
|
||||
// ------------
|
||||
|
||||
logic in_ready; // input handshake with upstream
|
||||
logic div_valid, sqrt_valid; // input signalling with unit
|
||||
logic unit_ready, unit_done; // status signals from unit instance
|
||||
logic unit_ready, unit_done, unit_done_q; // status signals from unit instance
|
||||
logic op_starting; // high in the cycle a new operation starts
|
||||
logic out_valid, out_ready; // output handshake with downstream
|
||||
logic hold_result; // whether to put result into hold register
|
||||
logic data_is_held; // data in hold register is valid
|
||||
logic unit_busy; // valid data in flight
|
||||
// FSM states
|
||||
typedef enum logic [1:0] {IDLE, BUSY, HOLD} fsm_state_e;
|
||||
fsm_state_e state_q, state_d;
|
||||
|
||||
// Upstream ready comes from sanitization FSM
|
||||
assign inp_pipe_ready[NUM_INP_REGS] = in_ready;
|
||||
// Ready synch with other lanes
|
||||
// Bring the FSM-generated ready outside the unit, to synchronize it with the other lanes
|
||||
assign divsqrt_ready_o = in_ready;
|
||||
// Upstream ready comes from sanitization FSM, and it is synched among all the lanes
|
||||
assign inp_pipe_ready[NUM_INP_REGS] = simd_synch_rdy_i;
|
||||
|
||||
// Valid synch with other lanes
|
||||
// When one divsqrt unit completes an operation, keep its done high, waiting for the other lanes
|
||||
// As soon as all the lanes are over, we can clear this FF and start with a new operation
|
||||
`FFLARNC(unit_done_q, unit_done, unit_done, simd_synch_done_i, 1'b0, clk_i, rst_ni);
|
||||
// Tell the other units that this unit has finished now or in the past
|
||||
assign divsqrt_done_o = unit_done_q | unit_done;
|
||||
|
||||
// Valids are gated by the FSM ready. Invalid input ops run a sqrt to not lose illegal instr.
|
||||
assign div_valid = in_valid_q & (op_q == fpnew_pkg::DIV) & in_ready & ~flush_i;
|
||||
|
@ -177,8 +197,6 @@ module fpnew_divsqrt_multi #(
|
|||
// Default assignments
|
||||
in_ready = 1'b0;
|
||||
out_valid = 1'b0;
|
||||
hold_result = 1'b0;
|
||||
data_is_held = 1'b0;
|
||||
unit_busy = 1'b0;
|
||||
state_d = state_q;
|
||||
|
||||
|
@ -193,8 +211,8 @@ module fpnew_divsqrt_multi #(
|
|||
// Operation in progress
|
||||
BUSY: begin
|
||||
unit_busy = 1'b1; // data in flight
|
||||
// If the unit is done with processing
|
||||
if (unit_done) begin
|
||||
// If all the lanes are done with processing
|
||||
if (simd_synch_done_i) begin
|
||||
out_valid = 1'b1; // try to commit result downstream
|
||||
// If downstream accepts our result
|
||||
if (out_ready) begin
|
||||
|
@ -205,7 +223,6 @@ module fpnew_divsqrt_multi #(
|
|||
end
|
||||
// Otherwise if downstream is not ready for the result
|
||||
end else begin
|
||||
hold_result = 1'b1; // activate the hold register
|
||||
state_d = HOLD; // wait for the pipeline to take the data
|
||||
end
|
||||
end
|
||||
|
@ -213,7 +230,6 @@ module fpnew_divsqrt_multi #(
|
|||
// Waiting with valid result for downstream
|
||||
HOLD: begin
|
||||
unit_busy = 1'b1; // data in flight
|
||||
data_is_held = 1'b1; // data in hold register is valid
|
||||
out_valid = 1'b1; // try to commit result downstream
|
||||
// If the result is accepted by downstream
|
||||
if (out_ready) begin
|
||||
|
@ -242,11 +258,13 @@ module fpnew_divsqrt_multi #(
|
|||
// Hold additional information while the operation is in progress
|
||||
logic result_is_fp8_q;
|
||||
TagType result_tag_q;
|
||||
logic result_mask_q;
|
||||
AuxType result_aux_q;
|
||||
|
||||
// Fill the registers everytime a valid operation arrives (load FF, active low asynch rst)
|
||||
`FFL(result_is_fp8_q, input_is_fp8, op_starting, '0)
|
||||
`FFL(result_tag_q, inp_pipe_tag_q[NUM_INP_REGS], op_starting, '0)
|
||||
`FFL(result_mask_q, inp_pipe_mask_q[NUM_INP_REGS],op_starting, '0)
|
||||
`FFL(result_aux_q, inp_pipe_aux_q[NUM_INP_REGS], op_starting, '0)
|
||||
|
||||
// -----------------
|
||||
|
@ -255,6 +273,7 @@ module fpnew_divsqrt_multi #(
|
|||
logic [63:0] unit_result;
|
||||
logic [WIDTH-1:0] adjusted_result, held_result_q;
|
||||
fpnew_pkg::status_t unit_status, held_status_q;
|
||||
logic hold_en;
|
||||
|
||||
div_sqrt_top_mvp i_divsqrt_lei (
|
||||
.Clk_CI ( clk_i ),
|
||||
|
@ -276,9 +295,12 @@ module fpnew_divsqrt_multi #(
|
|||
// Adjust result width and fix FP8
|
||||
assign adjusted_result = result_is_fp8_q ? unit_result >> 8 : unit_result;
|
||||
|
||||
// Hold the result when one lane has finished execution, except when all the lanes finish together
|
||||
// and the result can be accepted downstream
|
||||
assign hold_en = unit_done & (~simd_synch_done_i | ~out_ready);
|
||||
// The Hold register (load, no reset)
|
||||
`FFLNR(held_result_q, adjusted_result, hold_result, clk_i)
|
||||
`FFLNR(held_status_q, unit_status, hold_result, clk_i)
|
||||
`FFLNR(held_result_q, adjusted_result, hold_en, clk_i)
|
||||
`FFLNR(held_status_q, unit_status, hold_en, clk_i)
|
||||
|
||||
// --------------
|
||||
// Output Select
|
||||
|
@ -286,8 +308,8 @@ module fpnew_divsqrt_multi #(
|
|||
logic [WIDTH-1:0] result_d;
|
||||
fpnew_pkg::status_t status_d;
|
||||
// Prioritize hold register data
|
||||
assign result_d = data_is_held ? held_result_q : adjusted_result;
|
||||
assign status_d = data_is_held ? held_status_q : unit_status;
|
||||
assign result_d = unit_done_q ? held_result_q : adjusted_result;
|
||||
assign status_d = unit_done_q ? held_status_q : unit_status;
|
||||
|
||||
// ----------------
|
||||
// Output Pipeline
|
||||
|
@ -296,6 +318,7 @@ module fpnew_divsqrt_multi #(
|
|||
logic [0:NUM_OUT_REGS][WIDTH-1:0] out_pipe_result_q;
|
||||
fpnew_pkg::status_t [0:NUM_OUT_REGS] out_pipe_status_q;
|
||||
TagType [0:NUM_OUT_REGS] out_pipe_tag_q;
|
||||
logic [0:NUM_OUT_REGS] out_pipe_mask_q;
|
||||
AuxType [0:NUM_OUT_REGS] out_pipe_aux_q;
|
||||
logic [0:NUM_OUT_REGS] out_pipe_valid_q;
|
||||
// Ready signal is combinatorial for all stages
|
||||
|
@ -305,6 +328,7 @@ module fpnew_divsqrt_multi #(
|
|||
assign out_pipe_result_q[0] = result_d;
|
||||
assign out_pipe_status_q[0] = status_d;
|
||||
assign out_pipe_tag_q[0] = result_tag_q;
|
||||
assign out_pipe_mask_q[0] = result_mask_q;
|
||||
assign out_pipe_aux_q[0] = result_aux_q;
|
||||
assign out_pipe_valid_q[0] = out_valid;
|
||||
// Input stage: Propagate pipeline ready signal to inside pipe
|
||||
|
@ -325,6 +349,7 @@ module fpnew_divsqrt_multi #(
|
|||
`FFL(out_pipe_result_q[i+1], out_pipe_result_q[i], reg_ena, '0)
|
||||
`FFL(out_pipe_status_q[i+1], out_pipe_status_q[i], reg_ena, '0)
|
||||
`FFL(out_pipe_tag_q[i+1], out_pipe_tag_q[i], reg_ena, TagType'('0))
|
||||
`FFL(out_pipe_mask_q[i+1], out_pipe_mask_q[i], reg_ena, '0)
|
||||
`FFL(out_pipe_aux_q[i+1], out_pipe_aux_q[i], reg_ena, AuxType'('0))
|
||||
end
|
||||
// Output stage: Ready travels backwards from output side, driven by downstream circuitry
|
||||
|
@ -334,6 +359,7 @@ module fpnew_divsqrt_multi #(
|
|||
assign status_o = out_pipe_status_q[NUM_OUT_REGS];
|
||||
assign extension_bit_o = 1'b1; // always NaN-Box result
|
||||
assign tag_o = out_pipe_tag_q[NUM_OUT_REGS];
|
||||
assign mask_o = out_pipe_mask_q[NUM_OUT_REGS];
|
||||
assign aux_o = out_pipe_aux_q[NUM_OUT_REGS];
|
||||
assign out_valid_o = out_pipe_valid_q[NUM_OUT_REGS];
|
||||
assign busy_o = (| {inp_pipe_valid_q, unit_busy, out_pipe_valid_q});
|
|
@ -8,6 +8,8 @@
|
|||
// 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.
|
||||
//
|
||||
// SPDX-License-Identifier: SHL-0.51
|
||||
|
||||
// Author: Stefan Mach <smach@iis.ee.ethz.ch>
|
||||
|
||||
|
@ -31,6 +33,7 @@ module fpnew_fma #(
|
|||
input fpnew_pkg::operation_e op_i,
|
||||
input logic op_mod_i,
|
||||
input TagType tag_i,
|
||||
input logic mask_i,
|
||||
input AuxType aux_i,
|
||||
// Input Handshake
|
||||
input logic in_valid_i,
|
||||
|
@ -41,6 +44,7 @@ module fpnew_fma #(
|
|||
output fpnew_pkg::status_t status_o,
|
||||
output logic extension_bit_o,
|
||||
output TagType tag_o,
|
||||
output logic mask_o,
|
||||
output AuxType aux_o,
|
||||
// Output handshake
|
||||
output logic out_valid_o,
|
||||
|
@ -64,8 +68,8 @@ module fpnew_fma #(
|
|||
// datapath leakage. This is either given by the exponent bits or the width of the LZC result.
|
||||
// In most reasonable FP formats the internal exponent will be wider than the LZC result.
|
||||
localparam int unsigned EXP_WIDTH = unsigned'(fpnew_pkg::maximum(EXP_BITS + 2, LZC_RESULT_WIDTH));
|
||||
// Shift amount width: maximum internal mantissa size is 3p+3 bits
|
||||
localparam int unsigned SHIFT_AMOUNT_WIDTH = $clog2(3 * PRECISION_BITS + 3);
|
||||
// Shift amount width: maximum internal mantissa size is 3p+4 bits
|
||||
localparam int unsigned SHIFT_AMOUNT_WIDTH = $clog2(3 * PRECISION_BITS + 5);
|
||||
// Pipelines
|
||||
localparam NUM_INP_REGS = PipeConfig == fpnew_pkg::BEFORE
|
||||
? NumPipeRegs
|
||||
|
@ -102,6 +106,7 @@ module fpnew_fma #(
|
|||
fpnew_pkg::operation_e [0:NUM_INP_REGS] inp_pipe_op_q;
|
||||
logic [0:NUM_INP_REGS] inp_pipe_op_mod_q;
|
||||
TagType [0:NUM_INP_REGS] inp_pipe_tag_q;
|
||||
logic [0:NUM_INP_REGS] inp_pipe_mask_q;
|
||||
AuxType [0:NUM_INP_REGS] inp_pipe_aux_q;
|
||||
logic [0:NUM_INP_REGS] inp_pipe_valid_q;
|
||||
// Ready signal is combinatorial for all stages
|
||||
|
@ -114,6 +119,7 @@ module fpnew_fma #(
|
|||
assign inp_pipe_op_q[0] = op_i;
|
||||
assign inp_pipe_op_mod_q[0] = op_mod_i;
|
||||
assign inp_pipe_tag_q[0] = tag_i;
|
||||
assign inp_pipe_mask_q[0] = mask_i;
|
||||
assign inp_pipe_aux_q[0] = aux_i;
|
||||
assign inp_pipe_valid_q[0] = in_valid_i;
|
||||
// Input stage: Propagate pipeline ready signal to updtream circuitry
|
||||
|
@ -137,6 +143,7 @@ module fpnew_fma #(
|
|||
`FFL(inp_pipe_op_q[i+1], inp_pipe_op_q[i], reg_ena, fpnew_pkg::FMADD)
|
||||
`FFL(inp_pipe_op_mod_q[i+1], inp_pipe_op_mod_q[i], reg_ena, '0)
|
||||
`FFL(inp_pipe_tag_q[i+1], inp_pipe_tag_q[i], reg_ena, TagType'('0))
|
||||
`FFL(inp_pipe_mask_q[i+1], inp_pipe_mask_q[i], reg_ena, '0)
|
||||
`FFL(inp_pipe_aux_q[i+1], inp_pipe_aux_q[i], reg_ena, AuxType'('0))
|
||||
end
|
||||
|
||||
|
@ -167,7 +174,7 @@ module fpnew_fma #(
|
|||
// | FNMSUB | \c 1 | FNMADD: Invert sign of operands A and C
|
||||
// | ADD | \c 0 | ADD: Set operand A to +1.0
|
||||
// | ADD | \c 1 | SUB: Set operand A to +1.0, invert sign of operand C
|
||||
// | MUL | \c 0 | MUL: Set operand C to +0.0
|
||||
// | MUL | \c 0 | MUL: Set operand C to +0.0 or -0.0 depending on the rounding mode
|
||||
// | *others* | \c - | *invalid*
|
||||
// \note \c op_mod_q always inverts the sign of the addend.
|
||||
always_comb begin : op_select
|
||||
|
@ -190,8 +197,11 @@ module fpnew_fma #(
|
|||
operand_a = '{sign: 1'b0, exponent: BIAS, mantissa: '0};
|
||||
info_a = '{is_normal: 1'b1, is_boxed: 1'b1, default: 1'b0}; //normal, boxed value.
|
||||
end
|
||||
fpnew_pkg::MUL: begin // Set addend to -0 (for proper rounding with RDN)
|
||||
operand_c = '{sign: 1'b1, exponent: '0, mantissa: '0};
|
||||
fpnew_pkg::MUL: begin // Set addend to +0 or -0, depending whether the rounding mode is RDN
|
||||
if (inp_pipe_rnd_mode_q[NUM_INP_REGS] == fpnew_pkg::RDN)
|
||||
operand_c = '{sign: 1'b0, exponent: '0, mantissa: '0};
|
||||
else
|
||||
operand_c = '{sign: 1'b1, exponent: '0, mantissa: '0};
|
||||
info_c = '{is_zero: 1'b1, is_boxed: 1'b1, default: 1'b0}; //zero, boxed value.
|
||||
end
|
||||
default: begin // propagate don't cares
|
||||
|
@ -403,6 +413,7 @@ module fpnew_fma #(
|
|||
fp_t [0:NUM_MID_REGS] mid_pipe_spec_res_q;
|
||||
fpnew_pkg::status_t [0:NUM_MID_REGS] mid_pipe_spec_stat_q;
|
||||
TagType [0:NUM_MID_REGS] mid_pipe_tag_q;
|
||||
logic [0:NUM_MID_REGS] mid_pipe_mask_q;
|
||||
AuxType [0:NUM_MID_REGS] mid_pipe_aux_q;
|
||||
logic [0:NUM_MID_REGS] mid_pipe_valid_q;
|
||||
// Ready signal is combinatorial for all stages
|
||||
|
@ -422,6 +433,7 @@ module fpnew_fma #(
|
|||
assign mid_pipe_spec_res_q[0] = special_result;
|
||||
assign mid_pipe_spec_stat_q[0] = special_status;
|
||||
assign mid_pipe_tag_q[0] = inp_pipe_tag_q[NUM_INP_REGS];
|
||||
assign mid_pipe_mask_q[0] = inp_pipe_mask_q[NUM_INP_REGS];
|
||||
assign mid_pipe_aux_q[0] = inp_pipe_aux_q[NUM_INP_REGS];
|
||||
assign mid_pipe_valid_q[0] = inp_pipe_valid_q[NUM_INP_REGS];
|
||||
// Input stage: Propagate pipeline ready signal to input pipe
|
||||
|
@ -453,6 +465,7 @@ module fpnew_fma #(
|
|||
`FFL(mid_pipe_spec_res_q[i+1], mid_pipe_spec_res_q[i], reg_ena, '0)
|
||||
`FFL(mid_pipe_spec_stat_q[i+1], mid_pipe_spec_stat_q[i], reg_ena, '0)
|
||||
`FFL(mid_pipe_tag_q[i+1], mid_pipe_tag_q[i], reg_ena, TagType'('0))
|
||||
`FFL(mid_pipe_mask_q[i+1], mid_pipe_mask_q[i], reg_ena, '0)
|
||||
`FFL(mid_pipe_aux_q[i+1], mid_pipe_aux_q[i], reg_ena, AuxType'('0))
|
||||
end
|
||||
// Output stage: assign selected pipe outputs to signals for later use
|
||||
|
@ -629,6 +642,7 @@ module fpnew_fma #(
|
|||
fp_t [0:NUM_OUT_REGS] out_pipe_result_q;
|
||||
fpnew_pkg::status_t [0:NUM_OUT_REGS] out_pipe_status_q;
|
||||
TagType [0:NUM_OUT_REGS] out_pipe_tag_q;
|
||||
logic [0:NUM_OUT_REGS] out_pipe_mask_q;
|
||||
AuxType [0:NUM_OUT_REGS] out_pipe_aux_q;
|
||||
logic [0:NUM_OUT_REGS] out_pipe_valid_q;
|
||||
// Ready signal is combinatorial for all stages
|
||||
|
@ -638,6 +652,7 @@ module fpnew_fma #(
|
|||
assign out_pipe_result_q[0] = result_d;
|
||||
assign out_pipe_status_q[0] = status_d;
|
||||
assign out_pipe_tag_q[0] = mid_pipe_tag_q[NUM_MID_REGS];
|
||||
assign out_pipe_mask_q[0] = mid_pipe_mask_q[NUM_MID_REGS];
|
||||
assign out_pipe_aux_q[0] = mid_pipe_aux_q[NUM_MID_REGS];
|
||||
assign out_pipe_valid_q[0] = mid_pipe_valid_q[NUM_MID_REGS];
|
||||
// Input stage: Propagate pipeline ready signal to inside pipe
|
||||
|
@ -658,6 +673,7 @@ module fpnew_fma #(
|
|||
`FFL(out_pipe_result_q[i+1], out_pipe_result_q[i], reg_ena, '0)
|
||||
`FFL(out_pipe_status_q[i+1], out_pipe_status_q[i], reg_ena, '0)
|
||||
`FFL(out_pipe_tag_q[i+1], out_pipe_tag_q[i], reg_ena, TagType'('0))
|
||||
`FFL(out_pipe_mask_q[i+1], out_pipe_mask_q[i], reg_ena, '0)
|
||||
`FFL(out_pipe_aux_q[i+1], out_pipe_aux_q[i], reg_ena, AuxType'('0))
|
||||
end
|
||||
// Output stage: Ready travels backwards from output side, driven by downstream circuitry
|
||||
|
@ -667,6 +683,7 @@ module fpnew_fma #(
|
|||
assign status_o = out_pipe_status_q[NUM_OUT_REGS];
|
||||
assign extension_bit_o = 1'b1; // always NaN-Box result
|
||||
assign tag_o = out_pipe_tag_q[NUM_OUT_REGS];
|
||||
assign mask_o = out_pipe_mask_q[NUM_OUT_REGS];
|
||||
assign aux_o = out_pipe_aux_q[NUM_OUT_REGS];
|
||||
assign out_valid_o = out_pipe_valid_q[NUM_OUT_REGS];
|
||||
assign busy_o = (| {inp_pipe_valid_q, mid_pipe_valid_q, out_pipe_valid_q});
|
|
@ -8,6 +8,8 @@
|
|||
// 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.
|
||||
//
|
||||
// SPDX-License-Identifier: SHL-0.51
|
||||
|
||||
// Author: Stefan Mach <smach@iis.ee.ethz.ch>
|
||||
|
||||
|
@ -34,6 +36,7 @@ module fpnew_fma_multi #(
|
|||
input fpnew_pkg::fp_format_e src_fmt_i, // format of the multiplicands
|
||||
input fpnew_pkg::fp_format_e dst_fmt_i, // format of the addend and result
|
||||
input TagType tag_i,
|
||||
input logic mask_i,
|
||||
input AuxType aux_i,
|
||||
// Input Handshake
|
||||
input logic in_valid_i,
|
||||
|
@ -44,6 +47,7 @@ module fpnew_fma_multi #(
|
|||
output fpnew_pkg::status_t status_o,
|
||||
output logic extension_bit_o,
|
||||
output TagType tag_o,
|
||||
output logic mask_o,
|
||||
output AuxType aux_o,
|
||||
// Output handshake
|
||||
output logic out_valid_o,
|
||||
|
@ -70,8 +74,8 @@ module fpnew_fma_multi #(
|
|||
// datapath leakage. This is either given by the exponent bits or the width of the LZC result.
|
||||
// In most reasonable FP formats the internal exponent will be wider than the LZC result.
|
||||
localparam int unsigned EXP_WIDTH = fpnew_pkg::maximum(SUPER_EXP_BITS + 2, LZC_RESULT_WIDTH);
|
||||
// Shift amount width: maximum internal mantissa size is 3p+3 bits
|
||||
localparam int unsigned SHIFT_AMOUNT_WIDTH = $clog2(3 * PRECISION_BITS + 3);
|
||||
// Shift amount width: maximum internal mantissa size is 3p+4 bits
|
||||
localparam int unsigned SHIFT_AMOUNT_WIDTH = $clog2(3 * PRECISION_BITS + 5);
|
||||
// Pipelines
|
||||
localparam NUM_INP_REGS = PipeConfig == fpnew_pkg::BEFORE
|
||||
? NumPipeRegs
|
||||
|
@ -115,6 +119,7 @@ module fpnew_fma_multi #(
|
|||
fpnew_pkg::fp_format_e [0:NUM_INP_REGS] inp_pipe_src_fmt_q;
|
||||
fpnew_pkg::fp_format_e [0:NUM_INP_REGS] inp_pipe_dst_fmt_q;
|
||||
TagType [0:NUM_INP_REGS] inp_pipe_tag_q;
|
||||
logic [0:NUM_INP_REGS] inp_pipe_mask_q;
|
||||
AuxType [0:NUM_INP_REGS] inp_pipe_aux_q;
|
||||
logic [0:NUM_INP_REGS] inp_pipe_valid_q;
|
||||
// Ready signal is combinatorial for all stages
|
||||
|
@ -129,6 +134,7 @@ module fpnew_fma_multi #(
|
|||
assign inp_pipe_src_fmt_q[0] = src_fmt_i;
|
||||
assign inp_pipe_dst_fmt_q[0] = dst_fmt_i;
|
||||
assign inp_pipe_tag_q[0] = tag_i;
|
||||
assign inp_pipe_mask_q[0] = mask_i;
|
||||
assign inp_pipe_aux_q[0] = aux_i;
|
||||
assign inp_pipe_valid_q[0] = in_valid_i;
|
||||
// Input stage: Propagate pipeline ready signal to updtream circuitry
|
||||
|
@ -154,6 +160,7 @@ module fpnew_fma_multi #(
|
|||
`FFL(inp_pipe_src_fmt_q[i+1], inp_pipe_src_fmt_q[i], reg_ena, fpnew_pkg::fp_format_e'(0))
|
||||
`FFL(inp_pipe_dst_fmt_q[i+1], inp_pipe_dst_fmt_q[i], reg_ena, fpnew_pkg::fp_format_e'(0))
|
||||
`FFL(inp_pipe_tag_q[i+1], inp_pipe_tag_q[i], reg_ena, TagType'('0))
|
||||
`FFL(inp_pipe_mask_q[i+1], inp_pipe_mask_q[i], reg_ena, '0)
|
||||
`FFL(inp_pipe_aux_q[i+1], inp_pipe_aux_q[i], reg_ena, AuxType'('0))
|
||||
end
|
||||
// Output stage: assign selected pipe outputs to signals for later use
|
||||
|
@ -216,7 +223,7 @@ module fpnew_fma_multi #(
|
|||
// | FNMSUB | \c 1 | FNMADD: Invert sign of operands A and C
|
||||
// | ADD | \c 0 | ADD: Set operand A to +1.0
|
||||
// | ADD | \c 1 | SUB: Set operand A to +1.0, invert sign of operand C
|
||||
// | MUL | \c 0 | MUL: Set operand C to +0.0
|
||||
// | MUL | \c 0 | MUL: Set operand C to +0.0 or -0.0 depending on the rounding mode
|
||||
// | *others* | \c - | *invalid*
|
||||
// \note \c op_mod_q always inverts the sign of the addend.
|
||||
always_comb begin : op_select
|
||||
|
@ -239,8 +246,11 @@ module fpnew_fma_multi #(
|
|||
operand_a = '{sign: 1'b0, exponent: fpnew_pkg::bias(src_fmt_q), mantissa: '0};
|
||||
info_a = '{is_normal: 1'b1, is_boxed: 1'b1, default: 1'b0}; //normal, boxed value.
|
||||
end
|
||||
fpnew_pkg::MUL: begin // Set addend to -0 (for proper rounding with RDN)
|
||||
operand_c = '{sign: 1'b1, exponent: '0, mantissa: '0};
|
||||
fpnew_pkg::MUL: begin // Set addend to +0 or -0, depending whether the rounding mode is RDN
|
||||
if (inp_pipe_rnd_mode_q[NUM_INP_REGS] == fpnew_pkg::RDN)
|
||||
operand_c = '{sign: 1'b0, exponent: '0, mantissa: '0};
|
||||
else
|
||||
operand_c = '{sign: 1'b1, exponent: '0, mantissa: '0};
|
||||
info_c = '{is_zero: 1'b1, is_boxed: 1'b1, default: 1'b0}; //zero, boxed value.
|
||||
end
|
||||
default: begin // propagate don't cares
|
||||
|
@ -336,6 +346,8 @@ module fpnew_fma_multi #(
|
|||
end
|
||||
end else begin : inactive_format
|
||||
assign fmt_special_result[fmt] = '{default: fpnew_pkg::DONT_CARE};
|
||||
assign fmt_special_status[fmt] = '0;
|
||||
assign fmt_result_is_special[fmt] = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -486,6 +498,7 @@ module fpnew_fma_multi #(
|
|||
fp_t [0:NUM_MID_REGS] mid_pipe_spec_res_q;
|
||||
fpnew_pkg::status_t [0:NUM_MID_REGS] mid_pipe_spec_stat_q;
|
||||
TagType [0:NUM_MID_REGS] mid_pipe_tag_q;
|
||||
logic [0:NUM_MID_REGS] mid_pipe_mask_q;
|
||||
AuxType [0:NUM_MID_REGS] mid_pipe_aux_q;
|
||||
logic [0:NUM_MID_REGS] mid_pipe_valid_q;
|
||||
// Ready signal is combinatorial for all stages
|
||||
|
@ -506,6 +519,7 @@ module fpnew_fma_multi #(
|
|||
assign mid_pipe_spec_res_q[0] = special_result;
|
||||
assign mid_pipe_spec_stat_q[0] = special_status;
|
||||
assign mid_pipe_tag_q[0] = inp_pipe_tag_q[NUM_INP_REGS];
|
||||
assign mid_pipe_mask_q[0] = inp_pipe_mask_q[NUM_INP_REGS];
|
||||
assign mid_pipe_aux_q[0] = inp_pipe_aux_q[NUM_INP_REGS];
|
||||
assign mid_pipe_valid_q[0] = inp_pipe_valid_q[NUM_INP_REGS];
|
||||
// Input stage: Propagate pipeline ready signal to input pipe
|
||||
|
@ -538,6 +552,7 @@ module fpnew_fma_multi #(
|
|||
`FFL(mid_pipe_spec_res_q[i+1], mid_pipe_spec_res_q[i], reg_ena, '0)
|
||||
`FFL(mid_pipe_spec_stat_q[i+1], mid_pipe_spec_stat_q[i], reg_ena, '0)
|
||||
`FFL(mid_pipe_tag_q[i+1], mid_pipe_tag_q[i], reg_ena, TagType'('0))
|
||||
`FFL(mid_pipe_mask_q[i+1], mid_pipe_mask_q[i], reg_ena, '0)
|
||||
`FFL(mid_pipe_aux_q[i+1], mid_pipe_aux_q[i], reg_ena, AuxType'('0))
|
||||
end
|
||||
// Output stage: assign selected pipe outputs to signals for later use
|
||||
|
@ -776,6 +791,7 @@ module fpnew_fma_multi #(
|
|||
logic [0:NUM_OUT_REGS][WIDTH-1:0] out_pipe_result_q;
|
||||
fpnew_pkg::status_t [0:NUM_OUT_REGS] out_pipe_status_q;
|
||||
TagType [0:NUM_OUT_REGS] out_pipe_tag_q;
|
||||
logic [0:NUM_OUT_REGS] out_pipe_mask_q;
|
||||
AuxType [0:NUM_OUT_REGS] out_pipe_aux_q;
|
||||
logic [0:NUM_OUT_REGS] out_pipe_valid_q;
|
||||
// Ready signal is combinatorial for all stages
|
||||
|
@ -785,6 +801,7 @@ module fpnew_fma_multi #(
|
|||
assign out_pipe_result_q[0] = result_d;
|
||||
assign out_pipe_status_q[0] = status_d;
|
||||
assign out_pipe_tag_q[0] = mid_pipe_tag_q[NUM_MID_REGS];
|
||||
assign out_pipe_mask_q[0] = mid_pipe_mask_q[NUM_MID_REGS];
|
||||
assign out_pipe_aux_q[0] = mid_pipe_aux_q[NUM_MID_REGS];
|
||||
assign out_pipe_valid_q[0] = mid_pipe_valid_q[NUM_MID_REGS];
|
||||
// Input stage: Propagate pipeline ready signal to inside pipe
|
||||
|
@ -805,6 +822,7 @@ module fpnew_fma_multi #(
|
|||
`FFL(out_pipe_result_q[i+1], out_pipe_result_q[i], reg_ena, '0)
|
||||
`FFL(out_pipe_status_q[i+1], out_pipe_status_q[i], reg_ena, '0)
|
||||
`FFL(out_pipe_tag_q[i+1], out_pipe_tag_q[i], reg_ena, TagType'('0))
|
||||
`FFL(out_pipe_mask_q[i+1], out_pipe_mask_q[i], reg_ena, '0)
|
||||
`FFL(out_pipe_aux_q[i+1], out_pipe_aux_q[i], reg_ena, AuxType'('0))
|
||||
end
|
||||
// Output stage: Ready travels backwards from output side, driven by downstream circuitry
|
||||
|
@ -814,6 +832,7 @@ module fpnew_fma_multi #(
|
|||
assign status_o = out_pipe_status_q[NUM_OUT_REGS];
|
||||
assign extension_bit_o = 1'b1; // always NaN-Box result
|
||||
assign tag_o = out_pipe_tag_q[NUM_OUT_REGS];
|
||||
assign mask_o = out_pipe_mask_q[NUM_OUT_REGS];
|
||||
assign aux_o = out_pipe_aux_q[NUM_OUT_REGS];
|
||||
assign out_valid_o = out_pipe_valid_q[NUM_OUT_REGS];
|
||||
assign busy_o = (| {inp_pipe_valid_q, mid_pipe_valid_q, out_pipe_valid_q});
|
|
@ -8,6 +8,8 @@
|
|||
// 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.
|
||||
//
|
||||
// SPDX-License-Identifier: SHL-0.51
|
||||
|
||||
// Author: Stefan Mach <smach@iis.ee.ethz.ch>
|
||||
|
||||
|
@ -31,6 +33,7 @@ module fpnew_noncomp #(
|
|||
input fpnew_pkg::operation_e op_i,
|
||||
input logic op_mod_i,
|
||||
input TagType tag_i,
|
||||
input logic mask_i,
|
||||
input AuxType aux_i,
|
||||
// Input Handshake
|
||||
input logic in_valid_i,
|
||||
|
@ -43,6 +46,7 @@ module fpnew_noncomp #(
|
|||
output fpnew_pkg::classmask_e class_mask_o,
|
||||
output logic is_class_o,
|
||||
output TagType tag_o,
|
||||
output logic mask_o,
|
||||
output AuxType aux_o,
|
||||
// Output handshake
|
||||
output logic out_valid_o,
|
||||
|
@ -87,6 +91,7 @@ module fpnew_noncomp #(
|
|||
fpnew_pkg::operation_e [0:NUM_INP_REGS] inp_pipe_op_q;
|
||||
logic [0:NUM_INP_REGS] inp_pipe_op_mod_q;
|
||||
TagType [0:NUM_INP_REGS] inp_pipe_tag_q;
|
||||
logic [0:NUM_INP_REGS] inp_pipe_mask_q;
|
||||
AuxType [0:NUM_INP_REGS] inp_pipe_aux_q;
|
||||
logic [0:NUM_INP_REGS] inp_pipe_valid_q;
|
||||
// Ready signal is combinatorial for all stages
|
||||
|
@ -99,6 +104,7 @@ module fpnew_noncomp #(
|
|||
assign inp_pipe_op_q[0] = op_i;
|
||||
assign inp_pipe_op_mod_q[0] = op_mod_i;
|
||||
assign inp_pipe_tag_q[0] = tag_i;
|
||||
assign inp_pipe_mask_q[0] = mask_i;
|
||||
assign inp_pipe_aux_q[0] = aux_i;
|
||||
assign inp_pipe_valid_q[0] = in_valid_i;
|
||||
// Input stage: Propagate pipeline ready signal to updtream circuitry
|
||||
|
@ -122,6 +128,7 @@ module fpnew_noncomp #(
|
|||
`FFL(inp_pipe_op_q[i+1], inp_pipe_op_q[i], reg_ena, fpnew_pkg::FMADD)
|
||||
`FFL(inp_pipe_op_mod_q[i+1], inp_pipe_op_mod_q[i], reg_ena, '0)
|
||||
`FFL(inp_pipe_tag_q[i+1], inp_pipe_tag_q[i], reg_ena, TagType'('0))
|
||||
`FFL(inp_pipe_mask_q[i+1], inp_pipe_mask_q[i], reg_ena, '0)
|
||||
`FFL(inp_pipe_aux_q[i+1], inp_pipe_aux_q[i], reg_ena, AuxType'('0))
|
||||
end
|
||||
|
||||
|
@ -352,6 +359,7 @@ module fpnew_noncomp #(
|
|||
fpnew_pkg::classmask_e [0:NUM_OUT_REGS] out_pipe_class_mask_q;
|
||||
logic [0:NUM_OUT_REGS] out_pipe_is_class_q;
|
||||
TagType [0:NUM_OUT_REGS] out_pipe_tag_q;
|
||||
logic [0:NUM_OUT_REGS] out_pipe_mask_q;
|
||||
AuxType [0:NUM_OUT_REGS] out_pipe_aux_q;
|
||||
logic [0:NUM_OUT_REGS] out_pipe_valid_q;
|
||||
// Ready signal is combinatorial for all stages
|
||||
|
@ -364,6 +372,7 @@ module fpnew_noncomp #(
|
|||
assign out_pipe_class_mask_q[0] = class_mask_d;
|
||||
assign out_pipe_is_class_q[0] = is_class_d;
|
||||
assign out_pipe_tag_q[0] = inp_pipe_tag_q[NUM_INP_REGS];
|
||||
assign out_pipe_mask_q[0] = inp_pipe_mask_q[NUM_INP_REGS];
|
||||
assign out_pipe_aux_q[0] = inp_pipe_aux_q[NUM_INP_REGS];
|
||||
assign out_pipe_valid_q[0] = inp_pipe_valid_q[NUM_INP_REGS];
|
||||
// Input stage: Propagate pipeline ready signal to inside pipe
|
||||
|
@ -387,6 +396,7 @@ module fpnew_noncomp #(
|
|||
`FFL(out_pipe_class_mask_q[i+1], out_pipe_class_mask_q[i], reg_ena, fpnew_pkg::QNAN)
|
||||
`FFL(out_pipe_is_class_q[i+1], out_pipe_is_class_q[i], reg_ena, '0)
|
||||
`FFL(out_pipe_tag_q[i+1], out_pipe_tag_q[i], reg_ena, TagType'('0))
|
||||
`FFL(out_pipe_mask_q[i+1], out_pipe_mask_q[i], reg_ena, '0)
|
||||
`FFL(out_pipe_aux_q[i+1], out_pipe_aux_q[i], reg_ena, AuxType'('0))
|
||||
end
|
||||
// Output stage: Ready travels backwards from output side, driven by downstream circuitry
|
||||
|
@ -398,6 +408,7 @@ module fpnew_noncomp #(
|
|||
assign class_mask_o = out_pipe_class_mask_q[NUM_OUT_REGS];
|
||||
assign is_class_o = out_pipe_is_class_q[NUM_OUT_REGS];
|
||||
assign tag_o = out_pipe_tag_q[NUM_OUT_REGS];
|
||||
assign mask_o = out_pipe_mask_q[NUM_OUT_REGS];
|
||||
assign aux_o = out_pipe_aux_q[NUM_OUT_REGS];
|
||||
assign out_valid_o = out_pipe_valid_q[NUM_OUT_REGS];
|
||||
assign busy_o = (| {inp_pipe_valid_q, out_pipe_valid_q});
|
|
@ -8,6 +8,8 @@
|
|||
// 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.
|
||||
//
|
||||
// SPDX-License-Identifier: SHL-0.51
|
||||
|
||||
// Author: Stefan Mach <smach@iis.ee.ethz.ch>
|
||||
|
||||
|
@ -22,9 +24,12 @@ module fpnew_opgroup_block #(
|
|||
parameter fpnew_pkg::fmt_unit_types_t FmtUnitTypes = '{default: fpnew_pkg::PARALLEL},
|
||||
parameter fpnew_pkg::pipe_config_t PipeConfig = fpnew_pkg::BEFORE,
|
||||
parameter type TagType = logic,
|
||||
parameter int unsigned TrueSIMDClass = 0,
|
||||
// Do not change
|
||||
localparam int unsigned NUM_FORMATS = fpnew_pkg::NUM_FP_FORMATS,
|
||||
localparam int unsigned NUM_OPERANDS = fpnew_pkg::num_operands(OpGroup)
|
||||
localparam int unsigned NUM_OPERANDS = fpnew_pkg::num_operands(OpGroup),
|
||||
localparam int unsigned NUM_LANES = fpnew_pkg::max_num_lanes(Width, FpFmtMask, EnableVectors),
|
||||
localparam type MaskType = logic [NUM_LANES-1:0]
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
@ -39,6 +44,7 @@ module fpnew_opgroup_block #(
|
|||
input fpnew_pkg::int_format_e int_fmt_i,
|
||||
input logic vectorial_op_i,
|
||||
input TagType tag_i,
|
||||
input MaskType simd_mask_i,
|
||||
// Input Handshake
|
||||
input logic in_valid_i,
|
||||
output logic in_ready_o,
|
||||
|
@ -90,6 +96,11 @@ module fpnew_opgroup_block #(
|
|||
|
||||
assign in_valid = in_valid_i & (dst_fmt_i == fmt); // enable selected format
|
||||
|
||||
// Forward masks related to the right SIMD lane
|
||||
localparam int unsigned INTERNAL_LANES = fpnew_pkg::num_lanes(Width, fpnew_pkg::fp_format_e'(fmt), EnableVectors);
|
||||
logic [INTERNAL_LANES-1:0] mask_slice;
|
||||
always_comb for (int b = 0; b < INTERNAL_LANES; b++) mask_slice[b] = simd_mask_i[(NUM_LANES/INTERNAL_LANES)*b];
|
||||
|
||||
fpnew_opgroup_fmt_slice #(
|
||||
.OpGroup ( OpGroup ),
|
||||
.FpFormat ( fpnew_pkg::fp_format_e'(fmt) ),
|
||||
|
@ -97,7 +108,8 @@ module fpnew_opgroup_block #(
|
|||
.EnableVectors ( EnableVectors ),
|
||||
.NumPipeRegs ( FmtPipeRegs[fmt] ),
|
||||
.PipeConfig ( PipeConfig ),
|
||||
.TagType ( TagType )
|
||||
.TagType ( TagType ),
|
||||
.TrueSIMDClass ( TrueSIMDClass )
|
||||
) i_fmt_slice (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
|
@ -108,6 +120,7 @@ module fpnew_opgroup_block #(
|
|||
.op_mod_i,
|
||||
.vectorial_op_i,
|
||||
.tag_i,
|
||||
.simd_mask_i ( mask_slice ),
|
||||
.in_valid_i ( in_valid ),
|
||||
.in_ready_o ( fmt_in_ready[fmt] ),
|
||||
.flush_i,
|
||||
|
@ -122,9 +135,9 @@ module fpnew_opgroup_block #(
|
|||
// If the format wants to use merged ops, tie off the dangling ones not used here
|
||||
end else if (FpFmtMask[fmt] && ANY_MERGED && !IS_FIRST_MERGED) begin : merged_unused
|
||||
|
||||
localparam FMT = fpnew_pkg::get_first_enabled_multi(FmtUnitTypes, FpFmtMask);
|
||||
// Ready is split up into formats
|
||||
assign fmt_in_ready[fmt] = fmt_in_ready[fpnew_pkg::get_first_enabled_multi(FmtUnitTypes,
|
||||
FpFmtMask)];
|
||||
assign fmt_in_ready[fmt] = fmt_in_ready[int'(FMT)];
|
||||
|
||||
assign fmt_out_valid[fmt] = 1'b0; // don't emit values
|
||||
assign fmt_busy[fmt] = 1'b0; // never busy
|
||||
|
@ -181,6 +194,7 @@ module fpnew_opgroup_block #(
|
|||
.int_fmt_i,
|
||||
.vectorial_op_i,
|
||||
.tag_i,
|
||||
.simd_mask_i ( simd_mask_i ),
|
||||
.in_valid_i ( in_valid ),
|
||||
.in_ready_o ( fmt_in_ready[FMT] ),
|
||||
.flush_i,
|
|
@ -8,6 +8,8 @@
|
|||
// 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.
|
||||
//
|
||||
// SPDX-License-Identifier: SHL-0.51
|
||||
|
||||
// Author: Stefan Mach <smach@iis.ee.ethz.ch>
|
||||
|
||||
|
@ -20,8 +22,11 @@ module fpnew_opgroup_fmt_slice #(
|
|||
parameter int unsigned NumPipeRegs = 0,
|
||||
parameter fpnew_pkg::pipe_config_t PipeConfig = fpnew_pkg::BEFORE,
|
||||
parameter type TagType = logic,
|
||||
parameter int unsigned TrueSIMDClass = 0,
|
||||
// Do not change
|
||||
localparam int unsigned NUM_OPERANDS = fpnew_pkg::num_operands(OpGroup)
|
||||
localparam int unsigned NUM_OPERANDS = fpnew_pkg::num_operands(OpGroup),
|
||||
localparam int unsigned NUM_LANES = fpnew_pkg::num_lanes(Width, FpFormat, EnableVectors),
|
||||
localparam type MaskType = logic [NUM_LANES-1:0]
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
@ -33,6 +38,7 @@ module fpnew_opgroup_fmt_slice #(
|
|||
input logic op_mod_i,
|
||||
input logic vectorial_op_i,
|
||||
input TagType tag_i,
|
||||
input MaskType simd_mask_i,
|
||||
// Input Handshake
|
||||
input logic in_valid_i,
|
||||
output logic in_ready_o,
|
||||
|
@ -50,7 +56,7 @@ module fpnew_opgroup_fmt_slice #(
|
|||
);
|
||||
|
||||
localparam int unsigned FP_WIDTH = fpnew_pkg::fp_width(FpFormat);
|
||||
localparam int unsigned NUM_LANES = fpnew_pkg::num_lanes(Width, FpFormat, EnableVectors);
|
||||
localparam int unsigned SIMD_WIDTH = unsigned'(Width/NUM_LANES);
|
||||
|
||||
|
||||
logic [NUM_LANES-1:0] lane_in_ready, lane_out_valid; // Handshake signals for the lanes
|
||||
|
@ -63,6 +69,7 @@ module fpnew_opgroup_fmt_slice #(
|
|||
logic [NUM_LANES-1:0] lane_ext_bit; // only the first one is actually used
|
||||
fpnew_pkg::classmask_e [NUM_LANES-1:0] lane_class_mask;
|
||||
TagType [NUM_LANES-1:0] lane_tags; // only the first one is actually used
|
||||
logic [NUM_LANES-1:0] lane_masks;
|
||||
logic [NUM_LANES-1:0] lane_vectorial, lane_busy, lane_is_class; // dito
|
||||
|
||||
logic result_is_vector, result_is_class;
|
||||
|
@ -113,6 +120,7 @@ module fpnew_opgroup_fmt_slice #(
|
|||
.op_i,
|
||||
.op_mod_i,
|
||||
.tag_i,
|
||||
.mask_i ( simd_mask_i[lane] ),
|
||||
.aux_i ( vectorial_op ), // Remember whether operation was vectorial
|
||||
.in_valid_i ( in_valid ),
|
||||
.in_ready_o ( lane_in_ready[lane] ),
|
||||
|
@ -121,6 +129,7 @@ module fpnew_opgroup_fmt_slice #(
|
|||
.status_o ( op_status ),
|
||||
.extension_bit_o ( lane_ext_bit[lane] ),
|
||||
.tag_o ( lane_tags[lane] ),
|
||||
.mask_o ( lane_masks[lane] ),
|
||||
.aux_o ( lane_vectorial[lane] ),
|
||||
.out_valid_o ( out_valid ),
|
||||
.out_ready_i ( out_ready ),
|
||||
|
@ -174,6 +183,7 @@ module fpnew_opgroup_fmt_slice #(
|
|||
.op_i,
|
||||
.op_mod_i,
|
||||
.tag_i,
|
||||
.mask_i ( simd_mask_i[lane] ),
|
||||
.aux_i ( vectorial_op ), // Remember whether operation was vectorial
|
||||
.in_valid_i ( in_valid ),
|
||||
.in_ready_o ( lane_in_ready[lane] ),
|
||||
|
@ -184,6 +194,7 @@ module fpnew_opgroup_fmt_slice #(
|
|||
.class_mask_o ( lane_class_mask[lane] ),
|
||||
.is_class_o ( lane_is_class[lane] ),
|
||||
.tag_o ( lane_tags[lane] ),
|
||||
.mask_o ( lane_masks[lane] ),
|
||||
.aux_o ( lane_vectorial[lane] ),
|
||||
.out_valid_o ( out_valid ),
|
||||
.out_ready_i ( out_ready ),
|
||||
|
@ -213,7 +224,10 @@ module fpnew_opgroup_fmt_slice #(
|
|||
assign slice_result[(unsigned'(lane)+1)*FP_WIDTH-1:unsigned'(lane)*FP_WIDTH] = local_result;
|
||||
|
||||
// Create Classification results
|
||||
if ((lane+1)*8 <= Width) begin : vectorial_class // vectorial class blocks are 8bits in size
|
||||
if (TrueSIMDClass && SIMD_WIDTH >= 10) begin : vectorial_true_class // true vectorial class blocks are 10bits in size
|
||||
assign slice_vec_class_result[lane*SIMD_WIDTH +: 10] = lane_class_mask[lane];
|
||||
assign slice_vec_class_result[(lane+1)*SIMD_WIDTH-1 -: SIMD_WIDTH-10] = '0;
|
||||
end else if ((lane+1)*8 <= Width) begin : vectorial_class // vectorial class blocks are 8bits in size
|
||||
assign local_sign = (lane_class_mask[lane] == fpnew_pkg::NEGINF ||
|
||||
lane_class_mask[lane] == fpnew_pkg::NEGNORM ||
|
||||
lane_class_mask[lane] == fpnew_pkg::NEGSUBNORM ||
|
||||
|
@ -246,9 +260,11 @@ module fpnew_opgroup_fmt_slice #(
|
|||
|
||||
localparam int unsigned CLASS_VEC_BITS = (NUM_LANES*8 > Width) ? 8 * (Width / 8) : NUM_LANES*8;
|
||||
|
||||
// Pad out unused vec_class bits
|
||||
if (CLASS_VEC_BITS < Width) begin : pad_vectorial_class
|
||||
assign slice_vec_class_result[Width-1:CLASS_VEC_BITS] = '0;
|
||||
// Pad out unused vec_class bits if each classify result is on 8 bits
|
||||
if (!(TrueSIMDClass && SIMD_WIDTH >= 10)) begin
|
||||
if (CLASS_VEC_BITS < Width) begin : pad_vectorial_class
|
||||
assign slice_vec_class_result[Width-1:CLASS_VEC_BITS] = '0;
|
||||
end
|
||||
end
|
||||
|
||||
// localparam logic [Width-1:0] CLASS_VEC_MASK = 2**CLASS_VEC_BITS - 1;
|
||||
|
@ -270,7 +286,7 @@ module fpnew_opgroup_fmt_slice #(
|
|||
automatic fpnew_pkg::status_t temp_status;
|
||||
temp_status = '0;
|
||||
for (int i = 0; i < int'(NUM_LANES); i++)
|
||||
temp_status |= lane_status[i];
|
||||
temp_status |= lane_status[i] & {5{lane_masks[i]}};
|
||||
status_o = temp_status;
|
||||
end
|
||||
endmodule
|
|
@ -8,6 +8,8 @@
|
|||
// 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.
|
||||
//
|
||||
// SPDX-License-Identifier: SHL-0.51
|
||||
|
||||
// Author: Stefan Mach <smach@iis.ee.ethz.ch>
|
||||
|
||||
|
@ -25,7 +27,9 @@ module fpnew_opgroup_multifmt_slice #(
|
|||
parameter type TagType = logic,
|
||||
// Do not change
|
||||
localparam int unsigned NUM_OPERANDS = fpnew_pkg::num_operands(OpGroup),
|
||||
localparam int unsigned NUM_FORMATS = fpnew_pkg::NUM_FP_FORMATS
|
||||
localparam int unsigned NUM_FORMATS = fpnew_pkg::NUM_FP_FORMATS,
|
||||
localparam int unsigned NUM_SIMD_LANES = fpnew_pkg::max_num_lanes(Width, FpFmtConfig, EnableVectors),
|
||||
localparam type MaskType = logic [NUM_SIMD_LANES-1:0]
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
@ -40,6 +44,7 @@ module fpnew_opgroup_multifmt_slice #(
|
|||
input fpnew_pkg::int_format_e int_fmt_i,
|
||||
input logic vectorial_op_i,
|
||||
input TagType tag_i,
|
||||
input MaskType simd_mask_i,
|
||||
// Input Handshake
|
||||
input logic in_valid_i,
|
||||
output logic in_ready_o,
|
||||
|
@ -65,7 +70,7 @@ module fpnew_opgroup_multifmt_slice #(
|
|||
fpnew_pkg::maximum($clog2(NUM_FORMATS), $clog2(NUM_INT_FORMATS));
|
||||
localparam int unsigned AUX_BITS = FMT_BITS + 2; // also add vectorial and integer flags
|
||||
|
||||
logic [NUM_LANES-1:0] lane_in_ready, lane_out_valid; // Handshake signals for the lanes
|
||||
logic [NUM_LANES-1:0] lane_in_ready, lane_out_valid, divsqrt_done, divsqrt_ready; // Handshake signals for the lanes
|
||||
logic vectorial_op;
|
||||
logic [FMT_BITS-1:0] dst_fmt; // destination format to pass along with operation
|
||||
logic [AUX_BITS-1:0] aux_data;
|
||||
|
@ -86,6 +91,7 @@ module fpnew_opgroup_multifmt_slice #(
|
|||
fpnew_pkg::status_t [NUM_LANES-1:0] lane_status;
|
||||
logic [NUM_LANES-1:0] lane_ext_bit; // only the first one is actually used
|
||||
TagType [NUM_LANES-1:0] lane_tags; // only the first one is actually used
|
||||
logic [NUM_LANES-1:0] lane_masks;
|
||||
logic [NUM_LANES-1:0][AUX_BITS-1:0] lane_aux; // only the first one is actually used
|
||||
logic [NUM_LANES-1:0] lane_busy; // dito
|
||||
|
||||
|
@ -94,6 +100,8 @@ module fpnew_opgroup_multifmt_slice #(
|
|||
logic result_fmt_is_int, result_is_cpk;
|
||||
logic [1:0] result_vec_op; // info for vectorial results (for packing)
|
||||
|
||||
logic simd_synch_rdy, simd_synch_done;
|
||||
|
||||
// -----------
|
||||
// Input Side
|
||||
// -----------
|
||||
|
@ -213,6 +221,7 @@ module fpnew_opgroup_multifmt_slice #(
|
|||
.src_fmt_i,
|
||||
.dst_fmt_i,
|
||||
.tag_i,
|
||||
.mask_i ( simd_mask_i[lane] ),
|
||||
.aux_i ( aux_data ),
|
||||
.in_valid_i ( in_valid ),
|
||||
.in_ready_o ( lane_in_ready[lane] ),
|
||||
|
@ -221,6 +230,7 @@ module fpnew_opgroup_multifmt_slice #(
|
|||
.status_o ( op_status ),
|
||||
.extension_bit_o ( lane_ext_bit[lane] ),
|
||||
.tag_o ( lane_tags[lane] ),
|
||||
.mask_o ( lane_masks[lane] ),
|
||||
.aux_o ( lane_aux[lane] ),
|
||||
.out_valid_o ( out_valid ),
|
||||
.out_ready_i ( out_ready ),
|
||||
|
@ -243,14 +253,20 @@ module fpnew_opgroup_multifmt_slice #(
|
|||
.op_i,
|
||||
.dst_fmt_i,
|
||||
.tag_i,
|
||||
.mask_i ( simd_mask_i[lane] ),
|
||||
.aux_i ( aux_data ),
|
||||
.in_valid_i ( in_valid ),
|
||||
.in_ready_o ( lane_in_ready[lane] ),
|
||||
.divsqrt_done_o ( divsqrt_done[lane] ),
|
||||
.simd_synch_done_i( simd_synch_done ),
|
||||
.divsqrt_ready_o ( divsqrt_ready[lane]),
|
||||
.simd_synch_rdy_i( simd_synch_rdy ),
|
||||
.flush_i,
|
||||
.result_o ( op_result ),
|
||||
.status_o ( op_status ),
|
||||
.extension_bit_o ( lane_ext_bit[lane] ),
|
||||
.tag_o ( lane_tags[lane] ),
|
||||
.mask_o ( lane_masks[lane] ),
|
||||
.aux_o ( lane_aux[lane] ),
|
||||
.out_valid_o ( out_valid ),
|
||||
.out_ready_i ( out_ready ),
|
||||
|
@ -278,6 +294,7 @@ module fpnew_opgroup_multifmt_slice #(
|
|||
.dst_fmt_i,
|
||||
.int_fmt_i,
|
||||
.tag_i,
|
||||
.mask_i ( simd_mask_i[lane] ),
|
||||
.aux_i ( aux_data ),
|
||||
.in_valid_i ( in_valid ),
|
||||
.in_ready_o ( lane_in_ready[lane] ),
|
||||
|
@ -286,6 +303,7 @@ module fpnew_opgroup_multifmt_slice #(
|
|||
.status_o ( op_status ),
|
||||
.extension_bit_o ( lane_ext_bit[lane] ),
|
||||
.tag_o ( lane_tags[lane] ),
|
||||
.mask_o ( lane_masks[lane] ),
|
||||
.aux_o ( lane_aux[lane] ),
|
||||
.out_valid_o ( out_valid ),
|
||||
.out_ready_i ( out_ready ),
|
||||
|
@ -315,9 +333,16 @@ module fpnew_opgroup_multifmt_slice #(
|
|||
// Set up some constants
|
||||
localparam int unsigned FP_WIDTH = fpnew_pkg::fp_width(fpnew_pkg::fp_format_e'(fmt));
|
||||
// only for active formats within the lane
|
||||
if (ACTIVE_FORMATS[fmt])
|
||||
if (ACTIVE_FORMATS[fmt]) begin
|
||||
assign fmt_slice_result[fmt][(LANE+1)*FP_WIDTH-1:LANE*FP_WIDTH] =
|
||||
local_result[FP_WIDTH-1:0];
|
||||
end else if ((LANE+1)*FP_WIDTH <= Width) begin
|
||||
assign fmt_slice_result[fmt][(LANE+1)*FP_WIDTH-1:LANE*FP_WIDTH] =
|
||||
'{default: lane_ext_bit[LANE]};
|
||||
end else if (LANE*FP_WIDTH < Width) begin
|
||||
assign fmt_slice_result[fmt][Width-1:LANE*FP_WIDTH] =
|
||||
'{default: lane_ext_bit[LANE]};
|
||||
end
|
||||
end
|
||||
|
||||
// Generate result packing depending on integer format
|
||||
|
@ -325,9 +350,14 @@ module fpnew_opgroup_multifmt_slice #(
|
|||
for (genvar ifmt = 0; ifmt < NUM_INT_FORMATS; ifmt++) begin : pack_int_result
|
||||
// Set up some constants
|
||||
localparam int unsigned INT_WIDTH = fpnew_pkg::int_width(fpnew_pkg::int_format_e'(ifmt));
|
||||
if (ACTIVE_INT_FORMATS[ifmt])
|
||||
if (ACTIVE_INT_FORMATS[ifmt]) begin
|
||||
assign ifmt_slice_result[ifmt][(LANE+1)*INT_WIDTH-1:LANE*INT_WIDTH] =
|
||||
local_result[INT_WIDTH-1:0];
|
||||
end else if ((LANE+1)*INT_WIDTH <= Width) begin
|
||||
assign ifmt_slice_result[ifmt][(LANE+1)*INT_WIDTH-1:LANE*INT_WIDTH] = '0;
|
||||
end else if (LANE*INT_WIDTH < Width) begin
|
||||
assign ifmt_slice_result[ifmt][Width-1:LANE*INT_WIDTH] = '0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -387,6 +417,10 @@ module fpnew_opgroup_multifmt_slice #(
|
|||
assign {result_vec_op, result_is_cpk} = '0;
|
||||
end
|
||||
|
||||
// Synch lanes if there is more than one
|
||||
assign simd_synch_rdy = EnableVectors ? &divsqrt_ready : divsqrt_ready[0];
|
||||
assign simd_synch_done = EnableVectors ? &divsqrt_done : divsqrt_done[0];
|
||||
|
||||
// ------------
|
||||
// Output Side
|
||||
// ------------
|
||||
|
@ -408,7 +442,8 @@ module fpnew_opgroup_multifmt_slice #(
|
|||
automatic fpnew_pkg::status_t temp_status;
|
||||
temp_status = '0;
|
||||
for (int i = 0; i < int'(NUM_LANES); i++)
|
||||
temp_status |= lane_status[i];
|
||||
temp_status |= lane_status[i] & {5{lane_masks[i]}};
|
||||
status_o = temp_status;
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -8,6 +8,8 @@
|
|||
// 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.
|
||||
//
|
||||
// SPDX-License-Identifier: SHL-0.51
|
||||
|
||||
// Author: Stefan Mach <smach@iis.ee.ethz.ch>
|
||||
|
||||
|
@ -89,6 +91,14 @@ package fpnew_pkg;
|
|||
INT16: return 16;
|
||||
INT32: return 32;
|
||||
INT64: return 64;
|
||||
default: begin
|
||||
// pragma translate_off
|
||||
$fatal(1, "Invalid INT format supplied");
|
||||
// pragma translate_on
|
||||
// just return any integer to avoid any latches
|
||||
// hopefully this error is caught by simulation
|
||||
return INT8;
|
||||
end
|
||||
endcase
|
||||
endfunction
|
||||
|
||||
|
@ -123,6 +133,7 @@ package fpnew_pkg;
|
|||
RDN = 3'b010,
|
||||
RUP = 3'b011,
|
||||
RMM = 3'b100,
|
||||
ROD = 3'b101, // This mode is not defined in RISC-V FP-SPEC
|
||||
DYN = 3'b111
|
||||
} roundmode_e;
|
||||
|
|
@ -8,6 +8,8 @@
|
|||
// 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.
|
||||
//
|
||||
// SPDX-License-Identifier: SHL-0.51
|
||||
|
||||
// Author: Stefan Mach <smach@iis.ee.ethz.ch>
|
||||
|
||||
|
@ -38,6 +40,7 @@ module fpnew_rounding #(
|
|||
// 010 | RDN | Round Down (towards -\infty)
|
||||
// 011 | RUP | Round Up (towards \infty)
|
||||
// 100 | RMM | Round to Nearest, ties to Max Magnitude
|
||||
// 101 | ROD | Round towards odd (this mode is not define in RISC-V FP-SPEC)
|
||||
// others | | *invalid*
|
||||
always_comb begin : rounding_decision
|
||||
unique case (rnd_mode_i)
|
||||
|
@ -53,6 +56,7 @@ module fpnew_rounding #(
|
|||
fpnew_pkg::RDN: round_up = (| round_sticky_bits_i) ? sign_i : 1'b0; // to 0 if +, away if -
|
||||
fpnew_pkg::RUP: round_up = (| round_sticky_bits_i) ? ~sign_i : 1'b0; // to 0 if -, away if +
|
||||
fpnew_pkg::RMM: round_up = round_sticky_bits_i[1]; // round down if < ulp/2 away, else up
|
||||
fpnew_pkg::ROD: round_up = ~abs_value_i[0] & (| round_sticky_bits_i);
|
||||
default: round_up = fpnew_pkg::DONT_CARE; // propagate x
|
||||
endcase
|
||||
end
|
|
@ -8,6 +8,8 @@
|
|||
// 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.
|
||||
//
|
||||
// SPDX-License-Identifier: SHL-0.51
|
||||
|
||||
// Author: Stefan Mach <smach@iis.ee.ethz.ch>
|
||||
|
||||
|
@ -16,7 +18,11 @@ module fpnew_top #(
|
|||
parameter fpnew_pkg::fpu_features_t Features = fpnew_pkg::RV64D_Xsflt,
|
||||
parameter fpnew_pkg::fpu_implementation_t Implementation = fpnew_pkg::DEFAULT_NOREGS,
|
||||
parameter type TagType = logic,
|
||||
parameter int unsigned TrueSIMDClass = 0,
|
||||
parameter int unsigned EnableSIMDMask = 0,
|
||||
// Do not change
|
||||
localparam int unsigned NumLanes = fpnew_pkg::max_num_lanes(Features.Width, Features.FpFmtMask, Features.EnableVectors),
|
||||
localparam type MaskType = logic [NumLanes-1:0],
|
||||
localparam int unsigned WIDTH = Features.Width,
|
||||
localparam int unsigned NUM_OPERANDS = 3
|
||||
) (
|
||||
|
@ -32,6 +38,7 @@ module fpnew_top #(
|
|||
input fpnew_pkg::int_format_e int_fmt_i,
|
||||
input logic vectorial_op_i,
|
||||
input TagType tag_i,
|
||||
input MaskType simd_mask_i,
|
||||
// Input Handshake
|
||||
input logic in_valid_i,
|
||||
output logic in_ready_o,
|
||||
|
@ -85,6 +92,10 @@ module fpnew_top #(
|
|||
end
|
||||
end
|
||||
|
||||
// Filter out the mask if not used
|
||||
MaskType simd_mask;
|
||||
assign simd_mask = simd_mask_i | ~{NumLanes{logic'(EnableSIMDMask)}};
|
||||
|
||||
// -------------------------
|
||||
// Generate Operation Blocks
|
||||
// -------------------------
|
||||
|
@ -111,7 +122,8 @@ module fpnew_top #(
|
|||
.FmtPipeRegs ( Implementation.PipeRegs[opgrp] ),
|
||||
.FmtUnitTypes ( Implementation.UnitTypes[opgrp] ),
|
||||
.PipeConfig ( Implementation.PipeConfig ),
|
||||
.TagType ( TagType )
|
||||
.TagType ( TagType ),
|
||||
.TrueSIMDClass ( TrueSIMDClass )
|
||||
) i_opgroup_block (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
|
@ -125,6 +137,7 @@ module fpnew_top #(
|
|||
.int_fmt_i,
|
||||
.vectorial_op_i,
|
||||
.tag_i,
|
||||
.simd_mask_i ( simd_mask ),
|
||||
.in_valid_i ( in_valid ),
|
||||
.in_ready_o ( opgrp_in_ready[opgrp] ),
|
||||
.flush_i,
|
25
vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/CHANGELOG.md
vendored
Normal file
25
vendor/openhwgroup/cvfpu/src/fpu_div_sqrt_mvp/CHANGELOG.md
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
In this sense, we interpret the "Public API" of a hardware module as its port/parameter list.
|
||||
Versions of the IP in the same major relase are "pin-compatible" with each other. Minor relases are permitted to add new parameters as long as their default bindings ensure backwards compatibility.
|
||||
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
### Changed
|
||||
### Fixed
|
||||
|
||||
|
||||
## [1.0.4] - 2020-10-05
|
||||
|
||||
### Added
|
||||
- Started formal changelog
|
||||
|
||||
### Changed
|
||||
### Fixed
|
||||
- Signalling behavior for underflows to 0.0
|
|
@ -273,28 +273,14 @@ module norm_div_sqrt_mvp
|
|||
|
||||
else if(Exp_in_DI[C_EXP_FP64+1]) //minus //consider format
|
||||
begin
|
||||
if(((~Exp_Max_RS_FP32_D[C_EXP_FP32+1])&&FP32_SI) | ((~Exp_Max_RS_FP64_D[C_EXP_FP64+1])&&FP64_SI) | ((~Exp_Max_RS_FP16_D[C_EXP_FP16+1])&&FP16_SI) | ((~Exp_Max_RS_FP16ALT_D[C_EXP_FP16ALT+1])&&FP16ALT_SI) ) //OF EXP<0 after RS
|
||||
begin
|
||||
Div_Zero_S=1'b0;
|
||||
Exp_OF_S=1'b1;
|
||||
Exp_UF_S=1'b0;
|
||||
Mant_res_norm_D='0;
|
||||
Exp_res_norm_D='0;
|
||||
Mant_forround_D='0;
|
||||
Sign_res_D=Sign_in_DI;
|
||||
NV_OP_S = 1'b0;
|
||||
end
|
||||
else //denormal
|
||||
begin
|
||||
Div_Zero_S=1'b0;
|
||||
Exp_OF_S=1'b0;
|
||||
Exp_UF_S=1'b1;
|
||||
Mant_res_norm_D={Mant_RS_D[C_MANT_FP64:0]};
|
||||
Exp_res_norm_D='0;
|
||||
Mant_forround_D={Mant_forsticky_D[C_MANT_FP64+4:0]}; //??
|
||||
Sign_res_D=Sign_in_DI;
|
||||
NV_OP_S = 1'b0;
|
||||
end
|
||||
Div_Zero_S=1'b0;
|
||||
Exp_OF_S=1'b0;
|
||||
Exp_UF_S=1'b1;
|
||||
Mant_res_norm_D={Mant_RS_D[C_MANT_FP64:0]};
|
||||
Exp_res_norm_D='0;
|
||||
Mant_forround_D={Mant_forsticky_D[C_MANT_FP64+4:0]}; //??
|
||||
Sign_res_D=Sign_in_DI;
|
||||
NV_OP_S = 1'b0;
|
||||
end
|
||||
|
||||
else if( (Exp_in_DI[C_EXP_FP32]&&FP32_SI) | (Exp_in_DI[C_EXP_FP64]&&FP64_SI) | (Exp_in_DI[C_EXP_FP16]&&FP16_SI) | (Exp_in_DI[C_EXP_FP16ALT]&&FP16ALT_SI) ) //OF
|
|
@ -8,7 +8,7 @@
|
|||
{
|
||||
upstream:
|
||||
{
|
||||
url: https://github.com/pulp-platform/fpnew.git
|
||||
rev: 79f75e0a0fdab6ebc3840a14077c39f4934321fe
|
||||
url: https://github.com/openhwgroup/cvfpu
|
||||
rev: 3116391bf66660f806b45e212b9949c528b4e270
|
||||
}
|
||||
}
|
|
@ -5,21 +5,21 @@
|
|||
|
||||
{
|
||||
// Name of the project
|
||||
name: "pulp_fpnew",
|
||||
name: "openhwgroup_cvfpu",
|
||||
|
||||
// Target directory: relative to the location of this script.
|
||||
target_dir: "pulp-platform/fpnew",
|
||||
target_dir: "openhwgroup/cvfpu",
|
||||
|
||||
// Upstream repository
|
||||
upstream: {
|
||||
// URL
|
||||
url: "https://github.com/pulp-platform/fpnew.git",
|
||||
url: "https://github.com/openhwgroup/cvfpu",
|
||||
// revision
|
||||
rev: "v0.6.2",
|
||||
rev: "v0.7.0",
|
||||
}
|
||||
|
||||
// Patch dir for local changes
|
||||
patch_dir: "patches/pulp-platform/fpnew",
|
||||
patch_dir: "patches/openhwgroup/cvfpu",
|
||||
|
||||
// Exclusions from upstream content
|
||||
exclude_from_upstream: [
|
|
@ -1,7 +0,0 @@
|
|||
.*
|
||||
!.git*
|
||||
*.out
|
||||
*~
|
||||
/Bender.lock
|
||||
/Bender.local
|
||||
build
|
|
@ -1,210 +0,0 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
|
||||
## 1.13.1 - 2019-06-01
|
||||
|
||||
### Changed
|
||||
|
||||
- Fix path in `src_files.yml` for `stream_arbiter` and `stream_arbiter_flushable`
|
||||
|
||||
## 1.13.0 - 2019-05-29
|
||||
|
||||
### Added
|
||||
|
||||
- Added exponential backoff window module
|
||||
- Added parametric Galois LFSR module with optional whitening feature
|
||||
- Added `cf_math_pkg`: Constant Function implementations of mathematical functions for HDL elaboration
|
||||
|
||||
### Changed
|
||||
- Parametric payload data type for `rr_arb_tree`
|
||||
|
||||
### Deprecated
|
||||
- The following arbiter implementations are deprecated and superseded by `rr_arb_tree`:
|
||||
- Priority arbiter `prioarbiter`
|
||||
- Round-robin arbiter `rrarbiter`
|
||||
|
||||
### Fixed
|
||||
|
||||
## 1.12.0 - 2019-04-09
|
||||
|
||||
### Added
|
||||
- Add priority arbiter
|
||||
- Add Pseudo Least Recently Used tree
|
||||
- Add round robin arbiter mux tree
|
||||
|
||||
### Changed
|
||||
- Add selectable arbiter implementation for `stream_arbiter` and `stream_arbiter_flushable`. One can choose between priority (`prio`) and round-robin arbitration (`rr`).
|
||||
- Add `$onehot0` assertion in one-hot to bin
|
||||
- Rework `rrarbiter` unit (uses `rr_arb_tree` implementation underneath)
|
||||
|
||||
## 1.11.0 - 2019-03-20
|
||||
|
||||
### Added
|
||||
- Add stream fork
|
||||
- Add fall-through register
|
||||
- Add stream filter
|
||||
- Add ID queue
|
||||
|
||||
### Changed
|
||||
- `sync_wedge` use existing synchronizer. This defines a single place where a tech-specific synchronizer can be defined.
|
||||
|
||||
### Fixed
|
||||
- Fix FIFO push and pop signals in `stream_register` to observe interface prerequisites.
|
||||
- In `fifo_v3`, fix data output when pushing into empty fall-through FIFO. Previously, the data
|
||||
output of an empty fall-through FIFO with data at its input (and `push_i=1`) depended on
|
||||
`pop_i`: When `pop_i=0`, old, invalid data were visible at the output (even though `empty_o=0`,
|
||||
indicating that the data output is valid). Only when `pop_i=1`, the data from the input fell
|
||||
through. One consequence of this bug was that `data_o` of the `fall_through_register` could change
|
||||
while `valid_o=1`, violating the basic stream specification.
|
||||
|
||||
## 1.10.0 - 2018-12-18
|
||||
|
||||
### Added
|
||||
- Add `fifo_v3` with generic fill count
|
||||
- Add 16 bit LFSR
|
||||
- Add stream delayer
|
||||
- Add stream arbiter
|
||||
- Add register macros for RTL
|
||||
- Add shift register
|
||||
|
||||
### Changed
|
||||
- Make number of registers of `rstgen_bypass` a parameter.
|
||||
|
||||
### Fixed
|
||||
- Fix `valid_i` and `grant_i` guarantees in `generic_fifo` for backward compatibility.
|
||||
- LZC: Synthesis of streaming operators in ternary operators
|
||||
- Add missing entry for `popcount` to `Bender.yml`.
|
||||
- Add default values for parameters to improve compatibility with Synopsys DC and Vivado.
|
||||
|
||||
## 1.9.0 - 2018-11-02
|
||||
|
||||
### Added
|
||||
- Add popcount circuit `popcount`
|
||||
|
||||
## 1.8.0 - 2018-10-15
|
||||
|
||||
### Added
|
||||
- Add lock feature to the rrarbiter. This prevents the arbiter to change the decision when we have pending requests that remain unaknowledged for several cycles.
|
||||
- Add deglitching circuit
|
||||
- Add generic clock divider
|
||||
- Add edge detecter as alias to sync_wedge (name is more expressive)
|
||||
- Add generic counter
|
||||
- Add moving deglitcher
|
||||
|
||||
## 1.7.6 - 2018-09-27
|
||||
|
||||
### Added
|
||||
- Add reset synchronizer with explicit reset bypass in testmode
|
||||
|
||||
## 1.7.5 - 2018-09-06
|
||||
### Fixed
|
||||
- Fix incompatibility with verilator
|
||||
- Fix dependency to open-source repo
|
||||
|
||||
## 1.7.4 - 2018-09-06
|
||||
- Fix assertions in `fifo_v2` (write on full / read on empty did not trigger properly)
|
||||
|
||||
## 1.7.3 - 2018-08-27
|
||||
### Fixed
|
||||
- Use proper `fifo_v2` in `generic_fifo` module.
|
||||
|
||||
## 1.7.2 - 2018-08-27
|
||||
### Added
|
||||
- Almost full/empty flags to FIFO, as `fifo_v2`.
|
||||
|
||||
### Changed
|
||||
- FIFO moved to `fifo_v1` and instantiates `fifo_v2`.
|
||||
|
||||
## 1.7.1 - 2018-08-27
|
||||
### Fixed
|
||||
- Revert breaking changes to `fifo`.
|
||||
|
||||
## 1.7.0 - 2018-08-24
|
||||
### Added
|
||||
- Add stream register (`stream_register`).
|
||||
- Add stream multiplexer and demultiplexer (`stream_mux`, `stream_demux`).
|
||||
- Add round robin arbiter (`rrarbiter`).
|
||||
- Add leading zero counter (`lzc`).
|
||||
|
||||
### Changed
|
||||
- Deprecate `find_first_one` in favor of `lzc`.
|
||||
|
||||
## 1.6.0 - 2018-04-03
|
||||
### Added
|
||||
- Add binary to Gray code converter.
|
||||
- Add Gray code to binary converter.
|
||||
- Add Gray code testbench.
|
||||
- Add CDC FIFO based on Gray counters. This is a faster alternative to the 2-phase FIFO which also works if a domain's clock has stopped.
|
||||
|
||||
### Changed
|
||||
- Rename `cdc_fifo` to `cdc_fifo_2phase`.
|
||||
- Adjust CDC FIFO testbench to cover both implementations.
|
||||
|
||||
## 1.5.4 - 2018-03-31
|
||||
### Changed
|
||||
- Replace explicit clock gate in `fifo` with implicit one.
|
||||
|
||||
## 1.5.3 - 2018-03-16
|
||||
### Changed
|
||||
- Remove duplicate deprecated modules.
|
||||
|
||||
## 1.5.2 - 2018-03-16
|
||||
### Changed
|
||||
- Remove deprecated `rstgen` and fix interface.
|
||||
|
||||
## 1.5.1 - 2018-03-16
|
||||
### Changed
|
||||
- Remove deprecated `onehot_to_bin`.
|
||||
|
||||
## 1.5.0 - 2018-03-14
|
||||
### Added
|
||||
- Add behavioural SRAM model
|
||||
|
||||
## 1.4.0 - 2018-03-14
|
||||
### Added
|
||||
- Clock domain crossing FIFO
|
||||
|
||||
### Changed
|
||||
- Re-name new sync modules to resolve namespace collisions
|
||||
|
||||
## 1.3.0 - 2018-03-12
|
||||
### Added
|
||||
- 2-phase clock domain crossing
|
||||
- Add old common cells as deprecated legacy modules
|
||||
|
||||
## 1.2.3 - 2018-03-09
|
||||
### Added
|
||||
- Backwards compatibility wrapper for `generic_LFSR_8bit`
|
||||
|
||||
## 1.2.2 - 2018-03-09
|
||||
### Added
|
||||
- Backwards compatibility wrapper for `generic_fifo`
|
||||
|
||||
## 1.2.1 - 2018-03-09
|
||||
### Fixed
|
||||
- Fix an issue in the spill register which causes transactions to be lost
|
||||
|
||||
## 1.2.0 - 2018-03-09
|
||||
### Added
|
||||
- Add spill register
|
||||
|
||||
## 1.1.0 - 2018-03-06
|
||||
### Added
|
||||
- Find first zero
|
||||
|
||||
## 1.0.0 - 2018-03-02
|
||||
### Added
|
||||
- Re-implementation of the generic FIFO supporting all kinds of use-cases
|
||||
- Testbench for FIFO
|
||||
|
||||
### Changed
|
||||
- Re-formatting and artistic code clean-up
|
||||
|
||||
## 0.1.0 - 2018-02-23
|
||||
### Added
|
||||
- Fork of PULP common cells repository
|
|
@ -1,117 +0,0 @@
|
|||
# Common Cells Repository
|
||||
|
||||
Maintainer: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
|
||||
|
||||
This repository contains commonly used cells and headers for use in various projects.
|
||||
|
||||
## Cell Contents
|
||||
|
||||
This repository currently contains the following cells, ordered by categories.
|
||||
Please note that cells with status *deprecated* are not to be used for new designs and only serve to provide compatibility with old code.
|
||||
|
||||
### Clocks and Resets
|
||||
|
||||
| Name | Description | Status | Superseded By |
|
||||
|-------------------------|-----------------------------------------------------|--------------|---------------|
|
||||
| `clk_div` | Clock divider with integer divisor | active | |
|
||||
| `clock_divider` | Clock divider with configuration registers | *deprecated* | `clk_div` |
|
||||
| `clock_divider_counter` | Clock divider using a counter | *deprecated* | `clk_div` |
|
||||
| `rstgen` | Reset synchronizer | active | |
|
||||
| `rstgen_bypass` | Reset synchronizer with dedicated test reset bypass | active | |
|
||||
|
||||
### Clock Domains and Asynchronous Crossings
|
||||
|
||||
| Name | Description | Status | Superseded By |
|
||||
|----------------------|----------------------------------------------------------------------------------|--------------|---------------|
|
||||
| `cdc_2phase` | Clock domain crossing using two-phase handshake, with ready/valid interface | active | |
|
||||
| `cdc_fifo_2phase` | Clock domain crossing FIFO using two-phase handshake, with ready/valid interface | active | |
|
||||
| `cdc_fifo_gray` | Clock domain crossing FIFO using a gray-counter, with ready/valid interface | active | |
|
||||
| `edge_detect` | Rising/falling edge detector | active | |
|
||||
| `edge_propagator` | **ANTONIO ADD DESCRIPTION** | active | |
|
||||
| `edge_propagator_rx` | **ANTONIO ADD DESCRIPTION** | active | |
|
||||
| `edge_propagator_tx` | **ANTONIO ADD DESCRIPTION** | active | |
|
||||
| `pulp_sync` | Serial line synchronizer | *deprecated* | `sync` |
|
||||
| `pulp_sync_wedge` | Serial line synchronizer with edge detector | *deprecated* | `sync_wedge` |
|
||||
| `serial_deglitch` | Serial line deglitcher | active | |
|
||||
| `sync` | Serial line synchronizer | active | |
|
||||
| `sync_wedge` | Serial line synchronizer with edge detector | active | |
|
||||
|
||||
### Counters and Shift Registers
|
||||
|
||||
| Name | Description | Status | Superseded By |
|
||||
|---------------------|-------------------------------------------------------------------|--------------|---------------|
|
||||
| `counter` | Generic up/down counter with overflow detection | active | |
|
||||
| `generic_LFSR_8bit` | 8-bit linear feedback shift register (LFSR) | *deprecated* | `lfsr_8bit` |
|
||||
| `lfsr_8bit` | 8-bit linear feedback shift register (LFSR) | active | |
|
||||
| `lfsr_16bit` | 16-bit linear feedback shift register (LFSR) | active | |
|
||||
| `lfsr` | 4...64-bit parametric Galois LFSR with optional whitening feature | active | |
|
||||
| `mv_filter` | **ZARUBAF ADD DESCRIPTION** | active | |
|
||||
|
||||
### Data Path Elements
|
||||
|
||||
| Name | Description | Status | Superseded By |
|
||||
| :--------------------------- | :----------------------------------------------------------------------------- | :------------- | :------------ |
|
||||
| `binary_to_gray` | Binary to gray code converter | active | |
|
||||
| `find_first_one` | Leading-one finder / leading-zero counter | *deprecated* | `lzc` |
|
||||
| `gray_to_binary` | Gray code to binary converter | active | |
|
||||
| `lzc` | Leading/trailing-zero counter | active | |
|
||||
| `onehot_to_bin` | One-hot to binary converter | active | |
|
||||
| `shift_reg` | Shift register for arbitrary types | active | |
|
||||
| `rr_arb_tree` | Round-robin arbiter for req/gnt and vld/rdy interfaces with optional priority | active | |
|
||||
| `rrarbiter` | Round-robin arbiter for req/ack interface with look-ahead | *deprecated* | `rr_arb_tree` |
|
||||
| `prioarbiter` | Priority arbiter arbiter for req/ack interface with look-ahead | *deprecated* | `rr_arb_tree` |
|
||||
| `fall_through_register` | Fall-through register with ready/valid interface | active | |
|
||||
| `spill_register` | Register with ready/valid interface to cut all combinational interface paths | active | |
|
||||
| `stream_arbiter` | Round-robin arbiter for ready/valid stream interface | active | |
|
||||
| `stream_arbiter_flushable` | Round-robin arbiter for ready/valid stream interface and flush functionality | active | |
|
||||
| `stream_demux` | Ready/valid interface demultiplexer | active | |
|
||||
| `stream_mux` | Ready/valid interface multiplexer | active | |
|
||||
| `stream_register` | Register with ready/valid interface | active | |
|
||||
| `stream_fork` | Ready/valid fork | active | |
|
||||
| `stream_filter` | Ready/valid filter | active | |
|
||||
| `stream_delay` | Randomize or delay ready/valid interface | active | |
|
||||
| `popcount` | Combinatorial popcount (hamming weight) | active | |
|
||||
|
||||
### Data Structures
|
||||
|
||||
| Name | Description | Status | Superseded By |
|
||||
| :------------------- | :---------------------------------------------- | :------------- | :------------ |
|
||||
| `fifo` | FIFO register with upper threshold | *deprecated* | `fifo_v3` |
|
||||
| `fifo_v2` | FIFO register with upper and lower threshold | *deprecated* | `fifo_v3` |
|
||||
| `fifo_v3` | FIFO register with generic fill counts | active | |
|
||||
| `generic_fifo` | FIFO register without thresholds | *deprecated* | `fifo_v3` |
|
||||
| `generic_fifo_adv` | FIFO register without thresholds | *deprecated* | `fifo_v3` |
|
||||
| `sram` | SRAM behavioral model | active | |
|
||||
| `plru_tree` | Pseudo least recently used tree | active | |
|
||||
| `unread` | Empty module to sink unconnected outputs into | active | |
|
||||
|
||||
|
||||
## Header Contents
|
||||
|
||||
This repository currently contains the following header files.
|
||||
|
||||
### RTL Register Macros
|
||||
|
||||
The header file `registers.svh` contains macros that expand to descriptions of registers.
|
||||
To avoid misuse of `always_ff` blocks, only the following macros shall be used to describe sequential behavior.
|
||||
The use of linter rules that flag explicit uses of `always_ff` in source code is encouraged.
|
||||
|
||||
| Macro | Arguments | Description |
|
||||
|-----------------------|-----------------------------------------------------------------|-------------------------------------------------------------------------|
|
||||
| <code>\`FF</code> | `q_sig`, `d_sig`, `rst_val` | Flip-flop with asynchronous active-low reset (implicit) |
|
||||
| <code>\`FFAR</code> | `q_sig`, `d_sig`, `rst_val`, `clk_sig`, `arst_sig` | Flip-flop with asynchronous active-high reset |
|
||||
| <code>\`FFARN</code> | `q_sig`, `d_sig`, `rst_val`, `clk_sig`, `arstn_sig` | Flip-flop with asynchronous active-low reset |
|
||||
| <code>\`FFSR</code> | `q_sig`, `d_sig`, `rst_val`, `clk_sig`, `rst_sig` | Flip-flop with synchronous active-high reset |
|
||||
| <code>\`FFSRN</code> | `q_sig`, `d_sig`, `rst_val`, `clk_sig`, `rstn_sig` | Flip-flop with synchronous active-low reset |
|
||||
| <code>\`FFNR</code> | `q_sig`, `d_sig`, `clk_sig` | Flip-flop without reset |
|
||||
| | | |
|
||||
| <code>\`FFL</code> | `q_sig`, `d_sig`, `load_ena`, `rst_val` | Flip-flop with load-enable and asynchronous active-low reset (implicit) |
|
||||
| <code>\`FFLAR</code> | `q_sig`, `d_sig`, `load_ena`, `rst_val`, `clk_sig`, `arst_sig` | Flip-flop with load-enable and asynchronous active-high reset |
|
||||
| <code>\`FFLARN</code> | `q_sig`, `d_sig`, `load_ena`, `rst_val`, `clk_sig`, `arstn_sig` | Flip-flop with load-enable and asynchronous active-low reset |
|
||||
| <code>\`FFLSR</code> | `q_sig`, `d_sig`, `load_ena`, `rst_val`, `clk_sig`, `rst_sig` | Flip-flop with load-enable and synchronous active-high reset |
|
||||
| <code>\`FFLSRN</code> | `q_sig`, `d_sig`, `load_ena`, `rst_val`, `clk_sig`, `rstn_sig` | Flip-flop with load-enable and synchronous active-low reset |
|
||||
| <code>\`FFLNR</code> | `q_sig`, `d_sig`, `load_ena`, `clk_sig` | Flip-flop with load-enable without reset |
|
||||
- *The name of the clock and reset signals for implicit variants is `clk_i` and `rst_ni`, respectively.*
|
||||
- *Argument suffix `_sig` indicates signal names for present and next state as well as clocks and resets.*
|
||||
- *Argument `rst_val` specifies the value literal to be assigned upon reset.*
|
||||
- *Argument `load_ena` specifies the boolean expression that forms the load enable of the register.*
|
|
@ -1,224 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
//
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Common register defines for RTL designs
|
||||
`ifndef COMMON_CELLS_REGISTERS_SVH_
|
||||
`define COMMON_CELLS_REGISTERS_SVH_
|
||||
|
||||
// Abridged Summary of available FF macros:
|
||||
// `FF: asynchronous active-low reset (implicit clock and reset)
|
||||
// `FFAR: asynchronous active-high reset
|
||||
// `FFARN: asynchronous active-low reset
|
||||
// `FFSR: synchronous active-high reset
|
||||
// `FFSRN: synchronous active-low reset
|
||||
// `FFNR: without reset
|
||||
// `FFL: load-enable and asynchronous active-low reset (implicit clock and reset)
|
||||
// `FFLAR: load-enable and asynchronous active-high reset
|
||||
// `FFLARN: load-enable and asynchronous active-low reset
|
||||
// `FFLARNC: load-enable and asynchronous active-low reset and synchronous active-high clear
|
||||
// `FFLSR: load-enable and synchronous active-high reset
|
||||
// `FFLSRN: load-enable and synchronous active-low reset
|
||||
// `FFLNR: load-enable without reset
|
||||
|
||||
|
||||
// Flip-Flop with asynchronous active-low reset (implicit clock and reset)
|
||||
// __q: Q output of FF
|
||||
// __d: D input of FF
|
||||
// __reset_value: value assigned upon reset
|
||||
// Implicit:
|
||||
// clk_i: clock input
|
||||
// rst_ni: reset input (asynchronous, active low)
|
||||
`define FF(__q, __d, __reset_value) \
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin \
|
||||
if (!rst_ni) begin \
|
||||
__q <= (__reset_value); \
|
||||
end else begin \
|
||||
__q <= (__d); \
|
||||
end \
|
||||
end
|
||||
|
||||
// Flip-Flop with asynchronous active-high reset
|
||||
// __q: Q output of FF
|
||||
// __d: D input of FF
|
||||
// __reset_value: value assigned upon reset
|
||||
// __clk: clock input
|
||||
// __arst: asynchronous reset
|
||||
`define FFAR(__q, __d, __reset_value, __clk, __arst) \
|
||||
always_ff @(posedge (__clk) or posedge (__arst)) begin \
|
||||
if (__arst) begin \
|
||||
__q <= (__reset_value); \
|
||||
end else begin \
|
||||
__q <= (__d); \
|
||||
end \
|
||||
end
|
||||
|
||||
// Flip-Flop with asynchronous active-low reset
|
||||
// __q: Q output of FF
|
||||
// __d: D input of FF
|
||||
// __reset_value: value assigned upon reset
|
||||
// __clk: clock input
|
||||
// __arst_n: asynchronous reset
|
||||
`define FFARN(__q, __d, __reset_value, __clk, __arst_n) \
|
||||
always_ff @(posedge (__clk) or negedge (__arst_n)) begin \
|
||||
if (!__arst_n) begin \
|
||||
__q <= (__reset_value); \
|
||||
end else begin \
|
||||
__q <= (__d); \
|
||||
end \
|
||||
end
|
||||
|
||||
// Flip-Flop with synchronous active-high reset
|
||||
// __q: Q output of FF
|
||||
// __d: D input of FF
|
||||
// __reset_value: value assigned upon reset
|
||||
// __clk: clock input
|
||||
// __reset_clk: reset input
|
||||
`define FFSR(__q, __d, __reset_value, __clk, __reset_clk) \
|
||||
`ifndef VERILATOR \
|
||||
/``* synopsys sync_set_reset `"__reset_clk`" *``/ \
|
||||
`endif \
|
||||
always_ff @(posedge (__clk)) begin \
|
||||
__q <= (__reset_clk) ? (__reset_value) : (__d); \
|
||||
end
|
||||
|
||||
// Flip-Flop with synchronous active-low reset
|
||||
// __q: Q output of FF
|
||||
// __d: D input of FF
|
||||
// __reset_value: value assigned upon reset
|
||||
// __clk: clock input
|
||||
// __reset_n_clk: reset input
|
||||
`define FFSRN(__q, __d, __reset_value, __clk, __reset_n_clk) \
|
||||
`ifndef VERILATOR \
|
||||
/``* synopsys sync_set_reset `"__reset_n_clk`" *``/ \
|
||||
`endif \
|
||||
always_ff @(posedge (__clk)) begin \
|
||||
__q <= (!__reset_n_clk) ? (__reset_value) : (__d); \
|
||||
end
|
||||
|
||||
// Always-enable Flip-Flop without reset
|
||||
// __q: Q output of FF
|
||||
// __d: D input of FF
|
||||
// __clk: clock input
|
||||
`define FFNR(__q, __d, __clk) \
|
||||
always_ff @(posedge (__clk)) begin \
|
||||
__q <= (__d); \
|
||||
end
|
||||
|
||||
// Flip-Flop with load-enable and asynchronous active-low reset (implicit clock and reset)
|
||||
// __q: Q output of FF
|
||||
// __d: D input of FF
|
||||
// __load: load d value into FF
|
||||
// __reset_value: value assigned upon reset
|
||||
// Implicit:
|
||||
// clk_i: clock input
|
||||
// rst_ni: reset input (asynchronous, active low)
|
||||
`define FFL(__q, __d, __load, __reset_value) \
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin \
|
||||
if (!rst_ni) begin \
|
||||
__q <= (__reset_value); \
|
||||
end else begin \
|
||||
__q <= (__load) ? (__d) : (__q); \
|
||||
end \
|
||||
end
|
||||
|
||||
// Flip-Flop with load-enable and asynchronous active-high reset
|
||||
// __q: Q output of FF
|
||||
// __d: D input of FF
|
||||
// __load: load d value into FF
|
||||
// __reset_value: value assigned upon reset
|
||||
// __clk: clock input
|
||||
// __arst: asynchronous reset
|
||||
`define FFLAR(__q, __d, __load, __reset_value, __clk, __arst) \
|
||||
always_ff @(posedge (__clk) or posedge (__arst)) begin \
|
||||
if (__arst) begin \
|
||||
__q <= (__reset_value); \
|
||||
end else begin \
|
||||
__q <= (__load) ? (__d) : (__q); \
|
||||
end \
|
||||
end
|
||||
|
||||
// Flip-Flop with load-enable and asynchronous active-low reset
|
||||
// __q: Q output of FF
|
||||
// __d: D input of FF
|
||||
// __load: load d value into FF
|
||||
// __reset_value: value assigned upon reset
|
||||
// __clk: clock input
|
||||
// __arst_n: asynchronous reset
|
||||
`define FFLARN(__q, __d, __load, __reset_value, __clk, __arst_n) \
|
||||
always_ff @(posedge (__clk) or negedge (__arst_n)) begin \
|
||||
if (!__arst_n) begin \
|
||||
__q <= (__reset_value); \
|
||||
end else begin \
|
||||
__q <= (__load) ? (__d) : (__q); \
|
||||
end \
|
||||
end
|
||||
|
||||
// Flip-Flop with load-enable and synchronous active-high reset
|
||||
// __q: Q output of FF
|
||||
// __d: D input of FF
|
||||
// __load: load d value into FF
|
||||
// __reset_value: value assigned upon reset
|
||||
// __clk: clock input
|
||||
// __reset_clk: reset input
|
||||
`define FFLSR(__q, __d, __load, __reset_value, __clk, __reset_clk) \
|
||||
`ifndef VERILATOR \
|
||||
/``* synopsys sync_set_reset `"__reset_clk`" *``/ \
|
||||
`endif \
|
||||
always_ff @(posedge (__clk)) begin \
|
||||
__q <= (__reset_clk) ? (__reset_value) : ((__load) ? (__d) : (__q)); \
|
||||
end
|
||||
|
||||
// Flip-Flop with load-enable and synchronous active-low reset
|
||||
// __q: Q output of FF
|
||||
// __d: D input of FF
|
||||
// __load: load d value into FF
|
||||
// __reset_value: value assigned upon reset
|
||||
// __clk: clock input
|
||||
// __reset_n_clk: reset input
|
||||
`define FFLSRN(__q, __d, __load, __reset_value, __clk, __reset_n_clk) \
|
||||
`ifndef VERILATOR \
|
||||
/``* synopsys sync_set_reset `"__reset_n_clk`" *``/ \
|
||||
`endif \
|
||||
always_ff @(posedge (__clk)) begin \
|
||||
__q <= (!__reset_n_clk) ? (__reset_value) : ((__load) ? (__d) : (__q)); \
|
||||
end
|
||||
|
||||
// Flip-Flop with load-enable and asynchronous active-low reset and synchronous clear
|
||||
// __q: Q output of FF
|
||||
// __d: D input of FF
|
||||
// __load: load d value into FF
|
||||
// __clear: assign reset value into FF
|
||||
// __reset_value: value assigned upon reset
|
||||
// __clk: clock input
|
||||
// __arst_n: asynchronous reset
|
||||
`define FFLARNC(__q, __d, __load, __clear, __reset_value, __clk, __arst_n) \
|
||||
`ifndef VERILATOR \
|
||||
/``* synopsys sync_set_reset `"__clear`" *``/ \
|
||||
`endif \
|
||||
always_ff @(posedge (__clk) or negedge (__arst_n)) begin \
|
||||
if (!__arst_n) begin \
|
||||
__q <= (__reset_value); \
|
||||
end else begin \
|
||||
__q <= (__clear) ? (__reset_value) : (__load) ? (__d) : (__q); \
|
||||
end \
|
||||
end
|
||||
|
||||
// Load-enable Flip-Flop without reset
|
||||
// __q: Q output of FF
|
||||
// __d: D input of FF
|
||||
// __load: load d value into FF
|
||||
// __clk: clock input
|
||||
`define FFLNR(__q, __d, __load, __clk) \
|
||||
always_ff @(posedge (__clk)) begin \
|
||||
__q <= (__load) ? (__d) : (__q); \
|
||||
end
|
||||
|
||||
`endif
|
|
@ -1,175 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
//
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
//
|
||||
// Fabian Schuiki <fschuiki@iis.ee.ethz.ch>
|
||||
|
||||
/// A two-phase clock domain crossing.
|
||||
///
|
||||
/// CONSTRAINT: Requires max_delay of min_period(src_clk_i, dst_clk_i) through
|
||||
/// the paths async_req, async_ack, async_data.
|
||||
/* verilator lint_off DECLFILENAME */
|
||||
module cdc_2phase #(
|
||||
parameter type T = logic
|
||||
)(
|
||||
input logic src_rst_ni,
|
||||
input logic src_clk_i,
|
||||
input T src_data_i,
|
||||
input logic src_valid_i,
|
||||
output logic src_ready_o,
|
||||
|
||||
input logic dst_rst_ni,
|
||||
input logic dst_clk_i,
|
||||
output T dst_data_o,
|
||||
output logic dst_valid_o,
|
||||
input logic dst_ready_i
|
||||
);
|
||||
|
||||
// Asynchronous handshake signals.
|
||||
(* dont_touch = "true" *) logic async_req;
|
||||
(* dont_touch = "true" *) logic async_ack;
|
||||
(* dont_touch = "true" *) T async_data;
|
||||
|
||||
// The sender in the source domain.
|
||||
cdc_2phase_src #(.T(T)) i_src (
|
||||
.rst_ni ( src_rst_ni ),
|
||||
.clk_i ( src_clk_i ),
|
||||
.data_i ( src_data_i ),
|
||||
.valid_i ( src_valid_i ),
|
||||
.ready_o ( src_ready_o ),
|
||||
.async_req_o ( async_req ),
|
||||
.async_ack_i ( async_ack ),
|
||||
.async_data_o ( async_data )
|
||||
);
|
||||
|
||||
// The receiver in the destination domain.
|
||||
cdc_2phase_dst #(.T(T)) i_dst (
|
||||
.rst_ni ( dst_rst_ni ),
|
||||
.clk_i ( dst_clk_i ),
|
||||
.data_o ( dst_data_o ),
|
||||
.valid_o ( dst_valid_o ),
|
||||
.ready_i ( dst_ready_i ),
|
||||
.async_req_i ( async_req ),
|
||||
.async_ack_o ( async_ack ),
|
||||
.async_data_i ( async_data )
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
/// Half of the two-phase clock domain crossing located in the source domain.
|
||||
module cdc_2phase_src #(
|
||||
parameter type T = logic
|
||||
)(
|
||||
input logic rst_ni,
|
||||
input logic clk_i,
|
||||
input T data_i,
|
||||
input logic valid_i,
|
||||
output logic ready_o,
|
||||
output logic async_req_o,
|
||||
input logic async_ack_i,
|
||||
output T async_data_o
|
||||
);
|
||||
|
||||
(* dont_touch = "true" *)
|
||||
logic req_src_q, ack_src_q, ack_q;
|
||||
(* dont_touch = "true" *)
|
||||
T data_src_q;
|
||||
|
||||
// The req_src and data_src registers change when a new data item is accepted.
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
req_src_q <= 0;
|
||||
data_src_q <= '0;
|
||||
end else if (valid_i && ready_o) begin
|
||||
req_src_q <= ~req_src_q;
|
||||
data_src_q <= data_i;
|
||||
end
|
||||
end
|
||||
|
||||
// The ack_src and ack registers act as synchronization stages.
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
ack_src_q <= 0;
|
||||
ack_q <= 0;
|
||||
end else begin
|
||||
ack_src_q <= async_ack_i;
|
||||
ack_q <= ack_src_q;
|
||||
end
|
||||
end
|
||||
|
||||
// Output assignments.
|
||||
assign ready_o = (req_src_q == ack_q);
|
||||
assign async_req_o = req_src_q;
|
||||
assign async_data_o = data_src_q;
|
||||
|
||||
endmodule
|
||||
|
||||
|
||||
/// Half of the two-phase clock domain crossing located in the destination
|
||||
/// domain.
|
||||
module cdc_2phase_dst #(
|
||||
parameter type T = logic
|
||||
)(
|
||||
input logic rst_ni,
|
||||
input logic clk_i,
|
||||
output T data_o,
|
||||
output logic valid_o,
|
||||
input logic ready_i,
|
||||
input logic async_req_i,
|
||||
output logic async_ack_o,
|
||||
input T async_data_i
|
||||
);
|
||||
|
||||
(* dont_touch = "true" *)
|
||||
(* async_reg = "true" *)
|
||||
logic req_dst_q, req_q0, req_q1, ack_dst_q;
|
||||
(* dont_touch = "true" *)
|
||||
T data_dst_q;
|
||||
|
||||
// The ack_dst register changes when a new data item is accepted.
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
ack_dst_q <= 0;
|
||||
end else if (valid_o && ready_i) begin
|
||||
ack_dst_q <= ~ack_dst_q;
|
||||
end
|
||||
end
|
||||
|
||||
// The data_dst register changes when a new data item is presented. This is
|
||||
// indicated by the async_req line changing levels.
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
data_dst_q <= '0;
|
||||
end else if (req_q0 != req_q1 && !valid_o) begin
|
||||
data_dst_q <= async_data_i;
|
||||
end
|
||||
end
|
||||
|
||||
// The req_dst and req registers act as synchronization stages.
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
req_dst_q <= 0;
|
||||
req_q0 <= 0;
|
||||
req_q1 <= 0;
|
||||
end else begin
|
||||
req_dst_q <= async_req_i;
|
||||
req_q0 <= req_dst_q;
|
||||
req_q1 <= req_q0;
|
||||
end
|
||||
end
|
||||
|
||||
// Output assignments.
|
||||
assign valid_o = (ack_dst_q != req_q1);
|
||||
assign data_o = data_dst_q;
|
||||
assign async_ack_o = ack_dst_q;
|
||||
|
||||
endmodule
|
||||
/* verilator lint_on DECLFILENAME */
|
|
@ -1,134 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
//
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
//
|
||||
// Fabian Schuiki <fschuiki@iis.ee.ethz.ch>
|
||||
|
||||
/// A clock domain crossing FIFO, using 2-phase hand shakes.
|
||||
///
|
||||
/// This FIFO has its push and pop ports in two separate clock domains. Its size
|
||||
/// can only be powers of two, which is why its depth is given as 2**LOG_DEPTH.
|
||||
/// LOG_DEPTH must be at least 1.
|
||||
///
|
||||
/// CONSTRAINT: See the constraints for `cdc_2phase`. An additional maximum
|
||||
/// delay path needs to be specified from fifo_data_q to dst_data_o.
|
||||
module cdc_fifo_2phase #(
|
||||
/// The data type of the payload transported by the FIFO.
|
||||
parameter type T = logic,
|
||||
/// The FIFO's depth given as 2**LOG_DEPTH.
|
||||
parameter int LOG_DEPTH = 3
|
||||
)(
|
||||
input logic src_rst_ni,
|
||||
input logic src_clk_i,
|
||||
input T src_data_i,
|
||||
input logic src_valid_i,
|
||||
output logic src_ready_o,
|
||||
|
||||
input logic dst_rst_ni,
|
||||
input logic dst_clk_i,
|
||||
output T dst_data_o,
|
||||
output logic dst_valid_o,
|
||||
input logic dst_ready_i
|
||||
);
|
||||
|
||||
// Check the invariants.
|
||||
//pragma translate_off
|
||||
initial begin
|
||||
assert(LOG_DEPTH > 0);
|
||||
end
|
||||
//pragma translate_on
|
||||
|
||||
localparam int PTR_WIDTH = LOG_DEPTH+1;
|
||||
typedef logic [PTR_WIDTH-1:0] pointer_t;
|
||||
typedef logic [LOG_DEPTH-1:0] index_t;
|
||||
|
||||
localparam pointer_t PTR_FULL = (1 << LOG_DEPTH);
|
||||
localparam pointer_t PTR_EMPTY = '0;
|
||||
|
||||
// Allocate the registers for the FIFO memory with its separate write and read
|
||||
// ports. The FIFO has the following ports:
|
||||
//
|
||||
// - write: fifo_widx, fifo_wdata, fifo_write, src_clk_i
|
||||
// - read: fifo_ridx, fifo_rdata
|
||||
index_t fifo_widx, fifo_ridx;
|
||||
logic fifo_write;
|
||||
T fifo_wdata, fifo_rdata;
|
||||
T fifo_data_q [2**LOG_DEPTH];
|
||||
|
||||
assign fifo_rdata = fifo_data_q[fifo_ridx];
|
||||
|
||||
for (genvar i = 0; i < 2**LOG_DEPTH; i++) begin : g_word
|
||||
always_ff @(posedge src_clk_i, negedge src_rst_ni) begin
|
||||
if (!src_rst_ni)
|
||||
fifo_data_q[i] <= '0;
|
||||
else if (fifo_write && fifo_widx == i)
|
||||
fifo_data_q[i] <= fifo_wdata;
|
||||
end
|
||||
end
|
||||
|
||||
// Allocate the read and write pointers in the source and destination domain.
|
||||
pointer_t src_wptr_q, dst_wptr, src_rptr, dst_rptr_q;
|
||||
|
||||
always_ff @(posedge src_clk_i, negedge src_rst_ni) begin
|
||||
if (!src_rst_ni)
|
||||
src_wptr_q <= 0;
|
||||
else if (src_valid_i && src_ready_o)
|
||||
src_wptr_q <= src_wptr_q + 1;
|
||||
end
|
||||
|
||||
always_ff @(posedge dst_clk_i, negedge dst_rst_ni) begin
|
||||
if (!dst_rst_ni)
|
||||
dst_rptr_q <= 0;
|
||||
else if (dst_valid_o && dst_ready_i)
|
||||
dst_rptr_q <= dst_rptr_q + 1;
|
||||
end
|
||||
|
||||
// The pointers into the FIFO are one bit wider than the actual address into
|
||||
// the FIFO. This makes detecting critical states very simple: if all but the
|
||||
// topmost bit of rptr and wptr agree, the FIFO is in a critical state. If the
|
||||
// topmost bit is equal, the FIFO is empty, otherwise it is full.
|
||||
assign src_ready_o = ((src_wptr_q ^ src_rptr) != PTR_FULL);
|
||||
assign dst_valid_o = ((dst_rptr_q ^ dst_wptr) != PTR_EMPTY);
|
||||
|
||||
// Transport the read and write pointers across the clock domain boundary.
|
||||
cdc_2phase #(pointer_t) i_cdc_wptr (
|
||||
.src_rst_ni ( src_rst_ni ),
|
||||
.src_clk_i ( src_clk_i ),
|
||||
.src_data_i ( src_wptr_q ),
|
||||
.src_valid_i ( 1'b1 ),
|
||||
.src_ready_o ( ),
|
||||
.dst_rst_ni ( dst_rst_ni ),
|
||||
.dst_clk_i ( dst_clk_i ),
|
||||
.dst_data_o ( dst_wptr ),
|
||||
.dst_valid_o ( ),
|
||||
.dst_ready_i ( 1'b1 )
|
||||
);
|
||||
|
||||
cdc_2phase #(pointer_t) i_cdc_rptr (
|
||||
.src_rst_ni ( dst_rst_ni ),
|
||||
.src_clk_i ( dst_clk_i ),
|
||||
.src_data_i ( dst_rptr_q ),
|
||||
.src_valid_i ( 1'b1 ),
|
||||
.src_ready_o ( ),
|
||||
.dst_rst_ni ( src_rst_ni ),
|
||||
.dst_clk_i ( src_clk_i ),
|
||||
.dst_data_o ( src_rptr ),
|
||||
.dst_valid_o ( ),
|
||||
.dst_ready_i ( 1'b1 )
|
||||
);
|
||||
|
||||
// Drive the FIFO write and read ports.
|
||||
assign fifo_widx = src_wptr_q;
|
||||
assign fifo_wdata = src_data_i;
|
||||
assign fifo_write = src_valid_i && src_ready_o;
|
||||
assign fifo_ridx = dst_rptr_q;
|
||||
assign dst_data_o = fifo_rdata;
|
||||
|
||||
endmodule
|
|
@ -1,158 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
//
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
//
|
||||
// Fabian Schuiki <fschuiki@iis.ee.ethz.ch>
|
||||
|
||||
/// A clock domain crossing FIFO, using gray counters.
|
||||
///
|
||||
/// This FIFO has its push and pop ports in two separate clock domains. Its size
|
||||
/// can only be powers of two, which is why its depth is given as 2**LOG_DEPTH.
|
||||
/// LOG_DEPTH must be at least 1.
|
||||
///
|
||||
/// # Constraints
|
||||
///
|
||||
/// The following constraints need to be set:
|
||||
/// - max_delay -from src_wptr_gray_q -to dst_wptr_gray_q
|
||||
/// - max_delay -from dst_rptr_gray_q -to src_rptr_gray_q
|
||||
/// - max_delay -from fifo_data_q -to fifo_rdata
|
||||
module cdc_fifo_gray #(
|
||||
/// The data type of the payload transported by the FIFO.
|
||||
parameter type T = logic,
|
||||
/// The FIFO's depth given as 2**LOG_DEPTH.
|
||||
parameter int LOG_DEPTH = 3
|
||||
)(
|
||||
input logic src_rst_ni,
|
||||
input logic src_clk_i,
|
||||
input T src_data_i,
|
||||
input logic src_valid_i,
|
||||
output logic src_ready_o,
|
||||
|
||||
input logic dst_rst_ni,
|
||||
input logic dst_clk_i,
|
||||
output T dst_data_o,
|
||||
output logic dst_valid_o,
|
||||
input logic dst_ready_i
|
||||
);
|
||||
|
||||
// Check the invariants.
|
||||
//pragma translate_off
|
||||
initial begin
|
||||
assert(LOG_DEPTH > 0);
|
||||
end
|
||||
//pragma translate_on
|
||||
|
||||
localparam int PTR_WIDTH = LOG_DEPTH+1;
|
||||
typedef logic [PTR_WIDTH-1:0] pointer_t;
|
||||
typedef logic [LOG_DEPTH-1:0] index_t;
|
||||
|
||||
localparam pointer_t PTR_FULL = (1 << LOG_DEPTH);
|
||||
localparam pointer_t PTR_EMPTY = '0;
|
||||
|
||||
// Allocate the registers for the FIFO memory with its separate write and read
|
||||
// ports. The FIFO has the following ports:
|
||||
//
|
||||
// - write: fifo_widx, fifo_wdata, fifo_write, src_clk_i
|
||||
// - read: fifo_ridx, fifo_rdata
|
||||
index_t fifo_widx, fifo_ridx;
|
||||
logic fifo_write;
|
||||
T fifo_wdata, fifo_rdata;
|
||||
T fifo_data_q [2**LOG_DEPTH];
|
||||
|
||||
assign fifo_rdata = fifo_data_q[fifo_ridx];
|
||||
|
||||
for (genvar i = 0; i < 2**LOG_DEPTH; i++) begin : g_word
|
||||
always_ff @(posedge src_clk_i, negedge src_rst_ni) begin
|
||||
if (!src_rst_ni)
|
||||
fifo_data_q[i] <= '0;
|
||||
else if (fifo_write && fifo_widx == i)
|
||||
fifo_data_q[i] <= fifo_wdata;
|
||||
end
|
||||
end
|
||||
|
||||
// Create the write and read pointers in the source and destination domain.
|
||||
// These are binary counters combined with a Gray encoder. Both the binary and
|
||||
// the Gray coded output are registered; the binary one for use in the local
|
||||
// domain, the Gray one for synchronization into the other domain.
|
||||
pointer_t src_wptr_bin_q, src_wptr_gray_q, dst_rptr_bin_q, dst_rptr_gray_q;
|
||||
pointer_t src_wptr_bin_d, src_wptr_gray_d, dst_rptr_bin_d, dst_rptr_gray_d;
|
||||
|
||||
assign src_wptr_bin_d = src_wptr_bin_q + 1;
|
||||
assign dst_rptr_bin_d = dst_rptr_bin_q + 1;
|
||||
|
||||
binary_to_gray #(PTR_WIDTH) i_src_b2g (src_wptr_bin_d, src_wptr_gray_d);
|
||||
binary_to_gray #(PTR_WIDTH) i_dst_b2g (dst_rptr_bin_d, dst_rptr_gray_d);
|
||||
|
||||
always_ff @(posedge src_clk_i, negedge src_rst_ni) begin
|
||||
if (!src_rst_ni) begin
|
||||
src_wptr_bin_q <= '0;
|
||||
src_wptr_gray_q <= '0;
|
||||
end else if (src_valid_i && src_ready_o) begin
|
||||
src_wptr_bin_q <= src_wptr_bin_d;
|
||||
src_wptr_gray_q <= src_wptr_gray_d;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge dst_clk_i, negedge dst_rst_ni) begin
|
||||
if (!dst_rst_ni) begin
|
||||
dst_rptr_bin_q <= '0;
|
||||
dst_rptr_gray_q <= '0;
|
||||
end else if (dst_valid_o && dst_ready_i) begin
|
||||
dst_rptr_bin_q <= dst_rptr_bin_d;
|
||||
dst_rptr_gray_q <= dst_rptr_gray_d;
|
||||
end
|
||||
end
|
||||
|
||||
// Move the Gray-coded pointers over into the other clock domain and
|
||||
// synchronize them to reduce the probability of metastability.
|
||||
pointer_t src_rptr_gray_q, src_rptr_gray_q2;
|
||||
pointer_t dst_wptr_gray_q, dst_wptr_gray_q2;
|
||||
|
||||
always_ff @(posedge src_clk_i, negedge src_rst_ni) begin
|
||||
if (!src_rst_ni) begin
|
||||
src_rptr_gray_q <= '0;
|
||||
src_rptr_gray_q2 <= '0;
|
||||
end else begin
|
||||
src_rptr_gray_q <= dst_rptr_gray_q;
|
||||
src_rptr_gray_q2 <= src_rptr_gray_q;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge dst_clk_i, negedge dst_rst_ni) begin
|
||||
if (!dst_rst_ni) begin
|
||||
dst_wptr_gray_q <= '0;
|
||||
dst_wptr_gray_q2 <= '0;
|
||||
end else begin
|
||||
dst_wptr_gray_q <= src_wptr_gray_q;
|
||||
dst_wptr_gray_q2 <= dst_wptr_gray_q;
|
||||
end
|
||||
end
|
||||
|
||||
// Reverse the Gray coding of the synchronized pointers.
|
||||
pointer_t src_rptr_bin, dst_wptr_bin;
|
||||
|
||||
gray_to_binary #(PTR_WIDTH) i_src_g2b (src_rptr_gray_q2, src_rptr_bin);
|
||||
gray_to_binary #(PTR_WIDTH) i_dst_g2b (dst_wptr_gray_q2, dst_wptr_bin);
|
||||
|
||||
// The pointers into the FIFO are one bit wider than the actual address into
|
||||
// the FIFO. This makes detecting critical states very simple: if all but the
|
||||
// topmost bit of rptr and wptr agree, the FIFO is in a critical state. If the
|
||||
// topmost bit is equal, the FIFO is empty, otherwise it is full.
|
||||
assign src_ready_o = ((src_wptr_bin_q ^ src_rptr_bin) != PTR_FULL);
|
||||
assign dst_valid_o = ((dst_rptr_bin_q ^ dst_wptr_bin) != PTR_EMPTY);
|
||||
|
||||
// Drive the FIFO write and read ports.
|
||||
assign fifo_widx = src_wptr_bin_q;
|
||||
assign fifo_wdata = src_data_i;
|
||||
assign fifo_write = src_valid_i && src_ready_o;
|
||||
assign fifo_ridx = dst_rptr_bin_q;
|
||||
assign dst_data_o = fifo_rdata;
|
||||
|
||||
endmodule
|
|
@ -1,49 +0,0 @@
|
|||
// Copyright 2016 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// cf_math_pkg: Constant Function Implementations of Mathematical Functions for HDL Elaboration
|
||||
//
|
||||
// This package contains a collection of mathematical functions that are commonly used when defining
|
||||
// the value of constants in HDL code. These functions are implemented as Verilog constants
|
||||
// functions. Introduced in Verilog 2001 (IEEE Std 1364-2001), a constant function (§ 10.3.5) is a
|
||||
// function whose value can be evaluated at compile time or during elaboration. A constant function
|
||||
// must be called with arguments that are constants.
|
||||
|
||||
package automatic cf_math_pkg;
|
||||
|
||||
// Ceiled Division of Two Natural Numbers
|
||||
//
|
||||
// Returns the quotient of two natural numbers, rounded towards plus infinity.
|
||||
function integer ceil_div (input longint dividend, input longint divisor);
|
||||
automatic longint remainder;
|
||||
|
||||
// pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
if (dividend < 0) begin
|
||||
$fatal(1, "Dividend %0d is not a natural number!", dividend);
|
||||
end
|
||||
|
||||
if (divisor < 0) begin
|
||||
$fatal(1, "Divisor %0d is not a natural number!", divisor);
|
||||
end
|
||||
|
||||
if (divisor == 0) begin
|
||||
$fatal(1, "Division by zero!");
|
||||
end
|
||||
`endif
|
||||
// pragma translate_on
|
||||
|
||||
remainder = dividend;
|
||||
for (ceil_div = 0; remainder > 0; ceil_div++) begin
|
||||
remainder = remainder - divisor;
|
||||
end
|
||||
endfunction
|
||||
|
||||
endpackage
|
|
@ -1,42 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Author: Florian Zaruba
|
||||
// Description: Divides the clock by an integer factor
|
||||
module clk_div #(
|
||||
parameter int unsigned RATIO = 4
|
||||
)(
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
input logic testmode_i, // testmode
|
||||
input logic en_i, // enable clock divider
|
||||
output logic clk_o // divided clock out
|
||||
);
|
||||
logic [RATIO-1:0] counter_q;
|
||||
logic clk_q;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (~rst_ni) begin
|
||||
clk_q <= 1'b0;
|
||||
counter_q <= '0;
|
||||
end else begin
|
||||
clk_q <= 1'b0;
|
||||
if (en_i) begin
|
||||
if (counter_q == (RATIO[RATIO-1:0] - 1)) begin
|
||||
clk_q <= 1'b1;
|
||||
end else begin
|
||||
counter_q <= counter_q + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
// output assignment - bypass in testmode
|
||||
assign clk_o = testmode_i ? clk_i : clk_q;
|
||||
endmodule
|
|
@ -1,55 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Author: Florian Zaruba
|
||||
// Description: Generic up/down counter
|
||||
|
||||
module counter #(
|
||||
parameter int unsigned WIDTH = 4
|
||||
)(
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic clear_i, // synchronous clear
|
||||
input logic en_i, // enable the counter
|
||||
input logic load_i, // load a new value
|
||||
input logic down_i, // downcount, default is up
|
||||
input logic [WIDTH-1:0] d_i,
|
||||
output logic [WIDTH-1:0] q_o,
|
||||
output logic overflow_o
|
||||
);
|
||||
logic [WIDTH:0] counter_q, counter_d;
|
||||
// counter overflowed if the MSB is set
|
||||
assign overflow_o = counter_q[WIDTH];
|
||||
assign q_o = counter_q[WIDTH-1:0];
|
||||
|
||||
always_comb begin
|
||||
counter_d = counter_q;
|
||||
|
||||
if (clear_i) begin
|
||||
counter_d = '0;
|
||||
end else if (load_i) begin
|
||||
counter_d = {1'b0, d_i};
|
||||
end else if (en_i) begin
|
||||
if (down_i) begin
|
||||
counter_d = counter_q - 1;
|
||||
end else begin
|
||||
counter_d = counter_q + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (~rst_ni) begin
|
||||
counter_q <= '0;
|
||||
end else begin
|
||||
counter_q <= counter_d;
|
||||
end
|
||||
end
|
||||
endmodule
|
|
@ -1,191 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// Company: Multitherman Laboratory @ DEIS - University of Bologna //
|
||||
// Viale Risorgimento 2 40136 //
|
||||
// Bologna - fax 0512093785 - //
|
||||
// //
|
||||
// Engineer: Antonio Pullini - pullinia@iis.ee.ethz.ch //
|
||||
// //
|
||||
// Additional contributions by: //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// Create Date: 13/02/2013 //
|
||||
// Design Name: ULPSoC //
|
||||
// Module Name: clock_divider //
|
||||
// Project Name: ULPSoC //
|
||||
// Language: SystemVerilog //
|
||||
// //
|
||||
// Description: Clock Divider //
|
||||
// //
|
||||
// //
|
||||
// Revision: //
|
||||
// Revision v0.1 - File Created //
|
||||
// Revision v0.2 - (19/03/2015) clock_gating swapped in pulp_clock_gating //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module clock_divider
|
||||
#(
|
||||
parameter DIV_INIT = 0,
|
||||
parameter BYPASS_INIT = 1
|
||||
)
|
||||
(
|
||||
input logic clk_i,
|
||||
input logic rstn_i,
|
||||
input logic test_mode_i,
|
||||
input logic clk_gate_async_i,
|
||||
input logic [7:0] clk_div_data_i,
|
||||
input logic clk_div_valid_i,
|
||||
output logic clk_div_ack_o,
|
||||
output logic clk_o
|
||||
);
|
||||
|
||||
enum logic [1:0] {IDLE, STOP, WAIT, RELEASE} state, state_next;
|
||||
|
||||
logic s_clk_out;
|
||||
logic s_clock_enable;
|
||||
logic s_clock_enable_gate;
|
||||
logic s_clk_div_valid;
|
||||
|
||||
logic [7:0] reg_clk_div;
|
||||
logic s_clk_div_valid_sync;
|
||||
|
||||
logic s_rstn_sync;
|
||||
|
||||
logic [1:0] reg_ext_gate_sync;
|
||||
|
||||
assign s_clock_enable_gate = s_clock_enable & reg_ext_gate_sync;
|
||||
|
||||
`ifndef PULP_FPGA_EMUL
|
||||
rstgen i_rst_gen
|
||||
(
|
||||
// PAD FRAME SIGNALS
|
||||
.clk_i(clk_i),
|
||||
.rst_ni(rstn_i), //async signal coming from pads
|
||||
|
||||
// TEST MODE
|
||||
.test_mode_i(test_mode_i),
|
||||
|
||||
// OUTPUT RESET
|
||||
.rst_no(s_rstn_sync),
|
||||
.init_no() //not used
|
||||
);
|
||||
`else
|
||||
assign s_rstn_sync = rstn_i;
|
||||
`endif
|
||||
|
||||
|
||||
//handle the handshake with the soc_ctrl. Interface is now async
|
||||
pulp_sync_wedge i_edge_prop
|
||||
(
|
||||
.clk_i(clk_i),
|
||||
.rstn_i(s_rstn_sync),
|
||||
.en_i(1'b1),
|
||||
.serial_i(clk_div_valid_i),
|
||||
.serial_o(clk_div_ack_o),
|
||||
.r_edge_o(s_clk_div_valid_sync),
|
||||
.f_edge_o()
|
||||
);
|
||||
|
||||
clock_divider_counter
|
||||
#(
|
||||
.BYPASS_INIT(BYPASS_INIT),
|
||||
.DIV_INIT(DIV_INIT)
|
||||
)
|
||||
i_clkdiv_cnt
|
||||
(
|
||||
.clk(clk_i),
|
||||
.rstn(s_rstn_sync),
|
||||
.test_mode(test_mode_i),
|
||||
.clk_div(reg_clk_div),
|
||||
.clk_div_valid(s_clk_div_valid),
|
||||
.clk_out(s_clk_out)
|
||||
);
|
||||
|
||||
pulp_clock_gating i_clk_gate
|
||||
(
|
||||
.clk_i(s_clk_out),
|
||||
.en_i(s_clock_enable_gate),
|
||||
.test_en_i(test_mode_i),
|
||||
.clk_o(clk_o)
|
||||
);
|
||||
|
||||
always_comb
|
||||
begin
|
||||
case(state)
|
||||
IDLE:
|
||||
begin
|
||||
s_clock_enable = 1'b1;
|
||||
s_clk_div_valid = 1'b0;
|
||||
if (s_clk_div_valid_sync)
|
||||
state_next = STOP;
|
||||
else
|
||||
state_next = IDLE;
|
||||
end
|
||||
|
||||
STOP:
|
||||
begin
|
||||
s_clock_enable = 1'b0;
|
||||
s_clk_div_valid = 1'b1;
|
||||
state_next = WAIT;
|
||||
end
|
||||
|
||||
WAIT:
|
||||
begin
|
||||
s_clock_enable = 1'b0;
|
||||
s_clk_div_valid = 1'b0;
|
||||
state_next = RELEASE;
|
||||
end
|
||||
|
||||
RELEASE:
|
||||
begin
|
||||
s_clock_enable = 1'b0;
|
||||
s_clk_div_valid = 1'b0;
|
||||
state_next = IDLE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge s_rstn_sync)
|
||||
begin
|
||||
if (!s_rstn_sync)
|
||||
state <= IDLE;
|
||||
else
|
||||
state <= state_next;
|
||||
end
|
||||
|
||||
//sample the data when valid has been sync and there is a rise edge
|
||||
always_ff @(posedge clk_i or negedge s_rstn_sync)
|
||||
begin
|
||||
if (!s_rstn_sync)
|
||||
reg_clk_div <= '0;
|
||||
else if (s_clk_div_valid_sync)
|
||||
reg_clk_div <= clk_div_data_i;
|
||||
end
|
||||
|
||||
//sample the data when valid has been sync and there is a rise edge
|
||||
always_ff @(posedge clk_i or negedge s_rstn_sync)
|
||||
begin
|
||||
if (!s_rstn_sync)
|
||||
reg_ext_gate_sync <= 2'b00;
|
||||
else
|
||||
reg_ext_gate_sync <= {clk_gate_async_i, reg_ext_gate_sync[1]};
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -1,211 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Company: Multitherman Laboratory @ DEIS - University of Bologna //
|
||||
// Viale Risorgimento 2 40136 //
|
||||
// Bologna - fax 0512093785 - //
|
||||
// //
|
||||
// Engineer: Antonio Pullini - pullinia@iis.ee.ethz.ch //
|
||||
// //
|
||||
// Additional contributions by: //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// Create Date: 13/02/2013 //
|
||||
// Design Name: ULPSoC //
|
||||
// Module Name: clock_divider_counter //
|
||||
// Project Name: ULPSoC //
|
||||
// Language: SystemVerilog //
|
||||
// //
|
||||
// Description: clock_divider_counter //
|
||||
// //
|
||||
// //
|
||||
// Revision: //
|
||||
// Revision v0.1 - File Created //
|
||||
// Revision v0.2 - (19/03/2015) clock_gating swapped in pulp_clock_gating //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
module clock_divider_counter
|
||||
#(
|
||||
parameter BYPASS_INIT = 1,
|
||||
parameter DIV_INIT = 'hFF
|
||||
)
|
||||
(
|
||||
input logic clk,
|
||||
input logic rstn,
|
||||
input logic test_mode,
|
||||
input logic [7:0] clk_div,
|
||||
input logic clk_div_valid,
|
||||
output logic clk_out
|
||||
);
|
||||
|
||||
logic [7:0] counter;
|
||||
logic [7:0] counter_next;
|
||||
logic [7:0] clk_cnt;
|
||||
logic en1;
|
||||
logic en2;
|
||||
|
||||
logic is_odd;
|
||||
|
||||
logic div1;
|
||||
logic div2;
|
||||
logic div2_neg_sync;
|
||||
|
||||
logic [7:0] clk_cnt_odd;
|
||||
logic [7:0] clk_cnt_odd_incr;
|
||||
logic [7:0] clk_cnt_even;
|
||||
logic [7:0] clk_cnt_en2;
|
||||
|
||||
logic bypass;
|
||||
|
||||
logic clk_out_gen;
|
||||
logic clk_div_valid_reg;
|
||||
|
||||
logic clk_inv_test;
|
||||
logic clk_inv;
|
||||
|
||||
// assign clk_cnt_odd_incr = clk_div + 1;
|
||||
// assign clk_cnt_odd = {1'b0,clk_cnt_odd_incr[7:1]}; //if odd divider than clk_cnt = (clk_div+1)/2
|
||||
assign clk_cnt_odd = clk_div - 8'h1; //if odd divider than clk_cnt = clk_div - 1
|
||||
assign clk_cnt_even = (clk_div == 8'h2) ? 8'h0 : ({1'b0,clk_div[7:1]} - 8'h1); //if even divider than clk_cnt = clk_div/2
|
||||
assign clk_cnt_en2 = {1'b0,clk_cnt[7:1]} + 8'h1;
|
||||
|
||||
always_comb
|
||||
begin
|
||||
if (counter == 'h0)
|
||||
en1 = 1'b1;
|
||||
else
|
||||
en1 = 1'b0;
|
||||
|
||||
if (clk_div_valid)
|
||||
counter_next = 'h0;
|
||||
else if (counter == clk_cnt)
|
||||
counter_next = 'h0;
|
||||
else
|
||||
counter_next = counter + 1;
|
||||
|
||||
if (clk_div_valid)
|
||||
en2 = 1'b0;
|
||||
else if (counter == clk_cnt_en2)
|
||||
en2 = 1'b1;
|
||||
else
|
||||
en2 = 1'b0;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk, negedge rstn)
|
||||
begin
|
||||
if (~rstn)
|
||||
begin
|
||||
counter <= 'h0;
|
||||
div1 <= 1'b0;
|
||||
bypass <= BYPASS_INIT;
|
||||
clk_cnt <= DIV_INIT;
|
||||
is_odd <= 1'b0;
|
||||
clk_div_valid_reg <= 1'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (!bypass)
|
||||
counter <= counter_next;
|
||||
|
||||
clk_div_valid_reg <= clk_div_valid;
|
||||
if (clk_div_valid)
|
||||
begin
|
||||
if ((clk_div == 8'h0) || (clk_div == 8'h1))
|
||||
begin
|
||||
bypass <= 1'b1;
|
||||
clk_cnt <= 'h0;
|
||||
is_odd <= 1'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
bypass <= 1'b0;
|
||||
if (clk_div[0])
|
||||
begin
|
||||
is_odd <= 1'b1;
|
||||
clk_cnt <= clk_cnt_odd;
|
||||
end
|
||||
else
|
||||
begin
|
||||
is_odd <= 1'b0;
|
||||
clk_cnt <= clk_cnt_even;
|
||||
end
|
||||
end
|
||||
div1 <= 1'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (en1 && !bypass)
|
||||
div1 <= ~div1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
pulp_clock_inverter clk_inv_i
|
||||
(
|
||||
.clk_i(clk),
|
||||
.clk_o(clk_inv)
|
||||
);
|
||||
|
||||
`ifndef PULP_FPGA_EMUL
|
||||
`ifdef PULP_DFT
|
||||
pulp_clock_mux2 clk_muxinv_i
|
||||
(
|
||||
.clk0_i(clk_inv),
|
||||
.clk1_i(clk),
|
||||
.clk_sel_i(test_mode),
|
||||
.clk_o(clk_inv_test)
|
||||
);
|
||||
`else
|
||||
assign clk_inv_test = clk_inv;
|
||||
`endif
|
||||
`else
|
||||
assign clk_inv_test = clk_inv;
|
||||
`endif
|
||||
|
||||
always_ff @(posedge clk_inv_test or negedge rstn)
|
||||
begin
|
||||
if (!rstn)
|
||||
begin
|
||||
div2 <= 1'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if (clk_div_valid_reg)
|
||||
div2 <= 1'b0;
|
||||
else if (en2 && is_odd && !bypass)
|
||||
div2 <= ~div2;
|
||||
end
|
||||
end // always_ff @ (posedge clk_inv_test or negedge rstn)
|
||||
|
||||
pulp_clock_xor2 clock_xor_i
|
||||
(
|
||||
.clk_o(clk_out_gen),
|
||||
.clk0_i(div1),
|
||||
.clk1_i(div2)
|
||||
);
|
||||
|
||||
pulp_clock_mux2 clk_mux_i
|
||||
(
|
||||
.clk0_i(clk_out_gen),
|
||||
.clk1_i(clk),
|
||||
.clk_sel_i(bypass || test_mode),
|
||||
.clk_o(clk_out)
|
||||
);
|
||||
|
||||
endmodule
|
|
@ -1,57 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
|
||||
|
||||
/* verilator lint_off DECLFILENAME */
|
||||
module fifo #(
|
||||
parameter bit FALL_THROUGH = 1'b0, // fifo is in fall-through mode
|
||||
parameter int unsigned DATA_WIDTH = 32, // default data width if the fifo is of type logic
|
||||
parameter int unsigned DEPTH = 8, // depth can be arbitrary from 0 to 2**32
|
||||
parameter int unsigned THRESHOLD = 1, // fill count until when to assert threshold_o
|
||||
parameter type dtype = logic [DATA_WIDTH-1:0]
|
||||
)(
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
input logic flush_i, // flush the queue
|
||||
input logic testmode_i, // test_mode to bypass clock gating
|
||||
// status flags
|
||||
output logic full_o, // queue is full
|
||||
output logic empty_o, // queue is empty
|
||||
output logic threshold_o, // the FIFO is above the specified threshold
|
||||
// as long as the queue is not full we can push new data
|
||||
input dtype data_i, // data to push into the queue
|
||||
input logic push_i, // data is valid and can be pushed to the queue
|
||||
// as long as the queue is not empty we can pop new elements
|
||||
output dtype data_o, // output data
|
||||
input logic pop_i // pop head from queue
|
||||
);
|
||||
fifo_v2 #(
|
||||
.FALL_THROUGH ( FALL_THROUGH ),
|
||||
.DATA_WIDTH ( DATA_WIDTH ),
|
||||
.DEPTH ( DEPTH ),
|
||||
.ALM_FULL_TH ( THRESHOLD ),
|
||||
.dtype ( dtype )
|
||||
) impl (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.flush_i ( flush_i ),
|
||||
.testmode_i ( testmode_i ),
|
||||
.full_o ( full_o ),
|
||||
.empty_o ( empty_o ),
|
||||
.alm_full_o ( threshold_o ),
|
||||
.alm_empty_o ( ),
|
||||
.data_i ( data_i ),
|
||||
.push_i ( push_i ),
|
||||
.data_o ( data_o ),
|
||||
.pop_i ( pop_i )
|
||||
);
|
||||
endmodule
|
||||
/* verilator lint_on DECLFILENAME */
|
|
@ -1,79 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
|
||||
|
||||
module fifo_v2 #(
|
||||
parameter bit FALL_THROUGH = 1'b0, // fifo is in fall-through mode
|
||||
parameter int unsigned DATA_WIDTH = 32, // default data width if the fifo is of type logic
|
||||
parameter int unsigned DEPTH = 8, // depth can be arbitrary from 0 to 2**32
|
||||
parameter int unsigned ALM_EMPTY_TH = 1, // almost empty threshold (when to assert alm_empty_o)
|
||||
parameter int unsigned ALM_FULL_TH = 1, // almost full threshold (when to assert alm_full_o)
|
||||
parameter type dtype = logic [DATA_WIDTH-1:0],
|
||||
// DO NOT OVERWRITE THIS PARAMETER
|
||||
parameter int unsigned ADDR_DEPTH = (DEPTH > 1) ? $clog2(DEPTH) : 1
|
||||
)(
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
input logic flush_i, // flush the queue
|
||||
input logic testmode_i, // test_mode to bypass clock gating
|
||||
// status flags
|
||||
output logic full_o, // queue is full
|
||||
output logic empty_o, // queue is empty
|
||||
output logic alm_full_o, // FIFO fillstate >= the specified threshold
|
||||
output logic alm_empty_o, // FIFO fillstate <= the specified threshold
|
||||
// as long as the queue is not full we can push new data
|
||||
input dtype data_i, // data to push into the queue
|
||||
input logic push_i, // data is valid and can be pushed to the queue
|
||||
// as long as the queue is not empty we can pop new elements
|
||||
output dtype data_o, // output data
|
||||
input logic pop_i // pop head from queue
|
||||
);
|
||||
|
||||
logic [ADDR_DEPTH-1:0] usage;
|
||||
|
||||
// generate threshold parameters
|
||||
if (DEPTH == 0) begin
|
||||
assign alm_full_o = 1'b0; // that signal does not make any sense in a FIFO of depth 0
|
||||
assign alm_empty_o = 1'b0; // that signal does not make any sense in a FIFO of depth 0
|
||||
end else begin
|
||||
assign alm_full_o = (usage >= ALM_FULL_TH[ADDR_DEPTH-1:0]);
|
||||
assign alm_empty_o = (usage <= ALM_EMPTY_TH[ADDR_DEPTH-1:0]);
|
||||
end
|
||||
|
||||
fifo_v3 #(
|
||||
.FALL_THROUGH ( FALL_THROUGH ),
|
||||
.DATA_WIDTH ( DATA_WIDTH ),
|
||||
.DEPTH ( DEPTH ),
|
||||
.dtype ( dtype )
|
||||
) i_fifo_v3 (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.flush_i,
|
||||
.testmode_i,
|
||||
.full_o,
|
||||
.empty_o,
|
||||
.usage_o (usage),
|
||||
.data_i,
|
||||
.push_i,
|
||||
.data_o,
|
||||
.pop_i
|
||||
);
|
||||
|
||||
// pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
initial begin
|
||||
assert (ALM_FULL_TH <= DEPTH) else $error("ALM_FULL_TH can't be larger than the DEPTH.");
|
||||
assert (ALM_EMPTY_TH <= DEPTH) else $error("ALM_EMPTY_TH can't be larger than the DEPTH.");
|
||||
end
|
||||
`endif
|
||||
// pragma translate_on
|
||||
|
||||
endmodule // fifo_v2
|
|
@ -1,83 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
//
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Deprecated, use lzc unit instead.
|
||||
|
||||
/// A leading-one finder / leading zero counter.
|
||||
/// Set FLIP to 0 for find_first_one => first_one_o is the index of the first one (from the LSB)
|
||||
/// Set FLIP to 1 for leading zero counter => first_one_o is the number of leading zeroes (from the MSB)
|
||||
module find_first_one #(
|
||||
/// The width of the input vector.
|
||||
parameter int WIDTH = -1,
|
||||
parameter int FLIP = 0
|
||||
)(
|
||||
input logic [WIDTH-1:0] in_i,
|
||||
output logic [$clog2(WIDTH)-1:0] first_one_o,
|
||||
output logic no_ones_o
|
||||
);
|
||||
|
||||
localparam int NUM_LEVELS = $clog2(WIDTH);
|
||||
|
||||
// pragma translate_off
|
||||
initial begin
|
||||
assert(WIDTH >= 0);
|
||||
end
|
||||
// pragma translate_on
|
||||
|
||||
logic [WIDTH-1:0][NUM_LEVELS-1:0] index_lut;
|
||||
logic [2**NUM_LEVELS-1:0] sel_nodes;
|
||||
logic [2**NUM_LEVELS-1:0][NUM_LEVELS-1:0] index_nodes;
|
||||
|
||||
logic [WIDTH-1:0] in_tmp;
|
||||
|
||||
for (genvar i = 0; i < WIDTH; i++) begin
|
||||
assign in_tmp[i] = FLIP ? in_i[WIDTH-1-i] : in_i[i];
|
||||
end
|
||||
|
||||
for (genvar j = 0; j < WIDTH; j++) begin
|
||||
assign index_lut[j] = j;
|
||||
end
|
||||
|
||||
for (genvar level = 0; level < NUM_LEVELS; level++) begin
|
||||
|
||||
if (level < NUM_LEVELS-1) begin
|
||||
for (genvar l = 0; l < 2**level; l++) begin
|
||||
assign sel_nodes[2**level-1+l] = sel_nodes[2**(level+1)-1+l*2] | sel_nodes[2**(level+1)-1+l*2+1];
|
||||
assign index_nodes[2**level-1+l] = (sel_nodes[2**(level+1)-1+l*2] == 1'b1) ?
|
||||
index_nodes[2**(level+1)-1+l*2] : index_nodes[2**(level+1)-1+l*2+1];
|
||||
end
|
||||
end
|
||||
|
||||
if (level == NUM_LEVELS-1) begin
|
||||
for (genvar k = 0; k < 2**level; k++) begin
|
||||
// if two successive indices are still in the vector...
|
||||
if (k * 2 < WIDTH-1) begin
|
||||
assign sel_nodes[2**level-1+k] = in_tmp[k*2] | in_tmp[k*2+1];
|
||||
assign index_nodes[2**level-1+k] = (in_tmp[k*2] == 1'b1) ? index_lut[k*2] : index_lut[k*2+1];
|
||||
end
|
||||
// if only the first index is still in the vector...
|
||||
if (k * 2 == WIDTH-1) begin
|
||||
assign sel_nodes[2**level-1+k] = in_tmp[k*2];
|
||||
assign index_nodes[2**level-1+k] = index_lut[k*2];
|
||||
end
|
||||
// if index is out of range
|
||||
if (k * 2 > WIDTH-1) begin
|
||||
assign sel_nodes[2**level-1+k] = 1'b0;
|
||||
assign index_nodes[2**level-1+k] = '0;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign first_one_o = NUM_LEVELS > 0 ? index_nodes[0] : '0;
|
||||
assign no_ones_o = NUM_LEVELS > 0 ? ~sel_nodes[0] : '1;
|
||||
|
||||
endmodule
|
|
@ -1,64 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Igor Loi <igor.loi@unibo.it>
|
||||
|
||||
module generic_LFSR_8bit
|
||||
#(
|
||||
parameter OH_WIDTH = 4,
|
||||
parameter BIN_WIDTH = $clog2(OH_WIDTH),
|
||||
parameter SEED = 8'b00000000
|
||||
)
|
||||
(
|
||||
output logic [OH_WIDTH-1:0] data_OH_o, // One hot encoding
|
||||
output logic [BIN_WIDTH-1:0] data_BIN_o, // Binary encoding
|
||||
input logic enable_i, //
|
||||
input logic clk, //
|
||||
input logic rst_n //
|
||||
);
|
||||
|
||||
logic [7:0] out;
|
||||
logic linear_feedback;
|
||||
logic [BIN_WIDTH-1:0] temp_ref_way;
|
||||
|
||||
|
||||
//-------------Code Starts Here-------
|
||||
assign linear_feedback = !(out[7] ^ out[3] ^ out[2] ^ out[1]); // TAPS for XOR feedback
|
||||
|
||||
assign data_BIN_o = temp_ref_way;
|
||||
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if (rst_n == 1'b0)
|
||||
begin
|
||||
out <= SEED ;
|
||||
end
|
||||
else if (enable_i)
|
||||
begin
|
||||
out <= {out[6],out[5],out[4],out[3],out[2],out[1],out[0], linear_feedback};
|
||||
end
|
||||
end
|
||||
|
||||
generate
|
||||
|
||||
if(OH_WIDTH == 2)
|
||||
assign temp_ref_way = out[1];
|
||||
else
|
||||
assign temp_ref_way = out[BIN_WIDTH:1];
|
||||
endgenerate
|
||||
|
||||
// Bin to One Hot Encoder
|
||||
always_comb
|
||||
begin
|
||||
data_OH_o = '0;
|
||||
data_OH_o[temp_ref_way] = 1'b1;
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -1,274 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// ============================================================================= //
|
||||
// Company: Multitherman Laboratory @ DEIS - University of Bologna //
|
||||
// Viale Risorgimento 2 40136 //
|
||||
// Bologna - fax 0512093785 - //
|
||||
// //
|
||||
// Engineer: Igor Loi - igor.loi@unibo.it //
|
||||
// //
|
||||
// //
|
||||
// Additional contributions by: //
|
||||
// //
|
||||
// //
|
||||
// //
|
||||
// Create Date: 01/02/2014 //
|
||||
// Design Name: MISC //
|
||||
// Module Name: generic_fifo //
|
||||
// Project Name: PULP //
|
||||
// Language: SystemVerilog //
|
||||
// //
|
||||
// Description: A simple FIFO used in the D_address_decoder, and D_allocator //
|
||||
// to store the destinations ports //
|
||||
// //
|
||||
// Revision: //
|
||||
// Revision v0.1 - 01/02/2014 : File Created //
|
||||
// Revision v0.2 - 02/09/2015 : Updated with a global CG cell //
|
||||
// //
|
||||
// ============================================================================= //
|
||||
|
||||
module generic_fifo
|
||||
#(
|
||||
parameter int unsigned DATA_WIDTH = 32,
|
||||
parameter int unsigned DATA_DEPTH = 8
|
||||
)
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
//PUSH SIDE
|
||||
input logic [DATA_WIDTH-1:0] data_i,
|
||||
input logic valid_i,
|
||||
output logic grant_o,
|
||||
//POP SIDE
|
||||
output logic [DATA_WIDTH-1:0] data_o,
|
||||
output logic valid_o,
|
||||
input logic grant_i,
|
||||
|
||||
input logic test_mode_i
|
||||
);
|
||||
|
||||
|
||||
// Local Parameter
|
||||
localparam int unsigned ADDR_DEPTH = $clog2(DATA_DEPTH);
|
||||
enum logic [1:0] { EMPTY, FULL, MIDDLE } CS, NS;
|
||||
// Internal Signals
|
||||
|
||||
logic gate_clock;
|
||||
logic clk_gated;
|
||||
|
||||
logic [ADDR_DEPTH-1:0] Pop_Pointer_CS, Pop_Pointer_NS;
|
||||
logic [ADDR_DEPTH-1:0] Push_Pointer_CS, Push_Pointer_NS;
|
||||
logic [DATA_WIDTH-1:0] FIFO_REGISTERS[DATA_DEPTH-1:0];
|
||||
int unsigned i;
|
||||
|
||||
// Parameter Check
|
||||
// synopsys translate_off
|
||||
initial begin : parameter_check
|
||||
integer param_err_flg;
|
||||
param_err_flg = 0;
|
||||
|
||||
if (DATA_WIDTH < 1) begin
|
||||
param_err_flg = 1;
|
||||
$display("ERROR: %m :\n Invalid value (%d) for parameter DATA_WIDTH (legal range: greater than 1)", DATA_WIDTH );
|
||||
end
|
||||
|
||||
if (DATA_DEPTH < 1) begin
|
||||
param_err_flg = 1;
|
||||
$display("ERROR: %m :\n Invalid value (%d) for parameter DATA_DEPTH (legal range: greater than 1)", DATA_DEPTH );
|
||||
end
|
||||
end
|
||||
// synopsys translate_on
|
||||
|
||||
`ifndef PULP_FPGA_EMUL
|
||||
cluster_clock_gating cg_cell
|
||||
(
|
||||
.clk_i ( clk ),
|
||||
.en_i (~gate_clock ),
|
||||
.test_en_i ( test_mode_i ),
|
||||
.clk_o ( clk_gated )
|
||||
);
|
||||
`else
|
||||
assign clk_gated = clk;
|
||||
`endif
|
||||
|
||||
// UPDATE THE STATE
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if(rst_n == 1'b0)
|
||||
begin
|
||||
CS <= EMPTY;
|
||||
Pop_Pointer_CS <= {ADDR_DEPTH {1'b0}};
|
||||
Push_Pointer_CS <= {ADDR_DEPTH {1'b0}};
|
||||
end
|
||||
else
|
||||
begin
|
||||
CS <= NS;
|
||||
Pop_Pointer_CS <= Pop_Pointer_NS;
|
||||
Push_Pointer_CS <= Push_Pointer_NS;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// Compute Next State
|
||||
always_comb
|
||||
begin
|
||||
gate_clock = 1'b0;
|
||||
|
||||
case(CS)
|
||||
|
||||
EMPTY:
|
||||
begin
|
||||
grant_o = 1'b1;
|
||||
valid_o = 1'b0;
|
||||
|
||||
case(valid_i)
|
||||
1'b0 :
|
||||
begin
|
||||
NS = EMPTY;
|
||||
Push_Pointer_NS = Push_Pointer_CS;
|
||||
Pop_Pointer_NS = Pop_Pointer_CS;
|
||||
gate_clock = 1'b1;
|
||||
end
|
||||
|
||||
1'b1:
|
||||
begin
|
||||
NS = MIDDLE;
|
||||
Push_Pointer_NS = Push_Pointer_CS + 1'b1;
|
||||
Pop_Pointer_NS = Pop_Pointer_CS;
|
||||
end
|
||||
|
||||
endcase
|
||||
end//~EMPTY
|
||||
|
||||
MIDDLE:
|
||||
begin
|
||||
grant_o = 1'b1;
|
||||
valid_o = 1'b1;
|
||||
|
||||
case({valid_i,grant_i})
|
||||
|
||||
2'b01:
|
||||
begin
|
||||
gate_clock = 1'b1;
|
||||
|
||||
if((Pop_Pointer_CS == Push_Pointer_CS -1 ) || ((Pop_Pointer_CS == DATA_DEPTH-1) && (Push_Pointer_CS == 0) ))
|
||||
NS = EMPTY;
|
||||
else
|
||||
NS = MIDDLE;
|
||||
|
||||
Push_Pointer_NS = Push_Pointer_CS;
|
||||
|
||||
if(Pop_Pointer_CS == DATA_DEPTH-1)
|
||||
Pop_Pointer_NS = 0;
|
||||
else
|
||||
Pop_Pointer_NS = Pop_Pointer_CS + 1'b1;
|
||||
end
|
||||
|
||||
2'b00 :
|
||||
begin
|
||||
gate_clock = 1'b1;
|
||||
NS = MIDDLE;
|
||||
Push_Pointer_NS = Push_Pointer_CS;
|
||||
Pop_Pointer_NS = Pop_Pointer_CS;
|
||||
end
|
||||
|
||||
2'b11:
|
||||
begin
|
||||
NS = MIDDLE;
|
||||
|
||||
if(Push_Pointer_CS == DATA_DEPTH-1)
|
||||
Push_Pointer_NS = 0;
|
||||
else
|
||||
Push_Pointer_NS = Push_Pointer_CS + 1'b1;
|
||||
|
||||
if(Pop_Pointer_CS == DATA_DEPTH-1)
|
||||
Pop_Pointer_NS = 0;
|
||||
else
|
||||
Pop_Pointer_NS = Pop_Pointer_CS + 1'b1;
|
||||
end
|
||||
|
||||
2'b10:
|
||||
begin
|
||||
if(( Push_Pointer_CS == Pop_Pointer_CS - 1) || ( (Push_Pointer_CS == DATA_DEPTH-1) && (Pop_Pointer_CS == 0) ))
|
||||
NS = FULL;
|
||||
else
|
||||
NS = MIDDLE;
|
||||
|
||||
if(Push_Pointer_CS == DATA_DEPTH - 1)
|
||||
Push_Pointer_NS = 0;
|
||||
else
|
||||
Push_Pointer_NS = Push_Pointer_CS + 1'b1;
|
||||
|
||||
Pop_Pointer_NS = Pop_Pointer_CS;
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
FULL:
|
||||
begin
|
||||
grant_o = 1'b0;
|
||||
valid_o = 1'b1;
|
||||
gate_clock = 1'b1;
|
||||
|
||||
case(grant_i)
|
||||
1'b1:
|
||||
begin
|
||||
NS = MIDDLE;
|
||||
|
||||
Push_Pointer_NS = Push_Pointer_CS;
|
||||
|
||||
if(Pop_Pointer_CS == DATA_DEPTH-1)
|
||||
Pop_Pointer_NS = 0;
|
||||
else
|
||||
Pop_Pointer_NS = Pop_Pointer_CS + 1'b1;
|
||||
end
|
||||
|
||||
1'b0:
|
||||
begin
|
||||
NS = FULL;
|
||||
Push_Pointer_NS = Push_Pointer_CS;
|
||||
Pop_Pointer_NS = Pop_Pointer_CS;
|
||||
end
|
||||
endcase
|
||||
|
||||
end // end of FULL
|
||||
|
||||
default :
|
||||
begin
|
||||
gate_clock = 1'b1;
|
||||
grant_o = 1'b0;
|
||||
valid_o = 1'b0;
|
||||
NS = EMPTY;
|
||||
Pop_Pointer_NS = 0;
|
||||
Push_Pointer_NS = 0;
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_gated, negedge rst_n)
|
||||
begin
|
||||
if(rst_n == 1'b0)
|
||||
begin
|
||||
for (i=0; i< DATA_DEPTH; i++)
|
||||
FIFO_REGISTERS[i] <= {DATA_WIDTH {1'b0}};
|
||||
end
|
||||
else
|
||||
begin
|
||||
if((grant_o == 1'b1) && (valid_i == 1'b1))
|
||||
FIFO_REGISTERS[Push_Pointer_CS] <= data_i;
|
||||
end
|
||||
end
|
||||
|
||||
assign data_o = FIFO_REGISTERS[Pop_Pointer_CS];
|
||||
|
||||
endmodule // generic_fifo
|
|
@ -1,264 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Igor Loi <igor.loi@unibo.it>
|
||||
|
||||
module generic_fifo_adv
|
||||
#(
|
||||
parameter int unsigned DATA_WIDTH = 32,
|
||||
parameter int unsigned DATA_DEPTH = 8
|
||||
)
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
input logic clear_i,
|
||||
|
||||
//PUSH SIDE
|
||||
input logic [DATA_WIDTH-1:0] data_i,
|
||||
input logic valid_i,
|
||||
output logic grant_o,
|
||||
|
||||
//POP SIDE
|
||||
output logic [DATA_WIDTH-1:0] data_o,
|
||||
output logic valid_o,
|
||||
input logic grant_i,
|
||||
|
||||
input logic test_mode_i
|
||||
);
|
||||
|
||||
|
||||
// Local Parameter
|
||||
localparam int unsigned ADDR_DEPTH = $clog2(DATA_DEPTH);
|
||||
enum logic [1:0] { EMPTY, FULL, MIDDLE } CS, NS;
|
||||
// Internal Signals
|
||||
|
||||
logic gate_clock;
|
||||
logic clk_gated;
|
||||
|
||||
logic [ADDR_DEPTH-1:0] Pop_Pointer_CS, Pop_Pointer_NS;
|
||||
logic [ADDR_DEPTH-1:0] Push_Pointer_CS, Push_Pointer_NS;
|
||||
logic [DATA_WIDTH-1:0] FIFO_REGISTERS[DATA_DEPTH-1:0];
|
||||
int unsigned i;
|
||||
|
||||
// Parameter Check
|
||||
// synopsys translate_off
|
||||
initial
|
||||
begin : parameter_check
|
||||
integer param_err_flg;
|
||||
param_err_flg = 0;
|
||||
|
||||
if (DATA_WIDTH < 1)
|
||||
begin
|
||||
param_err_flg = 1;
|
||||
$display("ERROR: %m :\n Invalid value (%d) for parameter DATA_WIDTH (legal range: greater than 1)", DATA_WIDTH );
|
||||
end
|
||||
|
||||
if (DATA_DEPTH < 1)
|
||||
begin
|
||||
param_err_flg = 1;
|
||||
$display("ERROR: %m :\n Invalid value (%d) for parameter DATA_DEPTH (legal range: greater than 1)", DATA_DEPTH );
|
||||
end
|
||||
end
|
||||
// synopsys translate_on
|
||||
|
||||
`ifndef PULP_FPGA_EMUL
|
||||
cluster_clock_gating cg_cell
|
||||
(
|
||||
.clk_i ( clk ),
|
||||
.en_i (~gate_clock ),
|
||||
.test_en_i ( test_mode_i ),
|
||||
.clk_o ( clk_gated )
|
||||
);
|
||||
`else
|
||||
assign clk_gated = clk;
|
||||
`endif
|
||||
|
||||
// UPDATE THE STATE
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if(rst_n == 1'b0)
|
||||
begin
|
||||
CS <= EMPTY;
|
||||
Pop_Pointer_CS <= {ADDR_DEPTH {1'b0}};
|
||||
Push_Pointer_CS <= {ADDR_DEPTH {1'b0}};
|
||||
end
|
||||
else
|
||||
begin
|
||||
if(clear_i)
|
||||
begin
|
||||
CS <= EMPTY;
|
||||
Pop_Pointer_CS <= {ADDR_DEPTH {1'b0}};
|
||||
Push_Pointer_CS <= {ADDR_DEPTH {1'b0}};
|
||||
end
|
||||
else
|
||||
begin
|
||||
CS <= NS;
|
||||
Pop_Pointer_CS <= Pop_Pointer_NS;
|
||||
Push_Pointer_CS <= Push_Pointer_NS;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// Compute Next State
|
||||
always_comb
|
||||
begin
|
||||
gate_clock = 1'b0;
|
||||
|
||||
case(CS)
|
||||
|
||||
EMPTY:
|
||||
begin
|
||||
grant_o = 1'b1;
|
||||
valid_o = 1'b0;
|
||||
|
||||
case(valid_i)
|
||||
1'b0 :
|
||||
begin
|
||||
NS = EMPTY;
|
||||
Push_Pointer_NS = Push_Pointer_CS;
|
||||
Pop_Pointer_NS = Pop_Pointer_CS;
|
||||
gate_clock = 1'b1;
|
||||
end
|
||||
|
||||
1'b1:
|
||||
begin
|
||||
NS = MIDDLE;
|
||||
Push_Pointer_NS = Push_Pointer_CS + 1'b1;
|
||||
Pop_Pointer_NS = Pop_Pointer_CS;
|
||||
end
|
||||
|
||||
endcase
|
||||
end//~EMPTY
|
||||
|
||||
MIDDLE:
|
||||
begin
|
||||
grant_o = 1'b1;
|
||||
valid_o = 1'b1;
|
||||
|
||||
case({valid_i,grant_i})
|
||||
|
||||
2'b01:
|
||||
begin
|
||||
gate_clock = 1'b1;
|
||||
|
||||
if((Pop_Pointer_CS == Push_Pointer_CS -1 ) || ((Pop_Pointer_CS == DATA_DEPTH-1) && (Push_Pointer_CS == 0) ))
|
||||
NS = EMPTY;
|
||||
else
|
||||
NS = MIDDLE;
|
||||
|
||||
Push_Pointer_NS = Push_Pointer_CS;
|
||||
|
||||
if(Pop_Pointer_CS == DATA_DEPTH-1)
|
||||
Pop_Pointer_NS = 0;
|
||||
else
|
||||
Pop_Pointer_NS = Pop_Pointer_CS + 1'b1;
|
||||
end
|
||||
|
||||
2'b00 :
|
||||
begin
|
||||
gate_clock = 1'b1;
|
||||
NS = MIDDLE;
|
||||
Push_Pointer_NS = Push_Pointer_CS;
|
||||
Pop_Pointer_NS = Pop_Pointer_CS;
|
||||
end
|
||||
|
||||
2'b11:
|
||||
begin
|
||||
NS = MIDDLE;
|
||||
|
||||
if(Push_Pointer_CS == DATA_DEPTH-1)
|
||||
Push_Pointer_NS = 0;
|
||||
else
|
||||
Push_Pointer_NS = Push_Pointer_CS + 1'b1;
|
||||
|
||||
if(Pop_Pointer_CS == DATA_DEPTH-1)
|
||||
Pop_Pointer_NS = 0;
|
||||
else
|
||||
Pop_Pointer_NS = Pop_Pointer_CS + 1'b1;
|
||||
end
|
||||
|
||||
2'b10:
|
||||
begin
|
||||
if(( Push_Pointer_CS == Pop_Pointer_CS - 1) || ( (Push_Pointer_CS == DATA_DEPTH-1) && (Pop_Pointer_CS == 0) ))
|
||||
NS = FULL;
|
||||
else
|
||||
NS = MIDDLE;
|
||||
|
||||
if(Push_Pointer_CS == DATA_DEPTH - 1)
|
||||
Push_Pointer_NS = 0;
|
||||
else
|
||||
Push_Pointer_NS = Push_Pointer_CS + 1'b1;
|
||||
|
||||
Pop_Pointer_NS = Pop_Pointer_CS;
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
FULL:
|
||||
begin
|
||||
grant_o = 1'b0;
|
||||
valid_o = 1'b1;
|
||||
gate_clock = 1'b1;
|
||||
|
||||
case(grant_i)
|
||||
1'b1:
|
||||
begin
|
||||
NS = MIDDLE;
|
||||
|
||||
Push_Pointer_NS = Push_Pointer_CS;
|
||||
|
||||
if(Pop_Pointer_CS == DATA_DEPTH-1)
|
||||
Pop_Pointer_NS = 0;
|
||||
else
|
||||
Pop_Pointer_NS = Pop_Pointer_CS + 1'b1;
|
||||
end
|
||||
|
||||
1'b0:
|
||||
begin
|
||||
NS = FULL;
|
||||
Push_Pointer_NS = Push_Pointer_CS;
|
||||
Pop_Pointer_NS = Pop_Pointer_CS;
|
||||
end
|
||||
endcase
|
||||
|
||||
end // end of FULL
|
||||
|
||||
default :
|
||||
begin
|
||||
gate_clock = 1'b1;
|
||||
grant_o = 1'b0;
|
||||
valid_o = 1'b0;
|
||||
NS = EMPTY;
|
||||
Pop_Pointer_NS = 0;
|
||||
Push_Pointer_NS = 0;
|
||||
end
|
||||
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_gated, negedge rst_n)
|
||||
begin
|
||||
if(rst_n == 1'b0)
|
||||
begin
|
||||
for (i=0; i< DATA_DEPTH; i++)
|
||||
FIFO_REGISTERS[i] <= {DATA_WIDTH {1'b0}};
|
||||
end
|
||||
else
|
||||
begin
|
||||
if((grant_o == 1'b1) && (valid_i == 1'b1))
|
||||
FIFO_REGISTERS[Push_Pointer_CS] <= data_i;
|
||||
end
|
||||
end
|
||||
|
||||
assign data_o = FIFO_REGISTERS[Pop_Pointer_CS];
|
||||
|
||||
endmodule // generic_fifo
|
|
@ -1,89 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
//
|
||||
// Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>, ETH Zurich
|
||||
// Date: 16.03.2019
|
||||
// Description: Priority arbiter with Lock in. Port 0 has priority over port 1, port 1 over port2
|
||||
// and so on. If the `LOCK_IN` feature is activated the arbitration decision is kept
|
||||
// when the `en_i` is low.
|
||||
|
||||
// Dependencies: relies on fast leading zero counter tree "onehot_to_bin" in common_cells
|
||||
module prioarbiter #(
|
||||
parameter int unsigned NUM_REQ = 13,
|
||||
parameter int unsigned LOCK_IN = 0
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
input logic flush_i, // clears the fsm and control signal registers
|
||||
input logic en_i, // arbiter enable
|
||||
input logic [NUM_REQ-1:0] req_i, // request signals
|
||||
|
||||
output logic [NUM_REQ-1:0] ack_o, // acknowledge signals
|
||||
output logic vld_o, // request ack'ed
|
||||
output logic [$clog2(NUM_REQ)-1:0] idx_o // idx output
|
||||
);
|
||||
|
||||
localparam SEL_WIDTH = $clog2(NUM_REQ);
|
||||
|
||||
logic [SEL_WIDTH-1:0] arb_sel_lock_d, arb_sel_lock_q;
|
||||
logic lock_d, lock_q;
|
||||
|
||||
logic [$clog2(NUM_REQ)-1:0] idx;
|
||||
|
||||
// shared
|
||||
assign vld_o = (|req_i) & en_i;
|
||||
assign idx_o = (lock_q) ? arb_sel_lock_q : idx;
|
||||
|
||||
// Arbiter
|
||||
// Port 0 has priority over all other ports
|
||||
assign ack_o[0] = (req_i[0]) ? en_i : 1'b0;
|
||||
// check that the priorities
|
||||
for (genvar i = 1; i < NUM_REQ; i++) begin : gen_arb_req_ports
|
||||
// for every subsequent port check the priorities of the previous port
|
||||
assign ack_o[i] = (req_i[i] & ~(|ack_o[i-1:0])) ? en_i : 1'b0;
|
||||
end
|
||||
|
||||
onehot_to_bin #(
|
||||
.ONEHOT_WIDTH ( NUM_REQ )
|
||||
) i_onehot_to_bin (
|
||||
.onehot ( ack_o ),
|
||||
.bin ( idx )
|
||||
);
|
||||
|
||||
if (LOCK_IN) begin : gen_lock_in
|
||||
// latch decision in case we got at least one req and no acknowledge
|
||||
assign lock_d = (|req_i) & ~en_i;
|
||||
assign arb_sel_lock_d = idx_o;
|
||||
end else begin
|
||||
// disable
|
||||
assign lock_d = '0;
|
||||
assign arb_sel_lock_d = '0;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
|
||||
if (!rst_ni) begin
|
||||
lock_q <= 1'b0;
|
||||
arb_sel_lock_q <= '0;
|
||||
end else begin
|
||||
if (flush_i) begin
|
||||
lock_q <= 1'b0;
|
||||
arb_sel_lock_q <= '0;
|
||||
end else begin
|
||||
lock_q <= lock_d;
|
||||
arb_sel_lock_q <= arb_sel_lock_d;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule : prioarbiter
|
||||
|
||||
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Antonio Pullini <pullinia@iis.ee.ethz.ch>
|
||||
|
||||
module pulp_sync
|
||||
#(
|
||||
parameter STAGES = 2
|
||||
)
|
||||
(
|
||||
input logic clk_i,
|
||||
input logic rstn_i,
|
||||
input logic serial_i,
|
||||
output logic serial_o
|
||||
);
|
||||
|
||||
logic [STAGES-1:0] r_reg;
|
||||
|
||||
always_ff @(posedge clk_i, negedge rstn_i)
|
||||
begin
|
||||
if(!rstn_i)
|
||||
r_reg <= 'h0;
|
||||
else
|
||||
r_reg <= {r_reg[STAGES-2:0], serial_i};
|
||||
end
|
||||
|
||||
assign serial_o = r_reg[STAGES-1];
|
||||
|
||||
endmodule
|
|
@ -1,55 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Antonio Pullini <pullinia@iis.ee.ethz.ch>
|
||||
|
||||
module pulp_sync_wedge #(
|
||||
parameter int unsigned STAGES = 2
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rstn_i,
|
||||
input logic en_i,
|
||||
input logic serial_i,
|
||||
output logic r_edge_o,
|
||||
output logic f_edge_o,
|
||||
output logic serial_o
|
||||
);
|
||||
logic clk;
|
||||
logic serial, serial_q;
|
||||
|
||||
assign serial_o = serial_q;
|
||||
assign f_edge_o = ~serial & serial_q;
|
||||
assign r_edge_o = serial & ~serial_q;
|
||||
|
||||
pulp_sync #(
|
||||
.STAGES(STAGES)
|
||||
) i_pulp_sync (
|
||||
.clk_i,
|
||||
.rstn_i,
|
||||
.serial_i,
|
||||
.serial_o ( serial )
|
||||
);
|
||||
|
||||
pulp_clock_gating i_pulp_clock_gating (
|
||||
.clk_i,
|
||||
.en_i,
|
||||
.test_en_i ( 1'b0 ),
|
||||
.clk_o ( clk )
|
||||
);
|
||||
|
||||
always_ff @(posedge clk, negedge rstn_i) begin
|
||||
if (!rstn_i) begin
|
||||
serial_q <= 1'b0;
|
||||
end else begin
|
||||
serial_q <= serial;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -1,61 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
//
|
||||
// Author: Michael Schaffner <schaffner@iis.ee.ethz.ch>, ETH Zurich
|
||||
// Date: 16.08.2018
|
||||
// Description: Fair round robin arbiter with lock feature.
|
||||
//
|
||||
// The rrarbiter employs fair round robin arbitration - i.e. the priorities
|
||||
// rotate each cycle.
|
||||
//
|
||||
// The lock-in feature prevents the arbiter from changing the arbitration
|
||||
// decision when the arbiter is disabled. I.e., the index of the first request
|
||||
// that wins the arbitration will be locked until en_i is asserted again.
|
||||
//
|
||||
// Dependencies: relies on rr_arb_tree from common_cells.
|
||||
|
||||
module rrarbiter #(
|
||||
parameter int unsigned NUM_REQ = 64,
|
||||
parameter bit LOCK_IN = 1'b0
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
input logic flush_i, // clears arbiter state
|
||||
input logic en_i, // arbiter enable
|
||||
input logic [NUM_REQ-1:0] req_i, // request signals
|
||||
|
||||
output logic [NUM_REQ-1:0] ack_o, // acknowledge signals
|
||||
output logic vld_o, // request ack'ed
|
||||
output logic [$clog2(NUM_REQ)-1:0] idx_o // idx output
|
||||
);
|
||||
|
||||
logic req;
|
||||
assign vld_o = (|req_i) & en_i;
|
||||
|
||||
rr_arb_tree #(
|
||||
.NumIn ( NUM_REQ ),
|
||||
.DataWidth ( 1 ),
|
||||
.LockIn ( LOCK_IN ))
|
||||
i_rr_arb_tree (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.flush_i ( flush_i ),
|
||||
.rr_i ( '0 ),
|
||||
.req_i ( req_i ),
|
||||
.gnt_o ( ack_o ),
|
||||
.data_i ( '0 ),
|
||||
.gnt_i ( en_i & req ),
|
||||
.req_o ( req ),
|
||||
.data_o ( ),
|
||||
.idx_o ( idx_o )
|
||||
);
|
||||
|
||||
endmodule : rrarbiter
|
|
@ -1,32 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Author: Florian Zaruba
|
||||
// Description: Edge detector, clock needs to oversample for proper edge detection
|
||||
|
||||
module edge_detect (
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
input logic d_i, // data stream in
|
||||
output logic re_o, // rising edge detected
|
||||
output logic fe_o // falling edge detected
|
||||
);
|
||||
|
||||
sync_wedge i_sync_wedge (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.en_i ( 1'b1 ),
|
||||
.serial_i ( d_i ),
|
||||
.r_edge_o ( re_o ),
|
||||
.f_edge_o ( fe_o ),
|
||||
.serial_o ( )
|
||||
);
|
||||
|
||||
endmodule
|
|
@ -1,50 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Antonio Pullini <pullinia@iis.ee.ethz.ch>
|
||||
|
||||
module edge_propagator (
|
||||
input logic clk_tx_i,
|
||||
input logic rstn_tx_i,
|
||||
input logic edge_i,
|
||||
input logic clk_rx_i,
|
||||
input logic rstn_rx_i,
|
||||
output logic edge_o
|
||||
);
|
||||
|
||||
logic [1:0] sync_a;
|
||||
logic sync_b;
|
||||
|
||||
logic r_input_reg;
|
||||
logic s_input_reg_next;
|
||||
|
||||
assign s_input_reg_next = edge_i | (r_input_reg & (~sync_a[0]));
|
||||
|
||||
always @(negedge rstn_tx_i or posedge clk_tx_i) begin
|
||||
if (~rstn_tx_i) begin
|
||||
r_input_reg <= 1'b0;
|
||||
sync_a <= 2'b00;
|
||||
end else begin
|
||||
r_input_reg <= s_input_reg_next;
|
||||
sync_a <= {sync_b,sync_a[1]};
|
||||
end
|
||||
end
|
||||
|
||||
pulp_sync_wedge i_sync_clkb (
|
||||
.clk_i ( clk_rx_i ),
|
||||
.rstn_i ( rstn_rx_i ),
|
||||
.en_i ( 1'b1 ),
|
||||
.serial_i ( r_input_reg ),
|
||||
.r_edge_o ( edge_o ),
|
||||
.f_edge_o ( ),
|
||||
.serial_o ( sync_b )
|
||||
);
|
||||
|
||||
endmodule
|
|
@ -1,31 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Antonio Pullini <pullinia@iis.ee.ethz.ch>
|
||||
|
||||
module edge_propagator_rx (
|
||||
input logic clk_i,
|
||||
input logic rstn_i,
|
||||
input logic valid_i,
|
||||
output logic ack_o,
|
||||
output logic valid_o
|
||||
);
|
||||
|
||||
pulp_sync_wedge i_sync_clkb (
|
||||
.clk_i ( clk_i ),
|
||||
.rstn_i ( rstn_i ),
|
||||
.en_i ( 1'b1 ),
|
||||
.serial_i ( valid_i ),
|
||||
.r_edge_o ( valid_o ),
|
||||
.f_edge_o ( ),
|
||||
.serial_o ( ack_o )
|
||||
);
|
||||
|
||||
endmodule
|
|
@ -1,40 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Antonio Pullini <pullinia@iis.ee.ethz.ch>
|
||||
|
||||
module edge_propagator_tx (
|
||||
input logic clk_i,
|
||||
input logic rstn_i,
|
||||
input logic valid_i,
|
||||
input logic ack_i,
|
||||
output logic valid_o
|
||||
);
|
||||
|
||||
logic [1:0] sync_a;
|
||||
|
||||
logic r_input_reg;
|
||||
logic s_input_reg_next;
|
||||
|
||||
assign s_input_reg_next = valid_i | (r_input_reg & ~sync_a[0]);
|
||||
|
||||
always @(negedge rstn_i or posedge clk_i) begin
|
||||
if (~rstn_i) begin
|
||||
r_input_reg <= 1'b0;
|
||||
sync_a <= 2'b00;
|
||||
end else begin
|
||||
r_input_reg <= s_input_reg_next;
|
||||
sync_a <= {ack_i,sync_a[1]};
|
||||
end
|
||||
end
|
||||
|
||||
assign valid_o = r_input_reg;
|
||||
|
||||
endmodule
|
|
@ -1,94 +0,0 @@
|
|||
// Copyright 2019 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
//
|
||||
// Author: Michael Schaffner <schaffner@iis.ee.ethz.ch>, ETH Zurich
|
||||
// Date: 10.04.2019
|
||||
// Description: exponential backoff counter with randomization.
|
||||
//
|
||||
// For each failed trial (set_i pulsed), this unit exponentially increases the
|
||||
// (average) backoff time by masking an LFSR with a shifted mask in order to
|
||||
// create the backoff counter initial value.
|
||||
//
|
||||
// The shift register mask and the counter value are both reset to '0 in case of
|
||||
// a successful trial (clr_i).
|
||||
//
|
||||
|
||||
module exp_backoff #(
|
||||
parameter int unsigned Seed = 'hffff, // seed for 16bit lfsr
|
||||
parameter int unsigned MaxExp = 16 // 2**MaxExp-1 determines the maximum range from which random wait counts are drawn
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
//
|
||||
input logic set_i, // sets the backoff counter (pulse) -> use when trial did not succeed
|
||||
input logic clr_i, // clears the backoff counter (pulse) -> use when trial succeeded
|
||||
output logic is_zero_o // indicates whether the backoff counter is equal to zero and a new trial can be launched
|
||||
);
|
||||
|
||||
// leave this constant
|
||||
localparam WIDTH = 16;
|
||||
|
||||
logic [WIDTH-1:0] lfsr_d, lfsr_q, cnt_d, cnt_q, mask_d, mask_q;
|
||||
logic lfsr;
|
||||
|
||||
// generate random wait counts
|
||||
// note: we use a flipped lfsr here to
|
||||
// avoid strange correlation effects between
|
||||
// the (left-shifted) mask and the lfsr
|
||||
assign lfsr = lfsr_q[15-15] ^
|
||||
lfsr_q[15-13] ^
|
||||
lfsr_q[15-12] ^
|
||||
lfsr_q[15-10];
|
||||
|
||||
assign lfsr_d = (set_i) ? {lfsr, lfsr_q[$high(lfsr_q):1]} :
|
||||
lfsr_q;
|
||||
|
||||
// mask the wait counts with exponentially increasing mask (shift reg)
|
||||
assign mask_d = (clr_i) ? '0 :
|
||||
(set_i) ? {{(WIDTH-MaxExp){1'b0}},mask_q[MaxExp-2:0], 1'b1} :
|
||||
mask_q;
|
||||
|
||||
assign cnt_d = (clr_i) ? '0 :
|
||||
(set_i) ? (mask_q & lfsr_q) :
|
||||
(!is_zero_o) ? cnt_q - 1'b1 : '0;
|
||||
|
||||
assign is_zero_o = (cnt_q=='0);
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
|
||||
if (!rst_ni) begin
|
||||
lfsr_q <= WIDTH'(Seed);
|
||||
mask_q <= '0;
|
||||
cnt_q <= '0;
|
||||
end else begin
|
||||
lfsr_q <= lfsr_d;
|
||||
mask_q <= mask_d;
|
||||
cnt_q <= cnt_d;
|
||||
end
|
||||
end
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// assertions
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
//pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
initial begin
|
||||
// assert wrong parameterizations
|
||||
assert (MaxExp>0)
|
||||
else $fatal(1,"MaxExp must be greater than 0");
|
||||
assert (MaxExp<=16)
|
||||
else $fatal(1,"MaxExp cannot be greater than 16");
|
||||
assert (Seed>0)
|
||||
else $fatal(1,"Zero seed is not allowed for LFSR");
|
||||
end
|
||||
`endif
|
||||
//pragma translate_on
|
||||
|
||||
endmodule // exp_backoff
|
|
@ -1,58 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Fall-through register with a simple stream-like ready/valid handshake.
|
||||
// This register does not cut combinatorial paths on any signals: in case the module at its output
|
||||
// is ready to accept data within the same clock cycle, they are forwarded. Use this module to get a
|
||||
// 'default ready' behavior towards the input.
|
||||
module fall_through_register #(
|
||||
parameter type T = logic // Vivado requires a default value for type parameters.
|
||||
) (
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous active-low reset
|
||||
input logic clr_i, // Synchronous clear
|
||||
input logic testmode_i, // Test mode to bypass clock gating
|
||||
// Input port
|
||||
input logic valid_i,
|
||||
output logic ready_o,
|
||||
input T data_i,
|
||||
// Output port
|
||||
output logic valid_o,
|
||||
input logic ready_i,
|
||||
output T data_o
|
||||
);
|
||||
|
||||
logic fifo_empty,
|
||||
fifo_full;
|
||||
|
||||
fifo_v2 #(
|
||||
.FALL_THROUGH (1'b1),
|
||||
.DATA_WIDTH ($size(T)),
|
||||
.DEPTH (1),
|
||||
.dtype (T)
|
||||
) i_fifo (
|
||||
.clk_i (clk_i),
|
||||
.rst_ni (rst_ni),
|
||||
.flush_i (clr_i),
|
||||
.testmode_i (testmode_i),
|
||||
.full_o (fifo_full),
|
||||
.empty_o (fifo_empty),
|
||||
.alm_full_o ( ),
|
||||
.alm_empty_o ( ),
|
||||
.data_i (data_i),
|
||||
.push_i (valid_i & ~fifo_full),
|
||||
.data_o (data_o),
|
||||
.pop_i (ready_i & ~fifo_empty)
|
||||
);
|
||||
|
||||
assign ready_o = ~fifo_full;
|
||||
assign valid_o = ~fifo_empty;
|
||||
|
||||
endmodule
|
|
@ -1,153 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
|
||||
|
||||
module fifo_v3 #(
|
||||
parameter bit FALL_THROUGH = 1'b0, // fifo is in fall-through mode
|
||||
parameter int unsigned DATA_WIDTH = 32, // default data width if the fifo is of type logic
|
||||
parameter int unsigned DEPTH = 8, // depth can be arbitrary from 0 to 2**32
|
||||
parameter type dtype = logic [DATA_WIDTH-1:0],
|
||||
// DO NOT OVERWRITE THIS PARAMETER
|
||||
parameter int unsigned ADDR_DEPTH = (DEPTH > 1) ? $clog2(DEPTH) : 1
|
||||
)(
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
input logic flush_i, // flush the queue
|
||||
input logic testmode_i, // test_mode to bypass clock gating
|
||||
// status flags
|
||||
output logic full_o, // queue is full
|
||||
output logic empty_o, // queue is empty
|
||||
output logic [ADDR_DEPTH-1:0] usage_o, // fill pointer
|
||||
// as long as the queue is not full we can push new data
|
||||
input dtype data_i, // data to push into the queue
|
||||
input logic push_i, // data is valid and can be pushed to the queue
|
||||
// as long as the queue is not empty we can pop new elements
|
||||
output dtype data_o, // output data
|
||||
input logic pop_i // pop head from queue
|
||||
);
|
||||
// local parameter
|
||||
// FIFO depth - handle the case of pass-through, synthesizer will do constant propagation
|
||||
localparam int unsigned FIFO_DEPTH = (DEPTH > 0) ? DEPTH : 1;
|
||||
// clock gating control
|
||||
logic gate_clock;
|
||||
// pointer to the read and write section of the queue
|
||||
logic [ADDR_DEPTH - 1:0] read_pointer_n, read_pointer_q, write_pointer_n, write_pointer_q;
|
||||
// keep a counter to keep track of the current queue status
|
||||
logic [ADDR_DEPTH:0] status_cnt_n, status_cnt_q; // this integer will be truncated by the synthesis tool
|
||||
// actual memory
|
||||
dtype [FIFO_DEPTH - 1:0] mem_n, mem_q;
|
||||
|
||||
assign usage_o = status_cnt_q[ADDR_DEPTH-1:0];
|
||||
|
||||
if (DEPTH == 0) begin
|
||||
assign empty_o = ~push_i;
|
||||
assign full_o = ~pop_i;
|
||||
end else begin
|
||||
assign full_o = (status_cnt_q == FIFO_DEPTH[ADDR_DEPTH:0]);
|
||||
assign empty_o = (status_cnt_q == 0) & ~(FALL_THROUGH & push_i);
|
||||
end
|
||||
// status flags
|
||||
|
||||
// read and write queue logic
|
||||
always_comb begin : read_write_comb
|
||||
// default assignment
|
||||
read_pointer_n = read_pointer_q;
|
||||
write_pointer_n = write_pointer_q;
|
||||
status_cnt_n = status_cnt_q;
|
||||
data_o = (DEPTH == 0) ? data_i : mem_q[read_pointer_q];
|
||||
mem_n = mem_q;
|
||||
gate_clock = 1'b1;
|
||||
|
||||
// push a new element to the queue
|
||||
if (push_i && ~full_o) begin
|
||||
// push the data onto the queue
|
||||
mem_n[write_pointer_q] = data_i;
|
||||
// un-gate the clock, we want to write something
|
||||
gate_clock = 1'b0;
|
||||
// increment the write counter
|
||||
if (write_pointer_q == FIFO_DEPTH[ADDR_DEPTH-1:0] - 1)
|
||||
write_pointer_n = '0;
|
||||
else
|
||||
write_pointer_n = write_pointer_q + 1;
|
||||
// increment the overall counter
|
||||
status_cnt_n = status_cnt_q + 1;
|
||||
end
|
||||
|
||||
if (pop_i && ~empty_o) begin
|
||||
// read from the queue is a default assignment
|
||||
// but increment the read pointer...
|
||||
if (read_pointer_n == FIFO_DEPTH[ADDR_DEPTH-1:0] - 1)
|
||||
read_pointer_n = '0;
|
||||
else
|
||||
read_pointer_n = read_pointer_q + 1;
|
||||
// ... and decrement the overall count
|
||||
status_cnt_n = status_cnt_q - 1;
|
||||
end
|
||||
|
||||
// keep the count pointer stable if we push and pop at the same time
|
||||
if (push_i && pop_i && ~full_o && ~empty_o)
|
||||
status_cnt_n = status_cnt_q;
|
||||
|
||||
// FIFO is in pass through mode -> do not change the pointers
|
||||
if (FALL_THROUGH && (status_cnt_q == 0) && push_i) begin
|
||||
data_o = data_i;
|
||||
if (pop_i) begin
|
||||
status_cnt_n = status_cnt_q;
|
||||
read_pointer_n = read_pointer_q;
|
||||
write_pointer_n = write_pointer_q;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// sequential process
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if(~rst_ni) begin
|
||||
read_pointer_q <= '0;
|
||||
write_pointer_q <= '0;
|
||||
status_cnt_q <= '0;
|
||||
end else begin
|
||||
if (flush_i) begin
|
||||
read_pointer_q <= '0;
|
||||
write_pointer_q <= '0;
|
||||
status_cnt_q <= '0;
|
||||
end else begin
|
||||
read_pointer_q <= read_pointer_n;
|
||||
write_pointer_q <= write_pointer_n;
|
||||
status_cnt_q <= status_cnt_n;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if(~rst_ni) begin
|
||||
mem_q <= '0;
|
||||
end else if (!gate_clock) begin
|
||||
mem_q <= mem_n;
|
||||
end
|
||||
end
|
||||
|
||||
// pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
initial begin
|
||||
assert (DEPTH > 0) else $error("DEPTH must be greater than 0.");
|
||||
end
|
||||
|
||||
full_write : assert property(
|
||||
@(posedge clk_i) disable iff (~rst_ni) (full_o |-> ~push_i))
|
||||
else $fatal (1, "Trying to push new data although the FIFO is full.");
|
||||
|
||||
empty_read : assert property(
|
||||
@(posedge clk_i) disable iff (~rst_ni) (empty_o |-> ~pop_i))
|
||||
else $fatal (1, "Trying to pop data although the FIFO is empty.");
|
||||
`endif
|
||||
// pragma translate_on
|
||||
|
||||
endmodule // fifo_v3
|
|
@ -1,33 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
//
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
//
|
||||
// Fabian Schuiki <fschuiki@iis.ee.ethz.ch>
|
||||
|
||||
/// A binary to gray code converter.
|
||||
module binary_to_gray #(
|
||||
parameter int N = -1
|
||||
)(
|
||||
input logic [N-1:0] A,
|
||||
output logic [N-1:0] Z
|
||||
);
|
||||
assign Z = A ^ (A >> 1);
|
||||
endmodule
|
||||
|
||||
/// A gray code to binary converter.
|
||||
module gray_to_binary #(
|
||||
parameter int N = -1
|
||||
)(
|
||||
input logic [N-1:0] A,
|
||||
output logic [N-1:0] Z
|
||||
);
|
||||
for (genvar i = 0; i < N; i++)
|
||||
assign Z[i] = ^A[N-1:i];
|
||||
endmodule
|
|
@ -1,268 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// ID Queue
|
||||
//
|
||||
// In an ID queue, every element has a numeric ID. Among all elements that have the same ID, the ID
|
||||
// queue preserves FIFO order.
|
||||
//
|
||||
// This ID queue implementation allows to either push (through the `inp_*` signals) or pop (through
|
||||
// the `oup_*` signals) one element per clock cycle. The `inp_` port has priority and grants a
|
||||
// request iff the queue is not full. The `oup_` port dequeues an element iff `oup_pop_i` is
|
||||
// asserted during an `oup_` handshake; otherwise, it performs a non-destructive read. `oup_data_o`
|
||||
// is valid iff `oup_data_valid_o` is asserted during an `oup_` handshake. If `oup_data_valid_o` is
|
||||
// not asserted, the queue did not contain an element with the provided ID.
|
||||
//
|
||||
// This ID queue additionally provides the `exists_` port, which searches for an element anywhere in
|
||||
// the queue. The comparison performed during the search can be masked: for every bit that is
|
||||
// asserted in `exists_mask_i`, the corresponding bit in the queue element and in `exists_data_i`
|
||||
// must be equal for a match; the other bits are not compared. If masking is not required, tie
|
||||
// `exists_mask_i_ to `'1` and the synthesizer should simplify the comparisons to unmasked ones. The
|
||||
// `exists_` port operates independently of the `inp_` and `oup_` ports. If the `exists_` port is
|
||||
// unused, tie `exists_req_i` to `1'b0` and the synthesizer should remove the internal comparators.
|
||||
//
|
||||
// This ID queue can store at most `CAPACITY` elements, independent of their ID. Let
|
||||
// - C = `CAPACITY`
|
||||
// - B = $bits(data_t)
|
||||
// - I = 2**`ID_WIDTH`
|
||||
// Then
|
||||
// - the queue element storage requires O(C * (B + log2(C))) bit
|
||||
// - the ID table requires O(H * log2(C)) bit, where H = min(C, I)
|
||||
//
|
||||
// Maintainers:
|
||||
// - Andreas Kurth <akurth@iis.ee.ethz.ch>
|
||||
|
||||
module id_queue #(
|
||||
parameter int ID_WIDTH = 0,
|
||||
parameter int CAPACITY = 0,
|
||||
parameter type data_t = logic,
|
||||
// Dependent parameters, DO NOT OVERRIDE!
|
||||
localparam type id_t = logic[ID_WIDTH-1:0],
|
||||
localparam type mask_t = logic[$bits(data_t)-1:0]
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
input id_t inp_id_i,
|
||||
input data_t inp_data_i,
|
||||
input logic inp_req_i,
|
||||
output logic inp_gnt_o,
|
||||
|
||||
input data_t exists_data_i,
|
||||
input mask_t exists_mask_i,
|
||||
input logic exists_req_i,
|
||||
output logic exists_o,
|
||||
output logic exists_gnt_o,
|
||||
|
||||
input id_t oup_id_i,
|
||||
input logic oup_pop_i,
|
||||
input logic oup_req_i,
|
||||
output data_t oup_data_o,
|
||||
output logic oup_data_valid_o,
|
||||
output logic oup_gnt_o
|
||||
);
|
||||
|
||||
// Capacity of the head-tail table, which associates an ID with corresponding head and tail
|
||||
// indices.
|
||||
localparam int N_IDS = 2**ID_WIDTH;
|
||||
localparam int HT_CAPACITY = (N_IDS <= CAPACITY) ? N_IDS : CAPACITY;
|
||||
|
||||
// Type for indexing the head-tail table.
|
||||
typedef logic [$clog2(HT_CAPACITY)-1:0] ht_idx_t;
|
||||
|
||||
// Type for indexing the lined data table.
|
||||
typedef logic [$clog2(CAPACITY)-1:0] ld_idx_t;
|
||||
|
||||
// Type of an entry in the head-tail table.
|
||||
typedef struct packed {
|
||||
id_t id;
|
||||
ld_idx_t head,
|
||||
tail;
|
||||
logic free;
|
||||
} head_tail_t;
|
||||
|
||||
// Type of an entry in the linked data table.
|
||||
typedef struct packed {
|
||||
data_t data;
|
||||
ld_idx_t next;
|
||||
logic free;
|
||||
} linked_data_t;
|
||||
|
||||
head_tail_t [HT_CAPACITY-1:0] head_tail_d, head_tail_q;
|
||||
|
||||
linked_data_t [CAPACITY-1:0] linked_data_d, linked_data_q;
|
||||
|
||||
logic full,
|
||||
match_id_valid,
|
||||
no_id_match;
|
||||
|
||||
logic [HT_CAPACITY-1:0] head_tail_free,
|
||||
idx_matches_id;
|
||||
|
||||
logic [CAPACITY-1:0] exists_match,
|
||||
linked_data_free;
|
||||
|
||||
id_t match_id;
|
||||
|
||||
ht_idx_t head_tail_free_idx,
|
||||
match_idx;
|
||||
|
||||
ld_idx_t linked_data_free_idx;
|
||||
|
||||
// Find the index in the head-tail table that matches a given ID.
|
||||
for (genvar i = 0; i < HT_CAPACITY; i++) begin: gen_idx_match
|
||||
assign idx_matches_id[i] = match_id_valid && (head_tail_q[i].id == match_id) &&
|
||||
!head_tail_q[i].free;
|
||||
end
|
||||
assign no_id_match = !(|idx_matches_id);
|
||||
onehot_to_bin #(
|
||||
.ONEHOT_WIDTH (HT_CAPACITY)
|
||||
) i_id_ohb (
|
||||
.onehot (idx_matches_id),
|
||||
.bin (match_idx)
|
||||
);
|
||||
|
||||
// Find the first free index in the head-tail table.
|
||||
for (genvar i = 0; i < HT_CAPACITY; i++) begin: gen_head_tail_free
|
||||
assign head_tail_free[i] = head_tail_q[i].free;
|
||||
end
|
||||
lzc #(
|
||||
.WIDTH (HT_CAPACITY),
|
||||
.MODE (0) // Start at index 0.
|
||||
) i_ht_free_lzc (
|
||||
.in_i (head_tail_free),
|
||||
.cnt_o (head_tail_free_idx),
|
||||
.empty_o ()
|
||||
);
|
||||
|
||||
// Find the first free index in the linked data table.
|
||||
for (genvar i = 0; i < CAPACITY; i++) begin: gen_linked_data_free
|
||||
assign linked_data_free[i] = linked_data_q[i].free;
|
||||
end
|
||||
lzc #(
|
||||
.WIDTH (CAPACITY),
|
||||
.MODE (0) // Start at index 0.
|
||||
) i_ld_free_lzc (
|
||||
.in_i (linked_data_free),
|
||||
.cnt_o (linked_data_free_idx),
|
||||
.empty_o ()
|
||||
);
|
||||
|
||||
// The queue is full if and only if there are no free items in the linked data structure.
|
||||
assign full = !(|linked_data_free);
|
||||
|
||||
assign inp_gnt_o = ~full;
|
||||
always_comb begin
|
||||
match_id = 'x;
|
||||
match_id_valid = 1'b0;
|
||||
head_tail_d = head_tail_q;
|
||||
linked_data_d = linked_data_q;
|
||||
oup_gnt_o = 1'b0;
|
||||
oup_data_o = data_t'('x);
|
||||
oup_data_valid_o = 1'b0;
|
||||
if (inp_req_i && !full) begin
|
||||
match_id = inp_id_i;
|
||||
match_id_valid = 1'b1;
|
||||
// If the ID does not yet exist in the queue, add a new ID entry.
|
||||
if (no_id_match) begin
|
||||
head_tail_d[head_tail_free_idx] = '{
|
||||
id: inp_id_i,
|
||||
head: linked_data_free_idx,
|
||||
tail: linked_data_free_idx,
|
||||
free: 1'b0
|
||||
};
|
||||
// Otherwise append it to the existing ID subqueue.
|
||||
end else begin
|
||||
linked_data_d[head_tail_q[match_idx].tail].next = linked_data_free_idx;
|
||||
head_tail_d[match_idx].tail = linked_data_free_idx;
|
||||
end
|
||||
linked_data_d[linked_data_free_idx] = '{
|
||||
data: inp_data_i,
|
||||
next: 'x,
|
||||
free: 1'b0
|
||||
};
|
||||
end else if (oup_req_i) begin
|
||||
match_id = oup_id_i;
|
||||
match_id_valid = 1'b1;
|
||||
if (!no_id_match) begin
|
||||
oup_data_o = data_t'(linked_data_q[head_tail_q[match_idx].head].data);
|
||||
oup_data_valid_o = 1'b1;
|
||||
if (oup_pop_i) begin
|
||||
// Set free bit of linked data entry, all other bits are don't care.
|
||||
linked_data_d[head_tail_q[match_idx].head] = 'x;
|
||||
linked_data_d[head_tail_q[match_idx].head][0] = 1'b1;
|
||||
if (head_tail_q[match_idx].head == head_tail_q[match_idx].tail) begin
|
||||
head_tail_d[match_idx] = '{free: 1'b1, default: 'x};
|
||||
end else begin
|
||||
head_tail_d[match_idx].head = linked_data_q[head_tail_q[match_idx].head].next;
|
||||
end
|
||||
end
|
||||
end
|
||||
// Always grant the output request. If there was no match, the default, invalid entry
|
||||
// will be returned.
|
||||
oup_gnt_o = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
// Exists Lookup
|
||||
for (genvar i = 0; i < CAPACITY; i++) begin: gen_lookup
|
||||
mask_t exists_match_bits;
|
||||
for (genvar j = 0; j < $bits(data_t); j++) begin: gen_mask
|
||||
always_comb begin
|
||||
if (linked_data_q[i].free) begin
|
||||
exists_match_bits[j] = 1'b0;
|
||||
end else begin
|
||||
if (!exists_mask_i[j]) begin
|
||||
exists_match_bits[j] = 1'b1;
|
||||
end else begin
|
||||
exists_match_bits[j] = (linked_data_q[i].data[j] == exists_data_i[j]);
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
assign exists_match[i] = (&exists_match_bits);
|
||||
end
|
||||
always_comb begin
|
||||
exists_gnt_o = 1'b0;
|
||||
exists_o = 'x;
|
||||
if (exists_req_i) begin
|
||||
exists_gnt_o = 1'b1;
|
||||
exists_o = (|exists_match);
|
||||
end
|
||||
end
|
||||
|
||||
// Registers
|
||||
for (genvar i = 0; i < CAPACITY; i++) begin: gen_ffs
|
||||
always_ff @(posedge clk_i, negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
head_tail_q[i] <= '{free: 1'b1, default: 'x};
|
||||
// Set free bit of linked data entries, all other bits are don't care.
|
||||
linked_data_q[i] <= 'x;
|
||||
linked_data_q[i][0] <= 1'b1;
|
||||
end else begin
|
||||
head_tail_q[i] <= head_tail_d[i];
|
||||
linked_data_q[i] <= linked_data_d[i];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Validate parameters.
|
||||
// pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
initial begin: validate_params
|
||||
assert (ID_WIDTH >= 1)
|
||||
else $fatal("The ID must at least be one bit wide!");
|
||||
assert (CAPACITY >= 1)
|
||||
else $fatal("The queue must have capacity of at least one entry!");
|
||||
end
|
||||
`endif
|
||||
// pragma translate_on
|
||||
|
||||
endmodule
|
|
@ -1,310 +0,0 @@
|
|||
// Copyright 2019 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
//
|
||||
// Author: Michael Schaffner <schaffner@iis.ee.ethz.ch>, ETH Zurich
|
||||
// Date: 26.04.2019
|
||||
//
|
||||
// Description: This is a parametric LFSR with precomputed coefficients for
|
||||
// LFSR lengths from 4 to 64bit.
|
||||
|
||||
// Additional block cipher layers can be instantiated to non-linearly transform
|
||||
// the pseudo-random LFSR sequence at the output, and hence break the shifting
|
||||
// patterns. The additional cipher layers can only be used for an LFSR width
|
||||
// of 64bit, since the block cipher has been designed for that block length.
|
||||
|
||||
module lfsr #(
|
||||
parameter int unsigned LfsrWidth = 64, // [4,64]
|
||||
parameter int unsigned OutWidth = 8, // [1,LfsrWidth]
|
||||
parameter logic [LfsrWidth-1:0] RstVal = '1, // [1,2^LfsrWidth-1]
|
||||
// 0: disabled, the present cipher uses 31, but just a few layers (1-3) are enough
|
||||
// to break linear shifting patterns
|
||||
parameter int unsigned CipherLayers = 0,
|
||||
parameter bit CipherReg = 1'b1 // additional output reg after cipher
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic en_i,
|
||||
output logic [OutWidth-1:0] out_o
|
||||
);
|
||||
|
||||
// Galois LFSR feedback masks
|
||||
// Automatically generated with get_lfsr_masks.py
|
||||
// Masks are from https://users.ece.cmu.edu/~koopman/lfsr/
|
||||
localparam logic [63:0] masks [4:64] = '{64'hC,
|
||||
64'h1E,
|
||||
64'h39,
|
||||
64'h7E,
|
||||
64'hFA,
|
||||
64'h1FD,
|
||||
64'h3FC,
|
||||
64'h64B,
|
||||
64'hD8F,
|
||||
64'h1296,
|
||||
64'h2496,
|
||||
64'h4357,
|
||||
64'h8679,
|
||||
64'h1030E,
|
||||
64'h206CD,
|
||||
64'h403FE,
|
||||
64'h807B8,
|
||||
64'h1004B2,
|
||||
64'h2006A8,
|
||||
64'h4004B2,
|
||||
64'h800B87,
|
||||
64'h10004F3,
|
||||
64'h200072D,
|
||||
64'h40006AE,
|
||||
64'h80009E3,
|
||||
64'h10000583,
|
||||
64'h20000C92,
|
||||
64'h400005B6,
|
||||
64'h80000EA6,
|
||||
64'h1000007A3,
|
||||
64'h200000ABF,
|
||||
64'h400000842,
|
||||
64'h80000123E,
|
||||
64'h100000074E,
|
||||
64'h2000000AE9,
|
||||
64'h400000086A,
|
||||
64'h8000001213,
|
||||
64'h1000000077E,
|
||||
64'h2000000123B,
|
||||
64'h40000000877,
|
||||
64'h8000000108D,
|
||||
64'h100000000AE9,
|
||||
64'h200000000E9F,
|
||||
64'h4000000008A6,
|
||||
64'h80000000191E,
|
||||
64'h100000000090E,
|
||||
64'h2000000000FB3,
|
||||
64'h4000000000D7D,
|
||||
64'h80000000016A5,
|
||||
64'h10000000000B4B,
|
||||
64'h200000000010AF,
|
||||
64'h40000000000DDE,
|
||||
64'h8000000000181A,
|
||||
64'h100000000000B65,
|
||||
64'h20000000000102D,
|
||||
64'h400000000000CD5,
|
||||
64'h8000000000024C1,
|
||||
64'h1000000000000EF6,
|
||||
64'h2000000000001363,
|
||||
64'h4000000000000FCD,
|
||||
64'h80000000000019E2};
|
||||
|
||||
// this S-box and permutation P has been taken from the Present Cipher,
|
||||
// a super lightweight block cipher. use the cipher layers to add additional
|
||||
// non-linearity to the LFSR output. note one layer does not fully correspond
|
||||
// to the present cipher round, since the key and rekeying function is not applied here.
|
||||
//
|
||||
// See also:
|
||||
// "PRESENT: An Ultra-Lightweight Block Cipher", A. Bogdanov et al., Ches 2007
|
||||
// http://www.lightweightcrypto.org/present/present_ches2007.pdf
|
||||
|
||||
// this is the sbox from the present cipher
|
||||
localparam logic[15:0][3:0] sbox4 = {4'h2, 4'h1, 4'h7, 4'h4,
|
||||
4'h8, 4'hF, 4'hE, 4'h3,
|
||||
4'hD, 4'hA, 4'h0, 4'h9,
|
||||
4'hB, 4'h6, 4'h5, 4'hC };
|
||||
|
||||
// these are the permutation indices of the present cipher
|
||||
localparam logic[63:0][5:0] perm = {6'd63, 6'd47, 6'd31, 6'd15, 6'd62, 6'd46, 6'd30, 6'd14, 6'd61, 6'd45, 6'd29, 6'd13, 6'd60, 6'd44, 6'd28, 6'd12,
|
||||
6'd59, 6'd43, 6'd27, 6'd11, 6'd58, 6'd42, 6'd26, 6'd10, 6'd57, 6'd41, 6'd25, 6'd09, 6'd56, 6'd40, 6'd24, 6'd08,
|
||||
6'd55, 6'd39, 6'd23, 6'd07, 6'd54, 6'd38, 6'd22, 6'd06, 6'd53, 6'd37, 6'd21, 6'd05, 6'd52, 6'd36, 6'd20, 6'd04,
|
||||
6'd51, 6'd35, 6'd19, 6'd03, 6'd50, 6'd34, 6'd18, 6'd02, 6'd49, 6'd33, 6'd17, 6'd01, 6'd48, 6'd32, 6'd16, 6'd00};
|
||||
|
||||
|
||||
function automatic logic [63:0] sbox4_layer(logic [63:0] in);
|
||||
logic [63:0] out;
|
||||
//for (logic [4:0] j = '0; j<16; j++) out[j*4 +: 4] = sbox4[in[j*4 +: 4]];
|
||||
// this simulates much faster than the loop
|
||||
out[0*4 +: 4] = sbox4[in[0*4 +: 4]];
|
||||
out[1*4 +: 4] = sbox4[in[1*4 +: 4]];
|
||||
out[2*4 +: 4] = sbox4[in[2*4 +: 4]];
|
||||
out[3*4 +: 4] = sbox4[in[3*4 +: 4]];
|
||||
|
||||
out[4*4 +: 4] = sbox4[in[4*4 +: 4]];
|
||||
out[5*4 +: 4] = sbox4[in[5*4 +: 4]];
|
||||
out[6*4 +: 4] = sbox4[in[6*4 +: 4]];
|
||||
out[7*4 +: 4] = sbox4[in[7*4 +: 4]];
|
||||
|
||||
out[8*4 +: 4] = sbox4[in[8*4 +: 4]];
|
||||
out[9*4 +: 4] = sbox4[in[9*4 +: 4]];
|
||||
out[10*4 +: 4] = sbox4[in[10*4 +: 4]];
|
||||
out[11*4 +: 4] = sbox4[in[11*4 +: 4]];
|
||||
|
||||
out[12*4 +: 4] = sbox4[in[12*4 +: 4]];
|
||||
out[13*4 +: 4] = sbox4[in[13*4 +: 4]];
|
||||
out[14*4 +: 4] = sbox4[in[14*4 +: 4]];
|
||||
out[15*4 +: 4] = sbox4[in[15*4 +: 4]];
|
||||
return out;
|
||||
endfunction : sbox4_layer
|
||||
|
||||
function automatic logic [63:0] perm_layer(logic [63:0] in);
|
||||
logic [63:0] out;
|
||||
// for (logic [7:0] j = '0; j<64; j++) out[perm[j]] = in[j];
|
||||
// this simulates much faster than the loop
|
||||
out[perm[0]] = in[0];
|
||||
out[perm[1]] = in[1];
|
||||
out[perm[2]] = in[2];
|
||||
out[perm[3]] = in[3];
|
||||
out[perm[4]] = in[4];
|
||||
out[perm[5]] = in[5];
|
||||
out[perm[6]] = in[6];
|
||||
out[perm[7]] = in[7];
|
||||
out[perm[8]] = in[8];
|
||||
out[perm[9]] = in[9];
|
||||
|
||||
out[perm[10]] = in[10];
|
||||
out[perm[11]] = in[11];
|
||||
out[perm[12]] = in[12];
|
||||
out[perm[13]] = in[13];
|
||||
out[perm[14]] = in[14];
|
||||
out[perm[15]] = in[15];
|
||||
out[perm[16]] = in[16];
|
||||
out[perm[17]] = in[17];
|
||||
out[perm[18]] = in[18];
|
||||
out[perm[19]] = in[19];
|
||||
|
||||
out[perm[20]] = in[20];
|
||||
out[perm[21]] = in[21];
|
||||
out[perm[22]] = in[22];
|
||||
out[perm[23]] = in[23];
|
||||
out[perm[24]] = in[24];
|
||||
out[perm[25]] = in[25];
|
||||
out[perm[26]] = in[26];
|
||||
out[perm[27]] = in[27];
|
||||
out[perm[28]] = in[28];
|
||||
out[perm[29]] = in[29];
|
||||
|
||||
out[perm[30]] = in[30];
|
||||
out[perm[31]] = in[31];
|
||||
out[perm[32]] = in[32];
|
||||
out[perm[33]] = in[33];
|
||||
out[perm[34]] = in[34];
|
||||
out[perm[35]] = in[35];
|
||||
out[perm[36]] = in[36];
|
||||
out[perm[37]] = in[37];
|
||||
out[perm[38]] = in[38];
|
||||
out[perm[39]] = in[39];
|
||||
|
||||
out[perm[40]] = in[40];
|
||||
out[perm[41]] = in[41];
|
||||
out[perm[42]] = in[42];
|
||||
out[perm[43]] = in[43];
|
||||
out[perm[44]] = in[44];
|
||||
out[perm[45]] = in[45];
|
||||
out[perm[46]] = in[46];
|
||||
out[perm[47]] = in[47];
|
||||
out[perm[48]] = in[48];
|
||||
out[perm[49]] = in[49];
|
||||
|
||||
out[perm[50]] = in[50];
|
||||
out[perm[51]] = in[51];
|
||||
out[perm[52]] = in[52];
|
||||
out[perm[53]] = in[53];
|
||||
out[perm[54]] = in[54];
|
||||
out[perm[55]] = in[55];
|
||||
out[perm[56]] = in[56];
|
||||
out[perm[57]] = in[57];
|
||||
out[perm[58]] = in[58];
|
||||
out[perm[59]] = in[59];
|
||||
|
||||
out[perm[60]] = in[60];
|
||||
out[perm[61]] = in[61];
|
||||
out[perm[62]] = in[62];
|
||||
out[perm[63]] = in[63];
|
||||
return out;
|
||||
endfunction : perm_layer
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// lfsr
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
logic [LfsrWidth-1:0] lfsr_d, lfsr_q;
|
||||
assign lfsr_d = (en_i) ? (lfsr_q>>1) ^ ({LfsrWidth{lfsr_q[0]}} & masks[LfsrWidth][LfsrWidth-1:0]) : lfsr_q;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
|
||||
//$display("%b %h", en_i, lfsr_d);
|
||||
if (!rst_ni) begin
|
||||
lfsr_q <= LfsrWidth'(RstVal);
|
||||
end else begin
|
||||
lfsr_q <= lfsr_d;
|
||||
end
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// block cipher layers
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (CipherLayers > unsigned'(0)) begin : g_cipher_layers
|
||||
logic [63:0] ciph_layer;
|
||||
localparam int unsigned NumRepl = ((64+LfsrWidth)/LfsrWidth);
|
||||
|
||||
always_comb begin : p_ciph_layer
|
||||
automatic logic [63:0] tmp;
|
||||
tmp = 64'({NumRepl{lfsr_q}});
|
||||
for(int unsigned k = 0; k < CipherLayers; k++) begin
|
||||
tmp = perm_layer(sbox4_layer(tmp));
|
||||
end
|
||||
ciph_layer = tmp;
|
||||
end
|
||||
|
||||
// additiona output reg after cipher
|
||||
if (CipherReg) begin : g_cipher_reg
|
||||
logic [OutWidth-1:0] out_d, out_q;
|
||||
|
||||
assign out_d = (en_i) ? ciph_layer[OutWidth-1:0] : out_q;
|
||||
assign out_o = out_q[OutWidth-1:0];
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
|
||||
if (!rst_ni) begin
|
||||
out_q <= '0;
|
||||
end else begin
|
||||
out_q <= out_d;
|
||||
end
|
||||
end
|
||||
// no outreg
|
||||
end else begin : g_no_out_reg
|
||||
assign out_o = ciph_layer[OutWidth-1:0];
|
||||
end
|
||||
|
||||
// no block cipher
|
||||
end else begin : g_no_cipher_layers
|
||||
assign out_o = lfsr_q[OutWidth-1:0];
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// assertions
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// pragma translate_off
|
||||
initial begin
|
||||
// these are the LUT limits
|
||||
assert(OutWidth <= LfsrWidth) else
|
||||
$fatal(1,"OutWidth must be smaller equal the LfsrWidth.");
|
||||
assert(RstVal > unsigned'(0)) else
|
||||
$fatal(1,"RstVal must be nonzero.");
|
||||
assert((LfsrWidth >= $low(masks)) && (LfsrWidth <= $high(masks))) else
|
||||
$fatal(1,"Unsupported LfsrWidth.");
|
||||
assert(masks[LfsrWidth][LfsrWidth-1]) else
|
||||
$fatal(1, "LFSR mask is not correct. The MSB must be 1." );
|
||||
assert((CipherLayers > 0) && (LfsrWidth == 64) || (CipherLayers == 0)) else
|
||||
$fatal(1, "Use additional cipher layers only in conjunction with an LFSR width of 64 bit." );
|
||||
end
|
||||
|
||||
`ifndef VERILATOR
|
||||
all_zero: assert property (
|
||||
@(posedge clk_i) disable iff (!rst_ni) en_i |-> lfsr_d)
|
||||
else $fatal(1,"Lfsr must not be all-zero.");
|
||||
`endif
|
||||
// pragma translate_on
|
||||
|
||||
endmodule // lfsr
|
|
@ -1,67 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Author: Florian Zaruba, ETH Zurich
|
||||
// Date: 5.11.2018
|
||||
// Description: 16-bit LFSR
|
||||
|
||||
// --------------
|
||||
// 16-bit LFSR
|
||||
// --------------
|
||||
//
|
||||
// Description: Shift register
|
||||
//
|
||||
module lfsr_16bit #(
|
||||
parameter logic [15:0] SEED = 8'b0,
|
||||
parameter int unsigned WIDTH = 16
|
||||
)(
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic en_i,
|
||||
output logic [WIDTH-1:0] refill_way_oh,
|
||||
output logic [$clog2(WIDTH)-1:0] refill_way_bin
|
||||
);
|
||||
|
||||
localparam int unsigned LOG_WIDTH = $clog2(WIDTH);
|
||||
|
||||
logic [15:0] shift_d, shift_q;
|
||||
|
||||
|
||||
always_comb begin
|
||||
|
||||
automatic logic shift_in;
|
||||
shift_in = !(shift_q[15] ^ shift_q[12] ^ shift_q[5] ^ shift_q[1]);
|
||||
|
||||
shift_d = shift_q;
|
||||
|
||||
if (en_i)
|
||||
shift_d = {shift_q[14:0], shift_in};
|
||||
|
||||
// output assignment
|
||||
refill_way_oh = 'b0;
|
||||
refill_way_oh[shift_q[LOG_WIDTH-1:0]] = 1'b1;
|
||||
refill_way_bin = shift_q;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_
|
||||
if(~rst_ni) begin
|
||||
shift_q <= SEED;
|
||||
end else begin
|
||||
shift_q <= shift_d;
|
||||
end
|
||||
end
|
||||
|
||||
//pragma translate_off
|
||||
initial begin
|
||||
assert (WIDTH <= 16) else $fatal(1, "WIDTH needs to be less than 16 because of the 16-bit LFSR");
|
||||
end
|
||||
//pragma translate_on
|
||||
|
||||
endmodule
|
|
@ -1,68 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Author: Igor Loi - University of Bologna
|
||||
// Author: Florian Zaruba, ETH Zurich
|
||||
// Date: 12.11.2017
|
||||
// Description: 8-bit LFSR
|
||||
|
||||
// --------------
|
||||
// 8-bit LFSR
|
||||
// --------------
|
||||
//
|
||||
// Description: Shift register
|
||||
//
|
||||
module lfsr_8bit #(
|
||||
parameter logic [7:0] SEED = 8'b0,
|
||||
parameter int unsigned WIDTH = 8
|
||||
)(
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic en_i,
|
||||
output logic [WIDTH-1:0] refill_way_oh,
|
||||
output logic [$clog2(WIDTH)-1:0] refill_way_bin
|
||||
);
|
||||
|
||||
localparam int unsigned LOG_WIDTH = $clog2(WIDTH);
|
||||
|
||||
logic [7:0] shift_d, shift_q;
|
||||
|
||||
|
||||
always_comb begin
|
||||
|
||||
automatic logic shift_in;
|
||||
shift_in = !(shift_q[7] ^ shift_q[3] ^ shift_q[2] ^ shift_q[1]);
|
||||
|
||||
shift_d = shift_q;
|
||||
|
||||
if (en_i)
|
||||
shift_d = {shift_q[6:0], shift_in};
|
||||
|
||||
// output assignment
|
||||
refill_way_oh = 'b0;
|
||||
refill_way_oh[shift_q[LOG_WIDTH-1:0]] = 1'b1;
|
||||
refill_way_bin = shift_q;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_
|
||||
if(~rst_ni) begin
|
||||
shift_q <= SEED;
|
||||
end else begin
|
||||
shift_q <= shift_d;
|
||||
end
|
||||
end
|
||||
|
||||
//pragma translate_off
|
||||
initial begin
|
||||
assert (WIDTH <= 8) else $fatal(1, "WIDTH needs to be less than 8 because of the 8-bit LFSR");
|
||||
end
|
||||
//pragma translate_on
|
||||
|
||||
endmodule
|
|
@ -1,93 +0,0 @@
|
|||
// Copyright (c) 2018 - 2019 ETH Zurich, University of Bologna
|
||||
// All rights reserved.
|
||||
//
|
||||
// This code is under development and not yet released to the public.
|
||||
// Until it is released, the code is under the copyright of ETH Zurich and
|
||||
// the University of Bologna, and may contain confidential and/or unpublished
|
||||
// work. Any reuse/redistribution is strictly forbidden without written
|
||||
// permission from ETH Zurich.
|
||||
//
|
||||
// Bug fixes and contributions will eventually be released under the
|
||||
// SolderPad open hardware license in the context of the PULP platform
|
||||
// (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
|
||||
// University of Bologna.
|
||||
|
||||
/// A trailing zero counter / leading zero counter.
|
||||
/// Set MODE to 0 for trailing zero counter => cnt_o is the number of trailing zeros (from the LSB)
|
||||
/// Set MODE to 1 for leading zero counter => cnt_o is the number of leading zeros (from the MSB)
|
||||
/// If the input does not contain a zero, `empty_o` is asserted. Additionally `cnt_o` contains
|
||||
/// the maximum number of zeros - 1. For example:
|
||||
/// in_i = 000_0000, empty_o = 1, cnt_o = 6 (mode = 0)
|
||||
/// in_i = 000_0001, empty_o = 0, cnt_o = 0 (mode = 0)
|
||||
/// in_i = 000_1000, empty_o = 0, cnt_o = 3 (mode = 0)
|
||||
/// Furthermore, this unit contains a more efficient implementation for Verilator (simulation only).
|
||||
/// This speeds up simulation significantly.
|
||||
|
||||
module lzc #(
|
||||
/// The width of the input vector.
|
||||
parameter int unsigned WIDTH = 2,
|
||||
parameter bit MODE = 1'b0 // 0 -> trailing zero, 1 -> leading zero
|
||||
) (
|
||||
input logic [WIDTH-1:0] in_i,
|
||||
output logic [$clog2(WIDTH)-1:0] cnt_o,
|
||||
output logic empty_o // asserted if all bits in in_i are zero
|
||||
);
|
||||
|
||||
localparam int unsigned NUM_LEVELS = $clog2(WIDTH);
|
||||
|
||||
// pragma translate_off
|
||||
initial begin
|
||||
assert(WIDTH > 0) else $fatal("input must be at least one bit wide");
|
||||
end
|
||||
// pragma translate_on
|
||||
|
||||
logic [WIDTH-1:0][NUM_LEVELS-1:0] index_lut;
|
||||
logic [2**NUM_LEVELS-1:0] sel_nodes;
|
||||
logic [2**NUM_LEVELS-1:0][NUM_LEVELS-1:0] index_nodes;
|
||||
|
||||
logic [WIDTH-1:0] in_tmp;
|
||||
|
||||
// reverse vector if required
|
||||
always_comb begin : flip_vector
|
||||
for (int unsigned i = 0; i < WIDTH; i++) begin
|
||||
in_tmp[i] = (MODE) ? in_i[WIDTH-1-i] : in_i[i];
|
||||
end
|
||||
end
|
||||
|
||||
for (genvar j = 0; unsigned'(j) < WIDTH; j++) begin : g_index_lut
|
||||
assign index_lut[j] = NUM_LEVELS'(unsigned'(j));
|
||||
end
|
||||
|
||||
for (genvar level = 0; unsigned'(level) < NUM_LEVELS; level++) begin : g_levels
|
||||
if (unsigned'(level) == NUM_LEVELS-1) begin : g_last_level
|
||||
for (genvar k = 0; k < 2**level; k++) begin : g_level
|
||||
// if two successive indices are still in the vector...
|
||||
if (unsigned'(k) * 2 < WIDTH-1) begin
|
||||
assign sel_nodes[2**level-1+k] = in_tmp[k*2] | in_tmp[k*2+1];
|
||||
assign index_nodes[2**level-1+k] = (in_tmp[k*2] == 1'b1) ? index_lut[k*2] :
|
||||
index_lut[k*2+1];
|
||||
end
|
||||
// if only the first index is still in the vector...
|
||||
if (unsigned'(k) * 2 == WIDTH-1) begin
|
||||
assign sel_nodes[2**level-1+k] = in_tmp[k*2];
|
||||
assign index_nodes[2**level-1+k] = index_lut[k*2];
|
||||
end
|
||||
// if index is out of range
|
||||
if (unsigned'(k) * 2 > WIDTH-1) begin
|
||||
assign sel_nodes[2**level-1+k] = 1'b0;
|
||||
assign index_nodes[2**level-1+k] = '0;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
for (genvar l = 0; l < 2**level; l++) begin : g_level
|
||||
assign sel_nodes[2**level-1+l] = sel_nodes[2**(level+1)-1+l*2] | sel_nodes[2**(level+1)-1+l*2+1];
|
||||
assign index_nodes[2**level-1+l] = (sel_nodes[2**(level+1)-1+l*2] == 1'b1) ? index_nodes[2**(level+1)-1+l*2] :
|
||||
index_nodes[2**(level+1)-1+l*2+1];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign cnt_o = NUM_LEVELS > unsigned'(0) ? index_nodes[0] : $clog2(WIDTH)'(0);
|
||||
assign empty_o = NUM_LEVELS > unsigned'(0) ? ~sel_nodes[0] : ~(|in_i);
|
||||
|
||||
endmodule : lzc
|
|
@ -1,55 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
|
||||
|
||||
module mv_filter #(
|
||||
parameter int unsigned WIDTH = 4,
|
||||
parameter int unsigned THRESHOLD = 10
|
||||
)(
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic sample_i,
|
||||
input logic clear_i,
|
||||
input logic d_i,
|
||||
output logic q_o
|
||||
);
|
||||
logic [WIDTH-1:0] counter_q, counter_d;
|
||||
logic d, q;
|
||||
|
||||
assign q_o = q;
|
||||
|
||||
always_comb begin
|
||||
counter_d = counter_q;
|
||||
d = q;
|
||||
|
||||
if (counter_q >= THRESHOLD[WIDTH-1:0]) begin
|
||||
d = 1'b1;
|
||||
end else if (sample_i && d_i) begin
|
||||
counter_d = counter_q + 1;
|
||||
end
|
||||
|
||||
// sync reset
|
||||
if (clear_i) begin
|
||||
counter_d = '0;
|
||||
d = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (~rst_ni) begin
|
||||
counter_q <= '0;
|
||||
q <= 1'b0;
|
||||
end else begin
|
||||
counter_q <= counter_d;
|
||||
q <= d;
|
||||
end
|
||||
end
|
||||
endmodule
|
|
@ -1,39 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Franceco Conti <fconti@iis.ee.ethz.ch>
|
||||
|
||||
module onehot_to_bin #(
|
||||
parameter int unsigned ONEHOT_WIDTH = 16,
|
||||
// Do Not Change
|
||||
parameter int unsigned BIN_WIDTH = $clog2(ONEHOT_WIDTH)
|
||||
)(
|
||||
input logic [ONEHOT_WIDTH-1:0] onehot,
|
||||
output logic [BIN_WIDTH-1:0] bin
|
||||
);
|
||||
|
||||
for (genvar j = 0; j < BIN_WIDTH; j++) begin : jl
|
||||
logic [ONEHOT_WIDTH-1:0] tmp_mask;
|
||||
for (genvar i = 0; i < ONEHOT_WIDTH; i++) begin : il
|
||||
logic [BIN_WIDTH-1:0] tmp_i;
|
||||
assign tmp_i = i;
|
||||
assign tmp_mask[i] = tmp_i[j];
|
||||
end
|
||||
assign bin[j] = |(tmp_mask & onehot);
|
||||
end
|
||||
|
||||
// pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
initial begin
|
||||
assert($onehot0(onehot)) else $fatal(1, "[onehot_to_bin] More than two bit set in the one-hot signal");
|
||||
end
|
||||
`endif
|
||||
// pragma translate_on
|
||||
endmodule
|
|
@ -1,120 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
//
|
||||
// Author: David Schaffenrath, TU Graz
|
||||
// Author: Florian Zaruba, ETH Zurich
|
||||
//
|
||||
// Description: Pseudo Least Recently Used Tree (PLRU)
|
||||
// See: https://en.wikipedia.org/wiki/Pseudo-LRU
|
||||
|
||||
module plru_tree #(
|
||||
parameter int unsigned ENTRIES = 16
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic [ENTRIES-1:0] used_i, // element i was used (one hot)
|
||||
output logic [ENTRIES-1:0] plru_o // element i is the least recently used (one hot)
|
||||
);
|
||||
|
||||
localparam LOG_ENTRIES = $clog2(ENTRIES);
|
||||
|
||||
logic [2*(ENTRIES-1)-1:0] plru_tree_q, plru_tree_d;
|
||||
|
||||
always_comb begin : plru_replacement
|
||||
plru_tree_d = plru_tree_q;
|
||||
// The PLRU-tree indexing:
|
||||
// lvl0 0
|
||||
// / \
|
||||
// / \
|
||||
// lvl1 1 2
|
||||
// / \ / \
|
||||
// lvl2 3 4 5 6
|
||||
// / \ /\/\ /\
|
||||
// ... ... ... ...
|
||||
// Just predefine which nodes will be set/cleared
|
||||
// E.g. for a TLB with 8 entries, the for-loop is semantically
|
||||
// equivalent to the following pseudo-code:
|
||||
// unique case (1'b1)
|
||||
// used_i[7]: plru_tree_d[0, 2, 6] = {1, 1, 1};
|
||||
// used_i[6]: plru_tree_d[0, 2, 6] = {1, 1, 0};
|
||||
// used_i[5]: plru_tree_d[0, 2, 5] = {1, 0, 1};
|
||||
// used_i[4]: plru_tree_d[0, 2, 5] = {1, 0, 0};
|
||||
// used_i[3]: plru_tree_d[0, 1, 4] = {0, 1, 1};
|
||||
// used_i[2]: plru_tree_d[0, 1, 4] = {0, 1, 0};
|
||||
// used_i[1]: plru_tree_d[0, 1, 3] = {0, 0, 1};
|
||||
// used_i[0]: plru_tree_d[0, 1, 3] = {0, 0, 0};
|
||||
// default: begin /* No hit */ end
|
||||
// endcase
|
||||
for (int unsigned i = 0; i < ENTRIES; i++) begin
|
||||
automatic int unsigned idx_base, shift, new_index;
|
||||
// we got a hit so update the pointer as it was least recently used
|
||||
if (used_i[i]) begin
|
||||
// Set the nodes to the values we would expect
|
||||
for (int unsigned lvl = 0; lvl < LOG_ENTRIES; lvl++) begin
|
||||
idx_base = $unsigned((2**lvl)-1);
|
||||
// lvl0 <=> MSB, lvl1 <=> MSB-1, ...
|
||||
shift = LOG_ENTRIES - lvl;
|
||||
// to circumvent the 32 bit integer arithmetic assignment
|
||||
new_index = ~((i >> (shift-1)) & 32'b1);
|
||||
plru_tree_d[idx_base + (i >> shift)] = new_index[0];
|
||||
end
|
||||
end
|
||||
end
|
||||
// Decode tree to write enable signals
|
||||
// Next for-loop basically creates the following logic for e.g. an 8 entry
|
||||
// TLB (note: pseudo-code obviously):
|
||||
// plru_o[7] = &plru_tree_q[ 6, 2, 0]; //plru_tree_q[0,2,6]=={1,1,1}
|
||||
// plru_o[6] = &plru_tree_q[~6, 2, 0]; //plru_tree_q[0,2,6]=={1,1,0}
|
||||
// plru_o[5] = &plru_tree_q[ 5,~2, 0]; //plru_tree_q[0,2,5]=={1,0,1}
|
||||
// plru_o[4] = &plru_tree_q[~5,~2, 0]; //plru_tree_q[0,2,5]=={1,0,0}
|
||||
// plru_o[3] = &plru_tree_q[ 4, 1,~0]; //plru_tree_q[0,1,4]=={0,1,1}
|
||||
// plru_o[2] = &plru_tree_q[~4, 1,~0]; //plru_tree_q[0,1,4]=={0,1,0}
|
||||
// plru_o[1] = &plru_tree_q[ 3,~1,~0]; //plru_tree_q[0,1,3]=={0,0,1}
|
||||
// plru_o[0] = &plru_tree_q[~3,~1,~0]; //plru_tree_q[0,1,3]=={0,0,0}
|
||||
// For each entry traverse the tree. If every tree-node matches,
|
||||
// the corresponding bit of the entry's index, this is
|
||||
// the next entry to replace.
|
||||
for (int unsigned i = 0; i < ENTRIES; i += 1) begin
|
||||
automatic logic en;
|
||||
automatic int unsigned idx_base, shift, new_index;
|
||||
en = 1'b1;
|
||||
for (int unsigned lvl = 0; lvl < LOG_ENTRIES; lvl++) begin
|
||||
idx_base = $unsigned((2**lvl)-1);
|
||||
// lvl0 <=> MSB, lvl1 <=> MSB-1, ...
|
||||
shift = LOG_ENTRIES - lvl;
|
||||
// en &= plru_tree_q[idx_base + (i>>shift)] == ((i >> (shift-1)) & 1'b1);
|
||||
new_index = (i >> (shift-1)) & 32'b1;
|
||||
if (new_index[0]) begin
|
||||
en &= plru_tree_q[idx_base + (i>>shift)];
|
||||
end else begin
|
||||
en &= ~plru_tree_q[idx_base + (i>>shift)];
|
||||
end
|
||||
end
|
||||
plru_o[i] = en;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
plru_tree_q <= '0;
|
||||
end else begin
|
||||
plru_tree_q <= plru_tree_d;
|
||||
end
|
||||
end
|
||||
|
||||
// pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
initial begin
|
||||
assert (ENTRIES == 2**LOG_ENTRIES) else $error("Entries must be a power of two");
|
||||
end
|
||||
`endif
|
||||
// pragma translate_on
|
||||
|
||||
endmodule
|
|
@ -1,57 +0,0 @@
|
|||
// Copyright (C) 2013-2018 ETH Zurich, University of Bologna
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Author: Manuel Eggimann <meggimann@iis.ee.ethz.ch>
|
||||
|
||||
// Description: This module calculates the hamming weight (number of ones) in
|
||||
// its input vector using a balanced binary adder tree. Recursive instantiation
|
||||
// is used to build the tree. Any unsigned INPUT_WIDTH larger or equal 2 is
|
||||
// legal. The module pads the signal internally to the next power of two. The
|
||||
// output result width is ceil(log2(INPUT_WIDTH))+1.
|
||||
|
||||
module popcount #(
|
||||
parameter int unsigned INPUT_WIDTH = 256,
|
||||
localparam POPCOUNT_WIDTH = $clog2(INPUT_WIDTH)+1
|
||||
) (
|
||||
input logic [INPUT_WIDTH-1:0] data_i,
|
||||
output logic [POPCOUNT_WIDTH-1:0] popcount_o
|
||||
);
|
||||
|
||||
localparam int unsigned PADDED_WIDTH = 1 << $clog2(INPUT_WIDTH);
|
||||
|
||||
logic [PADDED_WIDTH-1:0] padded_input;
|
||||
logic [POPCOUNT_WIDTH-2:0] left_child_result, right_child_result;
|
||||
|
||||
//Zero pad the input to next power of two
|
||||
always_comb begin
|
||||
padded_input = '0;
|
||||
padded_input[INPUT_WIDTH-1:0] = data_i;
|
||||
end
|
||||
|
||||
//Recursive instantiation to build binary adder tree
|
||||
if (INPUT_WIDTH == 2) begin : leaf_node
|
||||
assign left_child_result = padded_input[1];
|
||||
assign right_child_result = padded_input[0];
|
||||
end else begin : non_leaf_node
|
||||
popcount #(.INPUT_WIDTH(PADDED_WIDTH / 2))
|
||||
left_child(
|
||||
.data_i(padded_input[PADDED_WIDTH-1:PADDED_WIDTH/2]),
|
||||
.popcount_o(left_child_result));
|
||||
|
||||
popcount #(.INPUT_WIDTH(PADDED_WIDTH / 2))
|
||||
right_child(
|
||||
.data_i(padded_input[PADDED_WIDTH/2-1:0]),
|
||||
.popcount_o(right_child_result));
|
||||
end
|
||||
|
||||
//Output assignment
|
||||
assign popcount_o = left_child_result + right_child_result;
|
||||
|
||||
endmodule : popcount
|
|
@ -1,244 +0,0 @@
|
|||
// Copyright 2019 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
//
|
||||
// Author: Michael Schaffner <schaffner@iis.ee.ethz.ch>, ETH Zurich
|
||||
// Date: 02.04.2019
|
||||
// Description: logarithmic arbitration tree with round robin arbitration scheme.
|
||||
//
|
||||
// The rr_arb_tree employs fair round robin arbitration - i.e. the priorities
|
||||
// rotate each cycle.
|
||||
//
|
||||
// The `LockIn` option prevents the arbiter from changing the arbitration
|
||||
// decision when the arbiter is disabled. I.e., the index of the first request
|
||||
// that wins the arbitration will be locked in case the destination is not
|
||||
// able to grant the request in the same cycle.
|
||||
//
|
||||
// The `ExtPrio` option allows to override the internal round robin counter via the
|
||||
// `rr_i` signal. This can be useful in case multiple arbiters need to have
|
||||
// rotating priorities that are operating in lock-step. If static priority arbitration
|
||||
// is needed, just connect `rr_i` to '0.
|
||||
//
|
||||
// If `AxiVldRdy` is set, the req/gnt signals are compliant with the AXI style vld/rdy
|
||||
// handshake. Namely, upstream vld (req) must not depend on rdy (gnt), as it can be deasserted
|
||||
// again even though vld is asserted. Enabling `AxiVldRdy` leads to a reduction of arbiter
|
||||
// delay and area.
|
||||
//
|
||||
|
||||
module rr_arb_tree #(
|
||||
parameter int unsigned NumIn = 64,
|
||||
parameter int unsigned DataWidth = 32,
|
||||
parameter type DataType = logic [DataWidth-1:0],
|
||||
parameter bit ExtPrio = 1'b0, // set to 1'b1 to enable
|
||||
parameter bit AxiVldRdy = 1'b0, // treat req/gnt as vld/rdy
|
||||
parameter bit LockIn = 1'b0 // set to 1'b1 to enable
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic flush_i, // clears the arbiter state
|
||||
input logic [$clog2(NumIn)-1:0] rr_i, // external RR prio (needs to be enabled above)
|
||||
// input requests and data
|
||||
input logic [NumIn-1:0] req_i,
|
||||
/* verilator lint_off UNOPTFLAT */
|
||||
output logic [NumIn-1:0] gnt_o,
|
||||
/* verilator lint_on UNOPTFLAT */
|
||||
input DataType [NumIn-1:0] data_i,
|
||||
// arbitrated output
|
||||
input logic gnt_i,
|
||||
output logic req_o,
|
||||
output DataType data_o,
|
||||
output logic [$clog2(NumIn)-1:0] idx_o
|
||||
);
|
||||
// just pass through in this corner case
|
||||
if (NumIn == unsigned'(1)) begin
|
||||
assign req_o = req_i[0];
|
||||
assign gnt_o[0] = gnt_i;
|
||||
assign data_o = data_i[0];
|
||||
assign idx_o = '0;
|
||||
// non-degenerate cases
|
||||
end else begin
|
||||
localparam int unsigned NumLevels = $clog2(NumIn);
|
||||
|
||||
/* verilator lint_off UNOPTFLAT */
|
||||
logic [2**NumLevels-2:0][NumLevels-1:0] index_nodes; // used to propagate the indices
|
||||
DataType [2**NumLevels-2:0] data_nodes; // used to propagate the data
|
||||
logic [2**NumLevels-2:0] gnt_nodes; // used to propagate the grant to masters
|
||||
logic [2**NumLevels-2:0] req_nodes; // used to propagate the requests to slave
|
||||
/* lint_off */
|
||||
logic [NumLevels-1:0] rr_q;
|
||||
logic [NumIn-1:0] req_d;
|
||||
|
||||
// the final arbitration decision can be taken from the root of the tree
|
||||
assign req_o = req_nodes[0];
|
||||
assign data_o = data_nodes[0];
|
||||
assign idx_o = index_nodes[0];
|
||||
|
||||
if (ExtPrio) begin : gen_ext_rr
|
||||
assign rr_q = rr_i;
|
||||
assign req_d = req_i;
|
||||
end else begin : gen_int_rr
|
||||
logic [NumLevels-1:0] rr_d;
|
||||
|
||||
// lock arbiter decision in case we got at least one req and no acknowledge
|
||||
if (LockIn) begin : gen_lock
|
||||
logic lock_d, lock_q;
|
||||
logic [NumIn-1:0] req_q;
|
||||
|
||||
assign lock_d = req_o & ~gnt_i;
|
||||
assign req_d = (lock_q) ? req_q : req_i;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : p_lock_reg
|
||||
if (!rst_ni) begin
|
||||
lock_q <= '0;
|
||||
end else begin
|
||||
if (flush_i) begin
|
||||
lock_q <= '0;
|
||||
end else begin
|
||||
lock_q <= lock_d;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
lock: assert property(
|
||||
@(posedge clk_i) disable iff (!rst_ni) LockIn |-> req_o && !gnt_i |=> idx_o == $past(idx_o))
|
||||
else $fatal (1, "Lock implies same arbiter decision in next cycle if output is not ready.");
|
||||
|
||||
logic [NumIn-1:0] req_tmp;
|
||||
assign req_tmp = req_q & req_i;
|
||||
lock_req: assert property(
|
||||
@(posedge clk_i) disable iff (!rst_ni) LockIn |-> lock_d |=> req_tmp == req_q)
|
||||
else $fatal (1, "It is disallowed to deassert unserved request signals when LockIn is enabled.");
|
||||
`endif
|
||||
// pragma translate_on
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : p_req_regs
|
||||
if (!rst_ni) begin
|
||||
req_q <= '0;
|
||||
end else begin
|
||||
if (flush_i) begin
|
||||
req_q <= '0;
|
||||
end else begin
|
||||
req_q <= req_d;
|
||||
end
|
||||
end
|
||||
end
|
||||
end else begin : gen_no_lock
|
||||
assign req_d = req_i;
|
||||
end
|
||||
|
||||
assign rr_d = (gnt_i && req_o) ? ((rr_q == NumLevels'(NumIn-1)) ? '0 : rr_q + 1'b1) : rr_q;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : p_rr_regs
|
||||
if (!rst_ni) begin
|
||||
rr_q <= '0;
|
||||
end else begin
|
||||
if (flush_i) begin
|
||||
rr_q <= '0;
|
||||
end else begin
|
||||
rr_q <= rr_d;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign gnt_nodes[0] = gnt_i;
|
||||
|
||||
// arbiter tree
|
||||
for (genvar level = 0; unsigned'(level) < NumLevels; level++) begin : gen_levels
|
||||
for (genvar l = 0; l < 2**level; l++) begin : gen_level
|
||||
// local select signal
|
||||
logic sel;
|
||||
// index calcs
|
||||
localparam int unsigned idx0 = 2**level-1+l;// current node
|
||||
localparam int unsigned idx1 = 2**(level+1)-1+l*2;
|
||||
//////////////////////////////////////////////////////////////
|
||||
// uppermost level where data is fed in from the inputs
|
||||
if (unsigned'(level) == NumLevels-1) begin : gen_first_level
|
||||
// if two successive indices are still in the vector...
|
||||
if (unsigned'(l) * 2 < NumIn-1) begin
|
||||
assign req_nodes[idx0] = req_d[l*2] | req_d[l*2+1];
|
||||
|
||||
// arbitration: round robin
|
||||
assign sel = ~req_d[l*2] | req_d[l*2+1] & rr_q[NumLevels-1-level];
|
||||
|
||||
assign index_nodes[idx0] = NumLevels'(sel);
|
||||
assign data_nodes[idx0] = (sel) ? data_i[l*2+1] : data_i[l*2];
|
||||
assign gnt_o[l*2] = gnt_nodes[idx0] & (AxiVldRdy | req_d[l*2]) & ~sel;
|
||||
assign gnt_o[l*2+1] = gnt_nodes[idx0] & (AxiVldRdy | req_d[l*2+1]) & sel;
|
||||
end
|
||||
// if only the first index is still in the vector...
|
||||
if (unsigned'(l) * 2 == NumIn-1) begin
|
||||
assign req_nodes[idx0] = req_d[l*2];
|
||||
assign index_nodes[idx0] = '0;// always zero in this case
|
||||
assign data_nodes[idx0] = data_i[l*2];
|
||||
assign gnt_o[l*2] = gnt_nodes[idx0] & (AxiVldRdy | req_d[l*2]);
|
||||
end
|
||||
// if index is out of range, fill up with zeros (will get pruned)
|
||||
if (unsigned'(l) * 2 > NumIn-1) begin
|
||||
assign req_nodes[idx0] = 1'b0;
|
||||
assign index_nodes[idx0] = DataType'('0);
|
||||
assign data_nodes[idx0] = DataType'('0);
|
||||
end
|
||||
//////////////////////////////////////////////////////////////
|
||||
// general case for other levels within the tree
|
||||
end else begin : gen_other_levels
|
||||
assign req_nodes[idx0] = req_nodes[idx1] | req_nodes[idx1+1];
|
||||
|
||||
// arbitration: round robin
|
||||
assign sel = ~req_nodes[idx1] | req_nodes[idx1+1] & rr_q[NumLevels-1-level];
|
||||
|
||||
assign index_nodes[idx0] = (sel) ? NumLevels'({1'b1, index_nodes[idx1+1][NumLevels-unsigned'(level)-2:0]}) :
|
||||
NumLevels'({1'b0, index_nodes[idx1][NumLevels-unsigned'(level)-2:0]});
|
||||
assign data_nodes[idx0] = (sel) ? data_nodes[idx1+1] : data_nodes[idx1];
|
||||
assign gnt_nodes[idx1] = gnt_nodes[idx0] & ~sel;
|
||||
assign gnt_nodes[idx1+1] = gnt_nodes[idx0] & sel;
|
||||
end
|
||||
//////////////////////////////////////////////////////////////
|
||||
end
|
||||
end
|
||||
|
||||
// pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
initial begin : p_assert
|
||||
assert(NumIn)
|
||||
else $fatal("Input must be at least one element wide.");
|
||||
assert(!(LockIn && ExtPrio))
|
||||
else $fatal(1,"Cannot use LockIn feature together with external ExtPrio.");
|
||||
end
|
||||
|
||||
hot_one : assert property(
|
||||
@(posedge clk_i) disable iff (!rst_ni) $onehot0(gnt_o))
|
||||
else $fatal (1, "Grant signal must be hot1 or zero.");
|
||||
|
||||
gnt0 : assert property(
|
||||
@(posedge clk_i) disable iff (!rst_ni) |gnt_o |-> gnt_i)
|
||||
else $fatal (1, "Grant out implies grant in.");
|
||||
|
||||
gnt1 : assert property(
|
||||
@(posedge clk_i) disable iff (!rst_ni) req_o |-> gnt_i |-> |gnt_o)
|
||||
else $fatal (1, "Req out and grant in implies grant out.");
|
||||
|
||||
gnt_idx : assert property(
|
||||
@(posedge clk_i) disable iff (!rst_ni) req_o |-> gnt_i |-> gnt_o[idx_o])
|
||||
else $fatal (1, "Idx_o / gnt_o do not match.");
|
||||
|
||||
req0 : assert property(
|
||||
@(posedge clk_i) disable iff (!rst_ni) |req_i |-> req_o)
|
||||
else $fatal (1, "Req in implies req out.");
|
||||
|
||||
req1 : assert property(
|
||||
@(posedge clk_i) disable iff (!rst_ni) |req_o |-> req_i)
|
||||
else $fatal (1, "Req out implies req in.");
|
||||
`endif
|
||||
// pragma translate_on
|
||||
end
|
||||
|
||||
endmodule : rr_arb_tree
|
|
@ -1,30 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Davide Rossi <davide.rossi@unibo.it>
|
||||
|
||||
module rstgen (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic test_mode_i,
|
||||
output logic rst_no,
|
||||
output logic init_no
|
||||
);
|
||||
|
||||
rstgen_bypass i_rstgen_bypass (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.rst_test_mode_ni ( rst_ni ),
|
||||
.test_mode_i ( test_mode_i ),
|
||||
.rst_no ( rst_no ),
|
||||
.init_no ( init_no )
|
||||
);
|
||||
|
||||
endmodule
|
|
@ -1,54 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Florian Zaruba <zarubaf@iis.ee.ethz.ch>
|
||||
// Description: This module is a reset synchronizer with a dedicated reset bypass pin for testmode reset.
|
||||
// Pro Tip: The wise Dr. Schaffner recommends at least 4 registers!
|
||||
|
||||
module rstgen_bypass #(
|
||||
parameter NumRegs = 4
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic rst_test_mode_ni,
|
||||
input logic test_mode_i,
|
||||
output logic rst_no,
|
||||
output logic init_no
|
||||
);
|
||||
|
||||
// internal reset
|
||||
logic rst_n;
|
||||
|
||||
logic [NumRegs-1:0] synch_regs_q;
|
||||
// bypass mode
|
||||
always_comb begin
|
||||
if (test_mode_i == 1'b0) begin
|
||||
rst_n = rst_ni;
|
||||
rst_no = synch_regs_q[NumRegs-1];
|
||||
init_no = synch_regs_q[NumRegs-1];
|
||||
end else begin
|
||||
rst_n = rst_test_mode_ni;
|
||||
rst_no = rst_test_mode_ni;
|
||||
init_no = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk_i or negedge rst_n) begin
|
||||
if (~rst_n) begin
|
||||
synch_regs_q <= 0;
|
||||
end else begin
|
||||
synch_regs_q <= {synch_regs_q[NumRegs-2:0], 1'b1};
|
||||
end
|
||||
end
|
||||
|
||||
initial begin : p_assertions
|
||||
if (NumRegs < 1) $fatal(1, "At least one register is required.");
|
||||
end
|
||||
endmodule
|
|
@ -1,50 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Author: Florian Zaruba
|
||||
// Description: Deglitches a serial line by taking multiple samples until
|
||||
// asserting the output high/low.
|
||||
|
||||
module serial_deglitch #(
|
||||
parameter int unsigned SIZE = 4
|
||||
)(
|
||||
input logic clk_i, // clock
|
||||
input logic rst_ni, // asynchronous reset active low
|
||||
input logic en_i, // enable
|
||||
input logic d_i, // serial data in
|
||||
output logic q_o // filtered data out
|
||||
);
|
||||
logic [SIZE-1:0] count_q;
|
||||
logic q;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (~rst_ni) begin
|
||||
count_q <= '0;
|
||||
q <= 1'b0;
|
||||
end else begin
|
||||
if (en_i) begin
|
||||
if (d_i == 1'b1 && count_q != SIZE[SIZE-1:0]) begin
|
||||
count_q <= count_q + 1;
|
||||
end else if (d_i == 1'b0 && count_q != SIZE[SIZE-1:0]) begin
|
||||
count_q <= count_q - 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// output process
|
||||
always_comb begin
|
||||
if (count_q == SIZE[SIZE-1:0]) begin
|
||||
q_o = 1'b1;
|
||||
end else if (count_q == 0) begin
|
||||
q_o = 1'b0;
|
||||
end
|
||||
end
|
||||
endmodule
|
|
@ -1,53 +0,0 @@
|
|||
|
||||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
//
|
||||
// Author: <zarubaf@iis.ee.ethz.ch>
|
||||
//
|
||||
// Description: Simple shift register for arbitrary depth and types
|
||||
|
||||
module shift_reg #(
|
||||
parameter type dtype = logic,
|
||||
parameter int unsigned Depth = 1
|
||||
)(
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous reset active low
|
||||
input dtype d_i,
|
||||
output dtype d_o
|
||||
);
|
||||
|
||||
// register of depth 0 is a wire
|
||||
if (Depth == 0) begin
|
||||
assign d_o = d_i;
|
||||
// register of depth 1 is a simple register
|
||||
end else if (Depth == 1) begin
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (~rst_ni) begin
|
||||
d_o <= '0;
|
||||
end else begin
|
||||
d_o <= d_i;
|
||||
end
|
||||
end
|
||||
// if depth is greater than 1 it becomes a shift register
|
||||
end else if (Depth > 1) begin
|
||||
dtype [Depth-1:0] reg_d, reg_q;
|
||||
assign d_o = reg_q[Depth-1];
|
||||
assign reg_d = {reg_q[Depth-2:0], d_i};
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (~rst_ni) begin
|
||||
reg_q <= '0;
|
||||
end else begin
|
||||
reg_q <= reg_d;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -1,89 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
//
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
//
|
||||
// Fabian Schuiki <fschuiki@iis.ee.ethz.ch>
|
||||
|
||||
|
||||
/// A register with handshakes that completely cuts any combinational paths
|
||||
/// between the input and output.
|
||||
module spill_register #(
|
||||
parameter type T = logic
|
||||
)(
|
||||
input logic clk_i ,
|
||||
input logic rst_ni ,
|
||||
input logic valid_i ,
|
||||
output logic ready_o ,
|
||||
input T data_i ,
|
||||
output logic valid_o ,
|
||||
input logic ready_i ,
|
||||
output T data_o
|
||||
);
|
||||
|
||||
// The A register.
|
||||
T a_data_q;
|
||||
logic a_full_q;
|
||||
logic a_fill, a_drain;
|
||||
logic a_en, a_en_data;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : ps_a_data
|
||||
if (!rst_ni)
|
||||
a_data_q <= '0;
|
||||
else if (a_fill)
|
||||
a_data_q <= data_i;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : ps_a_full
|
||||
if (!rst_ni)
|
||||
a_full_q <= 0;
|
||||
else if (a_fill || a_drain)
|
||||
a_full_q <= a_fill;
|
||||
end
|
||||
|
||||
// The B register.
|
||||
T b_data_q;
|
||||
logic b_full_q;
|
||||
logic b_fill, b_drain;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : ps_b_data
|
||||
if (!rst_ni)
|
||||
b_data_q <= '0;
|
||||
else if (b_fill)
|
||||
b_data_q <= a_data_q;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : ps_b_full
|
||||
if (!rst_ni)
|
||||
b_full_q <= 0;
|
||||
else if (b_fill || b_drain)
|
||||
b_full_q <= b_fill;
|
||||
end
|
||||
|
||||
// Fill the A register when the A or B register is empty. Drain the A register
|
||||
// whenever it is full and being filled.
|
||||
assign a_fill = valid_i && ready_o;
|
||||
assign a_drain = a_full_q && !b_full_q;
|
||||
|
||||
// Fill the B register whenever the A register is drained, but the downstream
|
||||
// circuit is not ready. Drain the B register whenever it is full and the
|
||||
// downstream circuit is ready.
|
||||
assign b_fill = a_drain && !ready_i;
|
||||
assign b_drain = b_full_q && ready_i;
|
||||
|
||||
// We can accept input as long as register B is not full.
|
||||
assign ready_o = !a_full_q || !b_full_q;
|
||||
|
||||
// The unit provides output as long as one of the registers is filled.
|
||||
assign valid_o = a_full_q | b_full_q;
|
||||
|
||||
// We empty the spill register before the slice register.
|
||||
assign data_o = b_full_q ? b_data_q : a_data_q;
|
||||
|
||||
endmodule
|
|
@ -1,46 +0,0 @@
|
|||
// Copyright 2017, 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
//
|
||||
// Date: 13.10.2017
|
||||
// Description: SRAM Behavioral Model
|
||||
|
||||
module sram #(
|
||||
int unsigned DATA_WIDTH = 64,
|
||||
int unsigned NUM_WORDS = 1024
|
||||
)(
|
||||
input logic clk_i,
|
||||
|
||||
input logic req_i,
|
||||
input logic we_i,
|
||||
input logic [$clog2(NUM_WORDS)-1:0] addr_i,
|
||||
input logic [DATA_WIDTH-1:0] wdata_i,
|
||||
input logic [DATA_WIDTH-1:0] be_i,
|
||||
output logic [DATA_WIDTH-1:0] rdata_o
|
||||
);
|
||||
localparam ADDR_WIDTH = $clog2(NUM_WORDS);
|
||||
|
||||
logic [DATA_WIDTH-1:0] ram [NUM_WORDS-1:0];
|
||||
logic [ADDR_WIDTH-1:0] raddr_q;
|
||||
|
||||
// 1. randomize array
|
||||
// 2. randomize output when no request is active
|
||||
always_ff @(posedge clk_i) begin
|
||||
if (req_i) begin
|
||||
if (!we_i)
|
||||
raddr_q <= addr_i;
|
||||
else
|
||||
for (int i = 0; i < DATA_WIDTH; i++)
|
||||
if (be_i[i]) ram[addr_i][i] <= wdata_i[i];
|
||||
end
|
||||
end
|
||||
|
||||
assign rdata_o = ram[raddr_q];
|
||||
|
||||
endmodule
|
|
@ -1,49 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Stream arbiter: Arbitrates a parametrizable number of input streams (i.e., valid-ready
|
||||
// handshaking with dependency rules as in AXI4) to a single output stream. Once `oup_valid_o` is
|
||||
// asserted, `oup_data_o` remains invariant until the output handshake has occurred. The
|
||||
// arbitration scheme is round-robin with "look ahead", see the `rrarbiter` for details.
|
||||
|
||||
module stream_arbiter #(
|
||||
parameter type DATA_T = logic, // Vivado requires a default value for type parameters.
|
||||
parameter integer N_INP = -1, // Synopsys DC requires a default value for parameters.
|
||||
parameter ARBITER = "rr" // "rr" or "prio"
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
input DATA_T [N_INP-1:0] inp_data_i,
|
||||
input logic [N_INP-1:0] inp_valid_i,
|
||||
output logic [N_INP-1:0] inp_ready_o,
|
||||
|
||||
output DATA_T oup_data_o,
|
||||
output logic oup_valid_o,
|
||||
input logic oup_ready_i
|
||||
);
|
||||
|
||||
stream_arbiter_flushable #(
|
||||
.DATA_T (DATA_T),
|
||||
.N_INP (N_INP),
|
||||
.ARBITER (ARBITER)
|
||||
) i_arb (
|
||||
.clk_i (clk_i),
|
||||
.rst_ni (rst_ni),
|
||||
.flush_i (1'b0),
|
||||
.inp_data_i (inp_data_i),
|
||||
.inp_valid_i (inp_valid_i),
|
||||
.inp_ready_o (inp_ready_o),
|
||||
.oup_data_o (oup_data_o),
|
||||
.oup_valid_o (oup_valid_o),
|
||||
.oup_ready_i (oup_ready_i)
|
||||
);
|
||||
|
||||
endmodule
|
|
@ -1,80 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Stream arbiter: Arbitrates a parametrizable number of input streams (i.e., valid-ready
|
||||
// handshaking with dependency rules as in AXI4) to a single output stream. Once `oup_valid_o` is
|
||||
// asserted, `oup_data_o` remains invariant until the output handshake has occurred. The
|
||||
// arbitration scheme is fair round-robin tree, see `rr_arb_tree` for details.
|
||||
|
||||
module stream_arbiter_flushable #(
|
||||
parameter type DATA_T = logic, // Vivado requires a default value for type parameters.
|
||||
parameter integer N_INP = -1, // Synopsys DC requires a default value for parameters.
|
||||
parameter ARBITER = "rr" // "rr" or "prio"
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic flush_i,
|
||||
|
||||
input DATA_T [N_INP-1:0] inp_data_i,
|
||||
input logic [N_INP-1:0] inp_valid_i,
|
||||
output logic [N_INP-1:0] inp_ready_o,
|
||||
|
||||
output DATA_T oup_data_o,
|
||||
output logic oup_valid_o,
|
||||
input logic oup_ready_i
|
||||
);
|
||||
|
||||
if (ARBITER == "rr") begin : gen_rr_arb
|
||||
rr_arb_tree #(
|
||||
.NumIn (N_INP),
|
||||
.DataType (DATA_T),
|
||||
.ExtPrio (1'b0),
|
||||
.AxiVldRdy (1'b1),
|
||||
.LockIn (1'b1)
|
||||
) i_arbiter (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.flush_i,
|
||||
.rr_i ('0),
|
||||
.req_i (inp_valid_i),
|
||||
.gnt_o (inp_ready_o),
|
||||
.data_i (inp_data_i),
|
||||
.gnt_i (oup_ready_i),
|
||||
.req_o (oup_valid_o),
|
||||
.data_o (oup_data_o),
|
||||
.idx_o ()
|
||||
);
|
||||
|
||||
end else if (ARBITER == "prio") begin : gen_prio_arb
|
||||
rr_arb_tree #(
|
||||
.NumIn (N_INP),
|
||||
.DataType (DATA_T),
|
||||
.ExtPrio (1'b1),
|
||||
.AxiVldRdy (1'b1),
|
||||
.LockIn (1'b1)
|
||||
) i_arbiter (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.flush_i,
|
||||
.rr_i ('0),
|
||||
.req_i (inp_valid_i),
|
||||
.gnt_o (inp_ready_o),
|
||||
.data_i (inp_data_i),
|
||||
.gnt_i (oup_ready_i),
|
||||
.req_o (oup_valid_o),
|
||||
.data_o (oup_data_o),
|
||||
.idx_o ()
|
||||
);
|
||||
|
||||
end else begin : gen_arb_error
|
||||
$fatal(1, "Invalid value for parameter 'ARBITER'!");
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -1,132 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Author: Florian Zaruba, zarubaf@iis.ee.ethz.ch
|
||||
// Description: Delay (or randomize) AXI-like handshaking
|
||||
|
||||
module stream_delay #(
|
||||
parameter bit StallRandom = 0,
|
||||
parameter int FixedDelay = 1,
|
||||
parameter type payload_t = logic
|
||||
)(
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
|
||||
input payload_t payload_i,
|
||||
output logic ready_o,
|
||||
input logic valid_i,
|
||||
|
||||
output payload_t payload_o,
|
||||
input logic ready_i,
|
||||
output logic valid_o
|
||||
);
|
||||
|
||||
if (FixedDelay == 0 && !StallRandom) begin : pass_through
|
||||
assign ready_o = ready_i;
|
||||
assign valid_o = valid_i;
|
||||
assign payload_o = payload_i;
|
||||
end else begin
|
||||
|
||||
localparam COUNTER_BITS = 4;
|
||||
|
||||
typedef enum logic [1:0] {
|
||||
Idle, Valid, Ready
|
||||
} state_e;
|
||||
|
||||
state_e state_d, state_q;
|
||||
|
||||
logic load;
|
||||
logic [3:0] count_out;
|
||||
logic en;
|
||||
|
||||
logic [COUNTER_BITS-1:0] counter_load;
|
||||
|
||||
assign payload_o = payload_i;
|
||||
|
||||
always_comb begin
|
||||
state_d = state_q;
|
||||
valid_o = 1'b0;
|
||||
ready_o = 1'b0;
|
||||
load = 1'b0;
|
||||
en = 1'b0;
|
||||
|
||||
unique case (state_q)
|
||||
Idle: begin
|
||||
if (valid_i) begin
|
||||
load = 1'b1;
|
||||
state_d = Valid;
|
||||
// Just one cycle delay
|
||||
if (FixedDelay == 1 || (StallRandom && counter_load == 1)) begin
|
||||
state_d = Ready;
|
||||
end
|
||||
|
||||
if (StallRandom && counter_load == 0) begin
|
||||
valid_o = 1'b1;
|
||||
ready_o = ready_i;
|
||||
if (ready_i) state_d = Idle;
|
||||
else state_d = Ready;
|
||||
end
|
||||
end
|
||||
end
|
||||
Valid: begin
|
||||
en = 1'b1;
|
||||
if (count_out == 0) begin
|
||||
state_d = Ready;
|
||||
end
|
||||
end
|
||||
|
||||
Ready: begin
|
||||
valid_o = 1'b1;
|
||||
ready_o = ready_i;
|
||||
if (ready_i) state_d = Idle;
|
||||
end
|
||||
default : /* default */;
|
||||
endcase
|
||||
|
||||
end
|
||||
|
||||
if (StallRandom) begin : random_stall
|
||||
lfsr_16bit #(
|
||||
.WIDTH ( 16 )
|
||||
) i_lfsr_16bit (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.en_i ( load ),
|
||||
.refill_way_oh ( ),
|
||||
.refill_way_bin ( counter_load )
|
||||
);
|
||||
end else begin
|
||||
assign counter_load = FixedDelay;
|
||||
end
|
||||
|
||||
counter #(
|
||||
.WIDTH ( COUNTER_BITS )
|
||||
) i_counter (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.clear_i ( 1'b0 ),
|
||||
.en_i ( en ),
|
||||
.load_i ( load ),
|
||||
.down_i ( 1'b1 ),
|
||||
.d_i ( counter_load ),
|
||||
.q_o ( count_out ),
|
||||
.overflow_o ( )
|
||||
);
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (~rst_ni) begin
|
||||
state_q <= Idle;
|
||||
end else begin
|
||||
state_q <= state_d;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -1,37 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
/// Stream demultiplexer: Connects the input stream (valid-ready) handshake to one of `N_OUP` output
|
||||
/// stream handshakes.
|
||||
///
|
||||
/// This module has no data ports because stream data does not need to be demultiplexed: the data of
|
||||
/// the input stream can just be applied at all output streams.
|
||||
|
||||
module stream_demux #(
|
||||
parameter integer N_OUP = 1,
|
||||
/// Dependent parameters, DO NOT OVERRIDE!
|
||||
localparam integer LOG_N_OUP = $clog2(N_OUP)
|
||||
) (
|
||||
input logic inp_valid_i,
|
||||
output logic inp_ready_o,
|
||||
|
||||
input logic [LOG_N_OUP-1:0] oup_sel_i,
|
||||
|
||||
output logic [N_OUP-1:0] oup_valid_o,
|
||||
input logic [N_OUP-1:0] oup_ready_i
|
||||
);
|
||||
|
||||
always_comb begin
|
||||
oup_valid_o = '0;
|
||||
oup_valid_o[oup_sel_i] = inp_valid_i;
|
||||
end
|
||||
assign inp_ready_o = oup_ready_i[oup_sel_i];
|
||||
|
||||
endmodule
|
|
@ -1,26 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Stream filter: If `drop_i` is `1`, signal `ready` to the upstream regardless of the downstream,
|
||||
// and do not propagate `valid` downstream. Otherwise, connect upstream to downstream.
|
||||
module stream_filter (
|
||||
input logic valid_i,
|
||||
output logic ready_o,
|
||||
|
||||
input logic drop_i,
|
||||
|
||||
output logic valid_o,
|
||||
input logic ready_i
|
||||
);
|
||||
|
||||
assign valid_o = drop_i ? 1'b0 : valid_i;
|
||||
assign ready_o = drop_i ? 1'b1 : ready_i;
|
||||
|
||||
endmodule
|
|
@ -1,133 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Stream fork: Connects the input stream (ready-valid) handshake to *all* of `N_OUP` output stream
|
||||
// handshakes. For each input stream handshake, every output stream handshakes exactly once. The
|
||||
// input stream only handshakes when all output streams have handshaked, but the output streams do
|
||||
// not have to handshake simultaneously.
|
||||
//
|
||||
// This module has no data ports because stream data does not need to be forked: the data of the
|
||||
// input stream can just be applied at all output streams.
|
||||
|
||||
module stream_fork #(
|
||||
parameter int unsigned N_OUP = 0 // Synopsys DC requires a default value for parameters.
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic valid_i,
|
||||
output logic ready_o,
|
||||
output logic [N_OUP-1:0] valid_o,
|
||||
input logic [N_OUP-1:0] ready_i
|
||||
);
|
||||
|
||||
typedef enum logic {READY, WAIT} state_t;
|
||||
|
||||
logic [N_OUP-1:0] oup_ready,
|
||||
all_ones;
|
||||
|
||||
state_t inp_state_d, inp_state_q;
|
||||
|
||||
// Input control FSM
|
||||
always_comb begin
|
||||
// ready_o = 1'b0;
|
||||
inp_state_d = inp_state_q;
|
||||
|
||||
unique case (inp_state_q)
|
||||
READY: begin
|
||||
if (valid_i) begin
|
||||
if (valid_o == all_ones && ready_i == all_ones) begin
|
||||
// If handshake on all outputs, handshake on input.
|
||||
ready_o = 1'b1;
|
||||
end else begin
|
||||
ready_o = 1'b0;
|
||||
// Otherwise, wait for inputs that did not handshake yet.
|
||||
inp_state_d = WAIT;
|
||||
end
|
||||
end else begin
|
||||
ready_o = 1'b0;
|
||||
end
|
||||
end
|
||||
WAIT: begin
|
||||
if (valid_i && oup_ready == all_ones) begin
|
||||
ready_o = 1'b1;
|
||||
inp_state_d = READY;
|
||||
end else begin
|
||||
ready_o = 1'b0;
|
||||
end
|
||||
end
|
||||
default: begin
|
||||
inp_state_d = READY;
|
||||
ready_o = 1'b0;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i, negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
inp_state_q <= READY;
|
||||
end else begin
|
||||
inp_state_q <= inp_state_d;
|
||||
end
|
||||
end
|
||||
|
||||
// Output control FSM
|
||||
for (genvar i = 0; i < N_OUP; i++) begin: gen_oup_state
|
||||
state_t oup_state_d, oup_state_q;
|
||||
|
||||
always_comb begin
|
||||
oup_ready[i] = 1'b1;
|
||||
valid_o[i] = 1'b0;
|
||||
oup_state_d = oup_state_q;
|
||||
|
||||
unique case (oup_state_q)
|
||||
READY: begin
|
||||
if (valid_i) begin
|
||||
valid_o[i] = 1'b1;
|
||||
if (ready_i[i]) begin // Output handshake
|
||||
if (!ready_o) begin // No input handshake yet
|
||||
oup_state_d = WAIT;
|
||||
end
|
||||
end else begin // No output handshake
|
||||
oup_ready[i] = 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
WAIT: begin
|
||||
if (valid_i && ready_o) begin // Input handshake
|
||||
oup_state_d = READY;
|
||||
end
|
||||
end
|
||||
default: begin
|
||||
oup_state_d = READY;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i, negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
oup_state_q <= READY;
|
||||
end else begin
|
||||
oup_state_q <= oup_state_d;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign all_ones = '1; // Synthesis fix for Vivado, which does not correctly compute the width
|
||||
// of the '1 literal when assigned to a port of parametrized width.
|
||||
|
||||
// pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
initial begin: p_assertions
|
||||
assert (N_OUP >= 1) else $fatal("Number of outputs must be at least 1!");
|
||||
end
|
||||
`endif
|
||||
// pragma translate_on
|
||||
|
||||
endmodule
|
|
@ -1,46 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
/// Stream multiplexer: connects the output to one of `N_INP` data streams with valid-ready
|
||||
/// handshaking.
|
||||
|
||||
module stream_mux #(
|
||||
parameter type DATA_T = logic, // Vivado requires a default value for type parameters.
|
||||
parameter integer N_INP = 0, // Synopsys DC requires a default value for value parameters.
|
||||
/// Dependent parameters, DO NOT OVERRIDE!
|
||||
localparam integer LOG_N_INP = $clog2(N_INP)
|
||||
) (
|
||||
input DATA_T [N_INP-1:0] inp_data_i,
|
||||
input logic [N_INP-1:0] inp_valid_i,
|
||||
output logic [N_INP-1:0] inp_ready_o,
|
||||
|
||||
input logic [LOG_N_INP-1:0] inp_sel_i,
|
||||
|
||||
output DATA_T oup_data_o,
|
||||
output logic oup_valid_o,
|
||||
input logic oup_ready_i
|
||||
);
|
||||
|
||||
always_comb begin
|
||||
inp_ready_o = '0;
|
||||
inp_ready_o[inp_sel_i] = oup_ready_i;
|
||||
end
|
||||
assign oup_data_o = inp_data_i[inp_sel_i];
|
||||
assign oup_valid_o = inp_valid_i[inp_sel_i];
|
||||
|
||||
// pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
initial begin: p_assertions
|
||||
assert (N_INP >= 1) else $fatal ("The number of inputs must be at least 1!");
|
||||
end
|
||||
`endif
|
||||
// pragma translate_on
|
||||
|
||||
endmodule
|
|
@ -1,57 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
/// Register with a simple stream-like ready/valid handshake.
|
||||
/// This register does not cut combinatorial paths on all control signals; if you need a complete
|
||||
/// cut, use the `spill_register`.
|
||||
module stream_register #(
|
||||
parameter type T = logic // Vivado requires a default value for type parameters.
|
||||
) (
|
||||
input logic clk_i, // Clock
|
||||
input logic rst_ni, // Asynchronous active-low reset
|
||||
input logic clr_i, // Synchronous clear
|
||||
input logic testmode_i, // Test mode to bypass clock gating
|
||||
// Input port
|
||||
input logic valid_i,
|
||||
output logic ready_o,
|
||||
input T data_i,
|
||||
// Output port
|
||||
output logic valid_o,
|
||||
input logic ready_i,
|
||||
output T data_o
|
||||
);
|
||||
|
||||
logic fifo_empty,
|
||||
fifo_full;
|
||||
|
||||
fifo_v2 #(
|
||||
.FALL_THROUGH (1'b0),
|
||||
.DATA_WIDTH ($size(T)),
|
||||
.DEPTH (1),
|
||||
.dtype (T)
|
||||
) i_fifo (
|
||||
.clk_i (clk_i),
|
||||
.rst_ni (rst_ni),
|
||||
.flush_i (clr_i),
|
||||
.testmode_i (testmode_i),
|
||||
.full_o (fifo_full),
|
||||
.empty_o (fifo_empty),
|
||||
.alm_full_o ( ),
|
||||
.alm_empty_o ( ),
|
||||
.data_i (data_i),
|
||||
.push_i (valid_i & ~fifo_full),
|
||||
.data_o (data_o),
|
||||
.pop_i (ready_i & ~fifo_empty)
|
||||
);
|
||||
|
||||
assign ready_o = ~fifo_full;
|
||||
assign valid_o = ~fifo_empty;
|
||||
|
||||
endmodule
|
|
@ -1,34 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Antonio Pullini <pullinia@iis.ee.ethz.ch>
|
||||
|
||||
module sync #(
|
||||
parameter int unsigned STAGES = 2
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic serial_i,
|
||||
output logic serial_o
|
||||
);
|
||||
|
||||
logic [STAGES-1:0] reg_q;
|
||||
|
||||
always_ff @(posedge clk_i, negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
reg_q <= 'h0;
|
||||
end else begin
|
||||
reg_q <= {reg_q[STAGES-2:0], serial_i};
|
||||
end
|
||||
end
|
||||
|
||||
assign serial_o = reg_q[STAGES-1];
|
||||
|
||||
endmodule
|
|
@ -1,56 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
|
||||
// Antonio Pullini <pullinia@iis.ee.ethz.ch>
|
||||
|
||||
module sync_wedge #(
|
||||
parameter int unsigned STAGES = 2
|
||||
) (
|
||||
input logic clk_i,
|
||||
input logic rst_ni,
|
||||
input logic en_i,
|
||||
input logic serial_i,
|
||||
output logic r_edge_o,
|
||||
output logic f_edge_o,
|
||||
output logic serial_o
|
||||
);
|
||||
logic clk;
|
||||
logic serial, serial_q;
|
||||
|
||||
assign serial_o = serial_q;
|
||||
assign f_edge_o = (~serial) & serial_q;
|
||||
assign r_edge_o = serial & (~serial_q);
|
||||
|
||||
sync #(
|
||||
.STAGES (STAGES)
|
||||
) i_sync (
|
||||
.clk_i,
|
||||
.rst_ni,
|
||||
.serial_i,
|
||||
.serial_o ( serial )
|
||||
);
|
||||
|
||||
pulp_clock_gating i_pulp_clock_gating (
|
||||
.clk_i,
|
||||
.en_i,
|
||||
.test_en_i ( 1'b0 ),
|
||||
.clk_o ( clk )
|
||||
);
|
||||
|
||||
always_ff @(posedge clk, negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
serial_q <= 1'b0;
|
||||
end else begin
|
||||
if (en_i) begin
|
||||
serial_q <= serial;
|
||||
end
|
||||
end
|
||||
end
|
||||
endmodule
|
|
@ -1,21 +0,0 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (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-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.
|
||||
//
|
||||
// Author: Florian Zaruba, ETH Zurich
|
||||
// Date: 29.10.2018
|
||||
// Description: Dummy circuit to mitigate Open Pin warnings
|
||||
|
||||
/* verilator lint_off UNUSED */
|
||||
module unread (
|
||||
input logic d_i
|
||||
);
|
||||
|
||||
endmodule
|
||||
/* verilator lint_on UNUSED */
|
|
@ -1,176 +0,0 @@
|
|||
SOLDERPAD HARDWARE LICENSE version 0.51
|
||||
|
||||
This license is based closely on the Apache License Version 2.0, but is not
|
||||
approved or endorsed by the Apache Foundation. A copy of the non-modified
|
||||
Apache License 2.0 can be found at http://www.apache.org/licenses/LICENSE-2.0.
|
||||
|
||||
As this license is not currently OSI or FSF approved, the Licensor permits any
|
||||
Work licensed under this License, at the option of the Licensee, to be treated
|
||||
as licensed under the Apache License Version 2.0 (which is so approved).
|
||||
|
||||
This License is licensed under the terms of this License and in particular
|
||||
clause 7 below (Disclaimer of Warranties) applies in relation to its use.
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and
|
||||
distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the Rights owner or entity authorized by the Rights owner
|
||||
that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities
|
||||
that control, are controlled by, or are under common control with that entity.
|
||||
For the purposes of this definition, "control" means (i) the power, direct or
|
||||
indirect, to cause the direction or management of such entity, whether by
|
||||
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising
|
||||
permissions granted by this License.
|
||||
|
||||
"Rights" means copyright and any similar right including design right (whether
|
||||
registered or unregistered), semiconductor topography (mask) rights and
|
||||
database rights (but excluding Patents and Trademarks).
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications, including
|
||||
but not limited to source code, net lists, board layouts, CAD files,
|
||||
documentation source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation or
|
||||
translation of a Source form, including but not limited to compiled object
|
||||
code, generated documentation, the instantiation of a hardware design and
|
||||
conversions to other media types, including intermediate forms such as
|
||||
bytecodes, FPGA bitstreams, artwork and semiconductor topographies (mask
|
||||
works).
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source form or other
|
||||
Object form, made available under the License, as indicated by a Rights notice
|
||||
that is included in or attached to the work (an example is provided in the
|
||||
Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that
|
||||
is based on (or derived from) the Work and for which the editorial revisions,
|
||||
annotations, elaborations, or other modifications represent, as a whole, an
|
||||
original work of authorship. For the purposes of this License, Derivative Works
|
||||
shall not include works that remain separable from, or merely link (or bind by
|
||||
name) or physically connect to or interoperate with the interfaces of, the Work
|
||||
and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any design or work of authorship, including the
|
||||
original version of the Work and any modifications or additions to that Work or
|
||||
Derivative Works thereof, that is intentionally submitted to Licensor for
|
||||
inclusion in the Work by the Rights owner or by an individual or Legal Entity
|
||||
authorized to submit on behalf of the Rights owner. For the purposes of this
|
||||
definition, "submitted" means any form of electronic, verbal, or written
|
||||
communication sent to the Licensor or its representatives, including but not
|
||||
limited to communication on electronic mailing lists, source code control
|
||||
systems, and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but excluding
|
||||
communication that is conspicuously marked or otherwise designated in writing
|
||||
by the Rights owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
|
||||
of whom a Contribution has been received by Licensor and subsequently
|
||||
incorporated within the Work.
|
||||
|
||||
2. Grant of License. Subject to the terms and conditions of this License, each
|
||||
Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable license under the Rights to reproduce,
|
||||
prepare Derivative Works of, publicly display, publicly perform, sublicense,
|
||||
and distribute the Work and such Derivative Works in Source or Object form and
|
||||
do anything in relation to the Work as if the Rights did not exist.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of this
|
||||
License, each Contributor hereby grants to You a perpetual, worldwide,
|
||||
non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this
|
||||
section) patent license to make, have made, use, offer to sell, sell, import,
|
||||
and otherwise transfer the Work, where such license applies only to those
|
||||
patent claims licensable by such Contributor that are necessarily infringed by
|
||||
their Contribution(s) alone or by combination of their Contribution(s) with the
|
||||
Work to which such Contribution(s) was submitted. If You institute patent
|
||||
litigation against any entity (including a cross-claim or counterclaim in a
|
||||
lawsuit) alleging that the Work or a Contribution incorporated within the Work
|
||||
constitutes direct or contributory patent infringement, then any patent
|
||||
licenses granted to You under this License for that Work shall terminate as of
|
||||
the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the Work or
|
||||
Derivative Works thereof in any medium, with or without modifications, and in
|
||||
Source or Object form, provided that You meet the following conditions:
|
||||
|
||||
You must give any other recipients of the Work or Derivative Works a copy
|
||||
of this License; and
|
||||
|
||||
You must cause any modified files to carry prominent notices stating that
|
||||
You changed the files; and
|
||||
|
||||
You must retain, in the Source form of any Derivative Works that You
|
||||
distribute, all copyright, patent, trademark, and attribution notices from
|
||||
the Source form of the Work, excluding those notices that do not pertain to
|
||||
any part of the Derivative Works; and
|
||||
|
||||
If the Work includes a "NOTICE" text file as part of its distribution, then
|
||||
any Derivative Works that You distribute must include a readable copy of
|
||||
the attribution notices contained within such NOTICE file, excluding those
|
||||
notices that do not pertain to any part of the Derivative Works, in at
|
||||
least one of the following places: within a NOTICE text file distributed as
|
||||
part of the Derivative Works; within the Source form or documentation, if
|
||||
provided along with the Derivative Works; or, within a display generated by
|
||||
the Derivative Works, if and wherever such third-party notices normally
|
||||
appear. The contents of the NOTICE file are for informational purposes only
|
||||
and do not modify the License. You may add Your own attribution notices
|
||||
within Derivative Works that You distribute, alongside or as an addendum to
|
||||
the NOTICE text from the Work, provided that such additional attribution
|
||||
notices cannot be construed as modifying the License. You may add Your own
|
||||
copyright statement to Your modifications and may provide additional or
|
||||
different license terms and conditions for use, reproduction, or
|
||||
distribution of Your modifications, or for any such Derivative Works as a
|
||||
whole, provided Your use, reproduction, and distribution of the Work
|
||||
otherwise complies with the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise, any
|
||||
Contribution intentionally submitted for inclusion in the Work by You to the
|
||||
Licensor shall be under the terms and conditions of this License, without any
|
||||
additional terms or conditions. Notwithstanding the above, nothing herein shall
|
||||
supersede or modify the terms of any separate license agreement you may have
|
||||
executed with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade names,
|
||||
trademarks, service marks, or product names of the Licensor, except as required
|
||||
for reasonable and customary use in describing the origin of the Work and
|
||||
reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in
|
||||
writing, Licensor provides the Work (and each Contributor provides its
|
||||
Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied, including, without limitation, any warranties
|
||||
or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any risks
|
||||
associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory, whether in
|
||||
tort (including negligence), contract, or otherwise, unless required by
|
||||
applicable law (such as deliberate and grossly negligent acts) or agreed to in
|
||||
writing, shall any Contributor be liable to You for damages, including any
|
||||
direct, indirect, special, incidental, or consequential damages of any
|
||||
character arising as a result of this License or out of the use or inability to
|
||||
use the Work (including but not limited to damages for loss of goodwill, work
|
||||
stoppage, computer failure or malfunction, or any and all other commercial
|
||||
damages or losses), even if such Contributor has been advised of the
|
||||
possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing the Work or
|
||||
Derivative Works thereof, You may choose to offer, and charge a fee for,
|
||||
acceptance of support, warranty, indemnity, or other liability obligations
|
||||
and/or rights consistent with this License. However, in accepting such
|
||||
obligations, You may act only on Your own behalf and on Your sole
|
||||
responsibility, not on behalf of any other Contributor, and only if You agree
|
||||
to indemnify, defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason of your
|
||||
accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
14
vendor/pulp-platform_common_cells_fpu.lock.hjson
vendored
14
vendor/pulp-platform_common_cells_fpu.lock.hjson
vendored
|
@ -1,14 +0,0 @@
|
|||
// Copyright lowRISC contributors.
|
||||
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// This file is generated by the util/vendor script. Please do not modify it
|
||||
// manually.
|
||||
|
||||
{
|
||||
upstream:
|
||||
{
|
||||
url: https://github.com/pulp-platform/common_cells.git
|
||||
rev: 790f2385c01c83022474eede55809666209216e3
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2022 Thales DIS France SAS
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0.
|
||||
// Original Author: Zbigniew Chamski (zbigniew.chamski@thalesgroup.com)
|
||||
|
||||
{
|
||||
// Name of the project
|
||||
name: "pulp_common_cells_fpu",
|
||||
|
||||
// Target directory: relative to the location of this script.
|
||||
target_dir: "pulp-platform/fpnew/src/common_cells",
|
||||
|
||||
// Upstream repository
|
||||
upstream: {
|
||||
// URL
|
||||
url: "https://github.com/pulp-platform/common_cells.git",
|
||||
// revision
|
||||
rev: "v1.13.1",
|
||||
}
|
||||
|
||||
//Patch dir for local changes
|
||||
patch_dir: "patches/pulp-platform/common_cells_fpu",
|
||||
|
||||
// Exclusions from upstream content
|
||||
exclude_from_upstream: [
|
||||
".git",
|
||||
".github",
|
||||
".gitlab-ci.yml",
|
||||
".travis.yml",
|
||||
"Bender.yml",
|
||||
"ci",
|
||||
"common_cells.core",
|
||||
"formal",
|
||||
"ips_list.yml",
|
||||
"lint",
|
||||
"Makefile",
|
||||
"src_files.yml",
|
||||
"test",
|
||||
]
|
||||
}
|
||||
|
|
@ -9,6 +9,6 @@
|
|||
upstream:
|
||||
{
|
||||
url: https://github.com/pulp-platform/fpu_div_sqrt_mvp.git
|
||||
rev: 83a601f97934ed5e06d737b9c80d98b08867c5fa
|
||||
rev: 86e1f558b3c95e91577c41b2fc452c86b04e85ac
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
name: "pulp_fpu_div_sqrt_mvp",
|
||||
|
||||
// Target directory: relative to the location of this script.
|
||||
target_dir: "pulp-platform/fpnew/src/fpu_div_sqrt_mvp",
|
||||
target_dir: "openhwgroup/cvfpu/src/fpu_div_sqrt_mvp",
|
||||
|
||||
// Upstream repository
|
||||
upstream: {
|
||||
// URL
|
||||
url: "https://github.com/pulp-platform/fpu_div_sqrt_mvp.git",
|
||||
// revision
|
||||
rev: "v1.0.3",
|
||||
rev: "v1.0.4",
|
||||
}
|
||||
|
||||
//Patch dir for local changes
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue