Merge branch 'ariane_next' into serpent

This commit is contained in:
Michael Schaffner 2018-09-14 21:00:29 +02:00
commit e2c57474f8
No known key found for this signature in database
GPG key ID: 7AA09AE049819C2C
29 changed files with 1161 additions and 808 deletions

1
.gitignore vendored
View file

@ -22,3 +22,4 @@ build/
*.vcd
*.log
*.out
work-ver/*

View file

@ -17,7 +17,7 @@ before_script:
- export NUM_JOBS=4
- ci/make-tmp.sh
- git submodule update --init --recursive
variables:
GIT_SUBMODULE_STRATEGY: recursive
@ -28,7 +28,6 @@ stages:
###################################
# prepare
build:
stage: build
script:

3
.gitmodules vendored
View file

@ -1,9 +1,6 @@
[submodule "src/axi_mem_if"]
path = src/axi_mem_if
url = https://github.com/pulp-platform/axi_mem_if.git
[submodule "src/axi_slice"]
path = src/axi_slice
url = https://github.com/pulp-platform/axi_slice.git
[submodule "src/axi_node"]
path = src/axi_node
url = https://github.com/pulp-platform/axi_node.git

View file

@ -88,7 +88,6 @@ jobs:
script:
- ci/build-riscv-tests.sh
- make -j${NUM_JOBS} run-asm-tests2-verilator
- stage: test
name: run torture
script:

View file

@ -61,7 +61,17 @@ sources:
- src/store_buffer.sv
- src/store_unit.sv
- src/tlb.sv
- src/commit_stage.sv
- src/axi_adapter.sv
- src/cache_subsystem/cache_ctrl.sv
- src/cache_subsystem/miss_handler.sv
- src/cache_subsystem/std_cache_subsystem.sv
- src/cache_subsystem/std_icache.sv
- src/cache_subsystem/std_nbdcache.sv
- src/debug/debug_rom/debug_rom.sv
- src/debug/dm_csrs.sv
- src/clint/clint.sv
- src/clint/axi_lite_interface.sv
- src/debug/dm_mem.sv
- src/debug/dm_top.sv
- src/debug/dmi_cdc.sv

View file

@ -10,7 +10,6 @@ ver-library ?= work-ver
dpi-library ?= work-dpi
# Top level module to compile
top_level ?= ariane_tb
test_top_level ?= ariane_tb
# Maximum amount of cycles for a successful simulation run
max_cycles ?= 10000000
# Test case to run
@ -31,14 +30,14 @@ ariane_pkg := include/riscv_pkg.sv \
include/ariane_pkg.sv \
include/std_cache_pkg.sv \
include/serpent_cache_pkg.sv \
include/axi_if.sv
include/axi_intf.sv
# utility modules
util := $(wildcard src/util/*.svh) \
src/util/instruction_tracer_pkg.sv \
src/util/instruction_tracer_if.sv \
src/util/cluster_clock_gating.sv \
src/util/sram.sv
src/util/sram.sv
# Test packages
test_pkg := $(wildcard tb/test/*/*sequence_pkg.sv*) \
@ -51,16 +50,20 @@ src := $(filter-out src/ariane_regfile.sv, $(wildcard src/*.sv)) \
$(wildcard src/frontend/*.sv) \
$(wildcard src/cache_subsystem/*.sv) \
$(wildcard bootrom/*.sv) \
$(wildcard src/axi_slice/*.sv) \
$(wildcard src/clint/*.sv) \
$(wildcard src/axi_node/src/*.sv) \
$(wildcard src/axi_mem_if/src/*.sv) \
$(filter-out src/debug/dm_pkg.sv, $(wildcard src/debug/*.sv)) \
$(wildcard src/debug/debug_rom/*.sv) \
src/axi/src/axi_cut.sv \
src/axi/src/axi_join.sv \
src/fpga-support/rtl/SyncSpRamBeNx64.sv \
src/common_cells/src/deprecated/generic_fifo.sv \
src/common_cells/src/deprecated/pulp_sync.sv \
src/common_cells/src/sync.sv \
src/common_cells/src/cdc_2phase.sv \
src/common_cells/src/spill_register.sv \
src/common_cells/src/sync_wedge.sv \
src/common_cells/src/fifo_v2.sv \
src/common_cells/src/fifo_v1.sv \
src/common_cells/src/lzc.sv \
src/common_cells/src/rrarbiter.sv \
src/common_cells/src/lfsr_8bit.sv \
@ -86,7 +89,7 @@ riscv-benchmarks := $(shell xargs printf '\n%s' < $(riscv-benchmarks-list)
riscv-test ?= rv64ui-p-add
# Search here for include files (e.g.: non-standalone components)
incdir :=
incdir :=
# Compile and sim flags
compile_flag += +cover=bcfst+/dut -incr -64 -nologo -quiet -suppress 13262 -permissive +define+$(defines)
uvm-flags += +UVM_NO_RELNOTES
@ -101,7 +104,7 @@ riscv-torture-bin := java -Xmx1G -Xss8M -XX:MaxPermSize=128M -jar sbt-launch.
# Build the TB and module using QuestaSim
build: $(library) $(library)/.build-srcs $(library)/.build-tb $(dpi-library)/ariane_dpi.so
# Optimize top level
vopt$(questa_version) $(compile_flag) -work $(library) $(test_top_level) -o $(test_top_level)_optimized +acc -check_synthesis
vopt$(questa_version) $(compile_flag) -work $(library) $(top_level) -o $(top_level)_optimized +acc -check_synthesis
# src files
$(library)/.build-srcs: $(ariane_pkg) $(util) $(src) $(library)
@ -131,7 +134,7 @@ $(dpi-library)/ariane_dpi.so: $(dpi)
$(CXX) -shared -m64 -o $(dpi-library)/ariane_dpi.so $? -lfesvr
sim: build
sim: build
vsim${questa_version} +permissive -64 -lib ${library} +max-cycles=$(max_cycles) +UVM_TESTNAME=${test_case} \
+BASEDIR=$(riscv-test-dir) $(uvm-flags) "+UVM_VERBOSITY=LOW" -coverage -classdebug +jtag_rbb_enable=0 \
$(QUESTASIM_FLAGS) \
@ -153,7 +156,7 @@ $(riscv-asm-tests): build
-do "coverage save -onexit tmp/$@.ucdb; run -a; quit -code [coverage attribute -name TESTSTATUS -concise]" \
${top_level}_optimized +permissive-off ++$(riscv-test-dir)/$@ ++$(target-options) | tee tmp/riscv-asm-tests-$@.log
$(riscv-benchmarks): build
$(riscv-benchmarks): build
vsim${questa_version} +permissive -64 -c -lib ${library} +max-cycles=$(max_cycles) +UVM_TESTNAME=${test_case} \
+BASEDIR=$(riscv-benchmarks-dir) $(uvm-flags) "+UVM_VERBOSITY=LOW" -coverage -classdebug +jtag_rbb_enable=0 \
$(QUESTASIM_FLAGS) \

View file

@ -25,6 +25,10 @@ Build the Verilator model of Ariane by using the Makefile:
```
$ make verilate
```
To build the verilator model with support for vcd files run
```
$ make verilate DEBUG=1
```
This will create a C++ model of the core including a SystemVerilog wrapper and link it against a C++ testbench (in the `tb` subfolder). The binary can be found in the `work-ver` and accepts a RISC-V ELF binary as an argument, e.g.:

Binary file not shown.

9
fpga/.gitignore vendored Normal file
View file

@ -0,0 +1,9 @@
.*
!.gitignore
vivado*
*.cache
*.hw
*.ip_user_files
*.runs
*.srcs
*.xpr

33
fpga/ariane.xdc Normal file
View file

@ -0,0 +1,33 @@
set_property PACKAGE_PIN AM13 [get_ports sys_rst]
set_property IOSTANDARD LVCMOS33 [get_ports sys_rst]
set_property PACKAGE_PIN A20 [get_ports tck]
set_property IOSTANDARD LVCMOS33 [get_ports tck]
set_property PACKAGE_PIN B20 [get_ports tdi]
set_property PACKAGE_PIN A22 [get_ports tdo]
set_property PACKAGE_PIN A21 [get_ports tms]
set_property PACKAGE_PIN B21 [get_ports trst_n]
set_property IOSTANDARD LVCMOS33 [get_ports tdi]
set_property IOSTANDARD LVCMOS33 [get_ports tdo]
set_property IOSTANDARD LVCMOS33 [get_ports tms]
set_property IOSTANDARD LVCMOS33 [get_ports trst_n]
# accept sub-optimal placement
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets tck_IBUF_inst/O]
create_clock -period 100.000 -name tck -waveform {0.000 50.000} [get_ports tck]
set_input_jitter tck 15.000
####################################################################################
# Constraints from file : 'axi_clock_converter_0_clocks.xdc'
####################################################################################
set_max_delay -datapath_only -from [get_clocks tck] -to [get_clocks mmcm_clkout0] 5.000
set_max_delay -datapath_only -from [get_clocks mmcm_clkout0] -to [get_clocks tck] 5.000
set_max_delay -datapath_only -from [get_clocks tck] -to [get_clocks c0_sys_clk_p] 5.000
set_max_delay -datapath_only -from [get_clocks c0_sys_clk_p] -to [get_clocks tck] 5.000
set_property C_CLK_INPUT_FREQ_HZ 300000000 [get_debug_cores dbg_hub]
set_property C_ENABLE_CLK_DIVIDER false [get_debug_cores dbg_hub]
set_property C_USER_SCAN_CHAIN 1 [get_debug_cores dbg_hub]
connect_debug_port dbg_hub/clk [get_nets clk_1]

543
fpga/ariane_xilinx.sv Normal file
View file

@ -0,0 +1,543 @@
// 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.
module ariane_xilinx (
input logic c0_sys_clk_p, // Clock
input logic c0_sys_clk_n, // Clock
input logic sys_rst, // active high reset
output logic c0_ddr4_act_n,
output logic [16:0] c0_ddr4_adr,
output logic [1:0] c0_ddr4_ba,
output logic [0:0] c0_ddr4_bg,
output logic [0:0] c0_ddr4_cke,
output logic [0:0] c0_ddr4_odt,
output logic [0:0] c0_ddr4_cs_n,
output logic [0:0] c0_ddr4_ck_t,
output logic [0:0] c0_ddr4_ck_c,
output logic c0_ddr4_reset_n,
inout logic [1:0] c0_ddr4_dm_dbi_n,
inout logic [15:0] c0_ddr4_dq,
inout logic [1:0] c0_ddr4_dqs_c,
inout logic [1:0] c0_ddr4_dqs_t,
input logic tck,
input logic tms,
input logic trst_n,
input logic tdi,
output logic tdo
);
localparam logic [63:0] RomBase = 64'h10000;
localparam NBSlave = 4; // debug, Instruction fetch, data bypass, data
localparam NBMaster = 3; // debug, ROM, RAM
localparam logic [63:0] CacheStartAddr = 64'h8000_0000;
localparam AxiAddrWidth = 64;
localparam AxiDataWidth = 64;
localparam AxiIdWidthMaster = 2;
localparam AxiIdWidthSlaves = AxiIdWidthMaster + $clog2(NBSlave); // 4
localparam AxiUserWidth = 1;
AXI_BUS #(
.AXI_ADDR_WIDTH ( AxiAddrWidth ),
.AXI_DATA_WIDTH ( AxiDataWidth ),
.AXI_ID_WIDTH ( AxiIdWidthMaster ),
.AXI_USER_WIDTH ( AxiUserWidth )
) slave[NBSlave-1:0]();
AXI_BUS #(
.AXI_ADDR_WIDTH ( AxiAddrWidth ),
.AXI_DATA_WIDTH ( AxiDataWidth ),
.AXI_ID_WIDTH ( AxiIdWidthMaster ),
.AXI_USER_WIDTH ( AxiUserWidth )
) slave_slice[NBSlave-1:0]();
AXI_BUS #(
.AXI_ADDR_WIDTH ( AxiAddrWidth ),
.AXI_DATA_WIDTH ( AxiDataWidth ),
.AXI_ID_WIDTH ( AxiIdWidthSlaves ),
.AXI_USER_WIDTH ( AxiUserWidth )
) master[NBMaster-1:0]();
// disable test-enable
logic test_en;
logic ndmreset;
logic ndmreset_n;
logic debug_req;
logic clk;
logic rst_n;
// DDR
logic c0_ddr4_ui_clk;
logic c0_init_calib_complete; // left open
logic c0_ddr4_ui_clk_sync_rst;
logic addn_ui_clkout1;
logic [3:0] s_axi_awid;
logic [31:0] s_axi_awaddr;
logic [7:0] s_axi_awlen;
logic [2:0] s_axi_awsize;
logic [1:0] s_axi_awburst;
logic [0:0] s_axi_awlock;
logic [3:0] s_axi_awcache;
logic [2:0] s_axi_awprot;
logic [3:0] s_axi_awregion;
logic [3:0] s_axi_awqos;
logic s_axi_awvalid;
logic s_axi_awready;
logic [63:0] s_axi_wdata;
logic [7:0] s_axi_wstrb;
logic s_axi_wlast;
logic s_axi_wvalid;
logic s_axi_wready;
logic [3:0] s_axi_bid;
logic [1:0] s_axi_bresp;
logic s_axi_bvalid;
logic s_axi_bready;
logic [3:0] s_axi_arid;
logic [31:0] s_axi_araddr;
logic [7:0] s_axi_arlen;
logic [2:0] s_axi_arsize;
logic [1:0] s_axi_arburst;
logic [0:0] s_axi_arlock;
logic [3:0] s_axi_arcache;
logic [2:0] s_axi_arprot;
logic [3:0] s_axi_arregion;
logic [3:0] s_axi_arqos;
logic s_axi_arvalid;
logic s_axi_arready;
logic [3:0] s_axi_rid;
logic [63:0] s_axi_rdata;
logic [1:0] s_axi_rresp;
logic s_axi_rlast;
logic s_axi_rvalid;
logic s_axi_rready;
logic [31:0] m_axi_awaddr;
logic [7:0] m_axi_awlen;
logic [2:0] m_axi_awsize;
logic [1:0] m_axi_awburst;
logic [0:0] m_axi_awlock;
logic [3:0] m_axi_awcache;
logic [2:0] m_axi_awprot;
logic [3:0] m_axi_awregion;
logic [3:0] m_axi_awqos;
logic m_axi_awvalid;
logic m_axi_awready;
logic [127:0] m_axi_wdata;
logic [15:0] m_axi_wstrb;
logic m_axi_wlast;
logic m_axi_wvalid;
logic m_axi_wready;
logic [1:0] m_axi_bresp;
logic m_axi_bvalid;
logic m_axi_bready;
logic [31:0] m_axi_araddr;
logic [7:0] m_axi_arlen;
logic [2:0] m_axi_arsize;
logic [1:0] m_axi_arburst;
logic [0:0] m_axi_arlock;
logic [3:0] m_axi_arcache;
logic [2:0] m_axi_arprot;
logic [3:0] m_axi_arregion;
logic [3:0] m_axi_arqos;
logic m_axi_arvalid;
logic m_axi_arready;
logic [127:0] m_axi_rdata;
logic [1:0] m_axi_rresp;
logic m_axi_rlast;
logic m_axi_rvalid;
logic m_axi_rready;
logic debug_req_valid;
logic debug_req_ready;
logic [6:0] debug_req_bits_addr;
logic [1:0] debug_req_bits_op;
logic [31:0] debug_req_bits_data;
logic debug_resp_valid;
logic debug_resp_ready;
logic [1:0] debug_resp_bits_resp;
logic [31:0] debug_resp_bits_data;
assign clk = addn_ui_clkout1;
assign rst_n = ~c0_ddr4_ui_clk_sync_rst;
assign test_en = 1'b0;
assign ndmreset_n = ~ndmreset ;
// Slice the AXI Masters (slave ports on the XBar)
for (genvar i = 0; i < NBSlave; i++) begin : slave_cut_gen
axi_cut #(
.ADDR_WIDTH ( AxiAddrWidth ),
.DATA_WIDTH ( AxiDataWidth ),
.ID_WIDTH ( AxiIdWidthMaster ),
.USER_WIDTH ( AxiUserWidth )
) i_axi_cut (
.clk_i ( clk ),
.rst_ni ( ndmreset_n ),
.in ( slave_slice[i] ),
.out ( slave[i] )
);
end
// ---------------
// AXI Xbar
// ---------------
axi_node_intf_wrap #(
// three ports from Ariane (instruction, data and bypass)
.NB_SLAVE ( NBSlave ),
.NB_MASTER ( NBMaster ), // debug unit, memory unit
.AXI_ADDR_WIDTH ( AxiAddrWidth ),
.AXI_DATA_WIDTH ( AxiDataWidth ),
.AXI_USER_WIDTH ( AxiUserWidth ),
.AXI_ID_WIDTH ( AxiIdWidthMaster )
) i_axi_xbar (
.clk ( clk ),
.rst_n ( ndmreset_n ),
.test_en_i ( test_en ),
.slave ( slave ),
.master ( master ),
.start_addr_i ( {64'h0, RomBase, CacheStartAddr} ),
.end_addr_i ( {64'hFFF, RomBase + 64'hFFFF, CacheStartAddr + 2**24} )
);
dm::dmi_req_t debug_req;;
dm::dmi_resp_t debug_resp;
// ---------------
// Debug Module
// ---------------
dmi_jtag i_dmi_jtag (
.clk_i ( clk ),
.rst_ni ( rst_n ),
.dmi_rst_no ( ), // keep open
.dmi_req_valid_o ( debug_req_valid ),
.dmi_req_ready_i ( debug_req_ready ),
.dmi_req_o ( debug_req ),
.dmi_resp_valid_i ( debug_resp_valid ),
.dmi_resp_ready_o ( debug_resp_ready ),
.dmi_resp_i ( debug_resp ),
.tck_i ( tck ),
.tms_i ( tms ),
.trst_ni ( trst_n ),
.td_i ( tdi ),
.td_o ( tdo ),
.tdo_oe_o ( )
);
// debug module
dm_top #(
// current implementation only supports 1 hart
.NrHarts ( 1 ),
.AxiIdWidth ( AxiIdWidthSlaves ),
.AxiAddrWidth ( AxiAddrWidth ),
.AxiDataWidth ( AxiDataWidth ),
.AxiUserWidth ( AxiUserWidth )
) i_dm_top (
.clk_i ( clk ),
.rst_ni ( rst_n ), // PoR
.testmode_i ( test_en ),
.ndmreset_o ( ndmreset ),
.dmactive_o ( ), // active debug session
.debug_req_o ( debug_req ),
.unavailable_i ( '0 ),
.axi_master ( slave_slice[3] ),
.axi_slave ( master[2] ),
.dmi_rst_ni ( rst_n ),
.dmi_req_valid_i ( debug_req_valid ),
.dmi_req_ready_o ( debug_req_ready ),
.dmi_req_i ( debug_req ),
.dmi_resp_valid_o ( debug_resp_valid ),
.dmi_resp_ready_i ( debug_resp_ready ),
.dmi_resp_o ( debug_resp )
);
// ---------------
// Core
// ---------------
ariane #(
.CACHE_START_ADDR ( CacheStartAddr ),
.AXI_ID_WIDTH ( AxiIdWidthMaster ),
.AXI_USER_WIDTH ( AxiUserWidth )
) i_ariane (
.clk_i ( clk ),
.rst_ni ( ndmreset_n ),
.boot_addr_i ( RomBase ), // start fetching from ROM
.core_id_i ( '0 ),
.cluster_id_i ( '0 ),
.irq_i ( '0 ),
.ipi_i ( '0 ),
.time_irq_i ( '0 ),
.debug_req_i ( debug_req ),
.data_if ( slave_slice[2] ),
.bypass_if ( slave_slice[1] ),
.instr_if ( slave_slice[0] )
);
// ---------------
// ROM
// ---------------
logic rom_req;
logic [AxiAddrWidth-1:0] rom_addr;
logic [AxiDataWidth-1:0] rom_rdata;
axi2mem #(
.AXI_ID_WIDTH ( AxiIdWidthSlaves ),
.AXI_ADDR_WIDTH ( AxiAddrWidth ),
.AXI_DATA_WIDTH ( AxiDataWidth ),
.AXI_USER_WIDTH ( AxiUserWidth )
) i_axi2rom (
.clk_i ( clk ),
.rst_ni ( ndmreset_n ),
.slave ( master[1] ),
.req_o ( rom_req ),
.we_o ( ),
.addr_o ( rom_addr ),
.be_o ( ),
.data_o ( ),
.data_i ( rom_rdata )
);
bootrom i_bootrom (
.clk_i ( clk ),
.req_i ( rom_req ),
.addr_i ( rom_addr ),
.rdata_o ( rom_rdata )
);
// DDR 4 Subsystem
axi_clock_converter_0 axi_clock_converter (
.s_axi_aclk(clk),
.s_axi_aresetn(ndmreset_n),
.s_axi_awid(master[0].aw_id),
.s_axi_awaddr(master[0].aw_addr),
.s_axi_awlen(master[0].aw_len),
.s_axi_awsize(master[0].aw_size),
.s_axi_awburst(master[0].aw_burst),
.s_axi_awlock(master[0].aw_lock),
.s_axi_awcache(master[0].aw_cache),
.s_axi_awprot(master[0].aw_prot),
.s_axi_awregion(master[0].aw_region),
.s_axi_awqos(master[0].aw_qos),
.s_axi_awvalid(master[0].aw_valid),
.s_axi_awready(master[0].aw_ready),
.s_axi_wdata(master[0].w_data),
.s_axi_wstrb(master[0].w_strb),
.s_axi_wlast(master[0].w_last),
.s_axi_wvalid(master[0].w_valid),
.s_axi_wready(master[0].w_ready),
.s_axi_bid(master[0].b_id),
.s_axi_bresp(master[0].b_resp),
.s_axi_bvalid(master[0].b_valid),
.s_axi_bready(master[0].b_ready),
.s_axi_arid(master[0].ar_id),
.s_axi_araddr(master[0].ar_addr[31:0]),
.s_axi_arlen(master[0].ar_len),
.s_axi_arsize(master[0].ar_size),
.s_axi_arburst(master[0].ar_burst),
.s_axi_arlock(master[0].ar_lock),
.s_axi_arcache(master[0].ar_cache),
.s_axi_arprot(master[0].ar_prot),
.s_axi_arregion(master[0].ar_region),
.s_axi_arqos(master[0].ar_qos),
.s_axi_arvalid(master[0].ar_valid),
.s_axi_arready(master[0].ar_ready),
.s_axi_rid(master[0].r_id),
.s_axi_rdata(master[0].r_data),
.s_axi_rresp(master[0].r_resp),
.s_axi_rlast(master[0].r_last),
.s_axi_rvalid(master[0].r_valid),
.s_axi_rready(master[0].r_ready),
// to size converter
.m_axi_aclk(c0_ddr4_ui_clk),
.m_axi_aresetn(ndmreset_n),
.m_axi_awid(s_axi_awid),
.m_axi_awaddr(s_axi_awaddr),
.m_axi_awlen(s_axi_awlen),
.m_axi_awsize(s_axi_awsize),
.m_axi_awburst(s_axi_awburst),
.m_axi_awlock(s_axi_awlock),
.m_axi_awcache(s_axi_awcache),
.m_axi_awprot(s_axi_awprot),
.m_axi_awregion(s_axi_awregion),
.m_axi_awqos(s_axi_awqos),
.m_axi_awvalid(s_axi_awvalid),
.m_axi_awready(s_axi_awready),
.m_axi_wdata(s_axi_wdata),
.m_axi_wstrb(s_axi_wstrb),
.m_axi_wlast(s_axi_wlast),
.m_axi_wvalid(s_axi_wvalid),
.m_axi_wready(s_axi_wready),
.m_axi_bid(s_axi_bid),
.m_axi_bresp(s_axi_bresp),
.m_axi_bvalid(s_axi_bvalid),
.m_axi_bready(s_axi_bready),
.m_axi_arid(s_axi_arid),
.m_axi_araddr(s_axi_araddr),
.m_axi_arlen(s_axi_arlen),
.m_axi_arsize(s_axi_arsize),
.m_axi_arburst(s_axi_arburst),
.m_axi_arlock(s_axi_arlock),
.m_axi_arcache(s_axi_arcache),
.m_axi_arprot(s_axi_arprot),
.m_axi_arregion(s_axi_arregion),
.m_axi_arqos(s_axi_arqos),
.m_axi_arvalid(s_axi_arvalid),
.m_axi_arready(s_axi_arready),
.m_axi_rid(s_axi_rid),
.m_axi_rdata(s_axi_rdata),
.m_axi_rresp(s_axi_rresp),
.m_axi_rlast(s_axi_rlast),
.m_axi_rvalid(s_axi_rvalid),
.m_axi_rready(s_axi_rready)
);
axi_dwidth_converter_0 axi_size_converter (
.s_axi_aclk(c0_ddr4_ui_clk),
.s_axi_aresetn(ndmreset_n),
.s_axi_awid,
.s_axi_awaddr,
.s_axi_awlen,
.s_axi_awsize,
.s_axi_awburst,
.s_axi_awlock,
.s_axi_awcache,
.s_axi_awprot,
.s_axi_awregion,
.s_axi_awqos,
.s_axi_awvalid,
.s_axi_awready,
.s_axi_wdata,
.s_axi_wstrb,
.s_axi_wlast,
.s_axi_wvalid,
.s_axi_wready,
.s_axi_bid,
.s_axi_bresp,
.s_axi_bvalid,
.s_axi_bready,
.s_axi_arid,
.s_axi_araddr,
.s_axi_arlen,
.s_axi_arsize,
.s_axi_arburst,
.s_axi_arlock,
.s_axi_arcache,
.s_axi_arprot,
.s_axi_arregion,
.s_axi_arqos,
.s_axi_arvalid,
.s_axi_arready,
.s_axi_rid,
.s_axi_rdata,
.s_axi_rresp,
.s_axi_rlast,
.s_axi_rvalid,
.s_axi_rready,
.m_axi_awaddr,
.m_axi_awlen,
.m_axi_awsize,
.m_axi_awburst,
.m_axi_awlock,
.m_axi_awcache,
.m_axi_awprot,
.m_axi_awregion,
.m_axi_awqos,
.m_axi_awvalid,
.m_axi_awready,
.m_axi_wdata,
.m_axi_wstrb,
.m_axi_wlast,
.m_axi_wvalid,
.m_axi_wready,
.m_axi_bresp,
.m_axi_bvalid,
.m_axi_bready,
.m_axi_araddr,
.m_axi_arlen,
.m_axi_arsize,
.m_axi_arburst,
.m_axi_arlock,
.m_axi_arcache,
.m_axi_arprot,
.m_axi_arregion,
.m_axi_arqos,
.m_axi_arvalid,
.m_axi_arready,
.m_axi_rdata,
.m_axi_rresp,
.m_axi_rlast,
.m_axi_rvalid,
.m_axi_rready
);
ddr4_0 ddr_i (
.sys_rst, // input
.c0_sys_clk_p,
.c0_sys_clk_n,
.c0_ddr4_act_n,
.c0_ddr4_adr,
.c0_ddr4_ba,
.c0_ddr4_bg,
.c0_ddr4_cke,
.c0_ddr4_odt,
.c0_ddr4_cs_n,
.c0_ddr4_ck_t,
.c0_ddr4_ck_c,
.c0_ddr4_reset_n,
.c0_ddr4_dm_dbi_n,
.c0_ddr4_dq,
.c0_ddr4_dqs_c,
.c0_ddr4_dqs_t,
.c0_init_calib_complete,
.c0_ddr4_ui_clk, // 1/4 of PHY clock, 300/4 = 75 MHz
.c0_ddr4_ui_clk_sync_rst,
.addn_ui_clkout1,
.dbg_clk(), // output
.c0_ddr4_aresetn(ndmreset_n),
.c0_ddr4_s_axi_awid('0),
.c0_ddr4_s_axi_awaddr(m_axi_awaddr),
.c0_ddr4_s_axi_awlen(m_axi_awlen),
.c0_ddr4_s_axi_awsize(m_axi_awsize),
.c0_ddr4_s_axi_awburst(m_axi_awburst),
.c0_ddr4_s_axi_awlock(m_axi_awlock),
.c0_ddr4_s_axi_awcache(m_axi_awcache),
.c0_ddr4_s_axi_awprot(m_axi_awprot),
.c0_ddr4_s_axi_awqos(m_axi_awqos),
.c0_ddr4_s_axi_awvalid(m_axi_awvalid),
.c0_ddr4_s_axi_awready(m_axi_awready),
.c0_ddr4_s_axi_wdata(m_axi_wdata),
.c0_ddr4_s_axi_wstrb(m_axi_wstrb),
.c0_ddr4_s_axi_wlast(m_axi_wlast),
.c0_ddr4_s_axi_wvalid(m_axi_wvalid),
.c0_ddr4_s_axi_wready(m_axi_wready),
.c0_ddr4_s_axi_bready(m_axi_bready),
.c0_ddr4_s_axi_bid(),
.c0_ddr4_s_axi_bresp(m_axi_bresp),
.c0_ddr4_s_axi_bvalid(m_axi_bvalid),
.c0_ddr4_s_axi_arid('0),
.c0_ddr4_s_axi_araddr(m_axi_araddr),
.c0_ddr4_s_axi_arlen(m_axi_arlen),
.c0_ddr4_s_axi_arsize(m_axi_arsize),
.c0_ddr4_s_axi_arburst(m_axi_arburst),
.c0_ddr4_s_axi_arlock(m_axi_arlock),
.c0_ddr4_s_axi_arcache(m_axi_arcache),
.c0_ddr4_s_axi_arprot(m_axi_arprot),
.c0_ddr4_s_axi_arqos(m_axi_arqos),
.c0_ddr4_s_axi_arvalid(m_axi_arvalid),
.c0_ddr4_s_axi_arready(m_axi_arready),
.c0_ddr4_s_axi_rready(m_axi_rready),
.c0_ddr4_s_axi_rid(),
.c0_ddr4_s_axi_rdata(m_axi_rdata),
.c0_ddr4_s_axi_rresp(m_axi_rresp),
.c0_ddr4_s_axi_rlast(m_axi_rlast),
.c0_ddr4_s_axi_rvalid(m_axi_rvalid),
.dbg_bus()
);
endmodule

View file

@ -1,128 +0,0 @@
// Copyright 2015 - 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.
//
////////////////////////////////////////////////////////////////////////////////
// Only general functions and definitions are defined here //
// These functions are not intended to be modified //
////////////////////////////////////////////////////////////////////////////////
interface AXI_BUS
#(
parameter AXI_ADDR_WIDTH = 64,
parameter AXI_DATA_WIDTH = 64,
parameter AXI_ID_WIDTH = 10,
parameter AXI_USER_WIDTH = 6
);
localparam AXI_STRB_WIDTH = AXI_DATA_WIDTH/8;
logic [AXI_ADDR_WIDTH-1:0] aw_addr;
logic [2:0] aw_prot;
logic [3:0] aw_region;
logic [7:0] aw_len;
logic [2:0] aw_size;
logic [1:0] aw_burst;
logic aw_lock;
logic [3:0] aw_cache;
logic [3:0] aw_qos;
logic [AXI_ID_WIDTH-1:0] aw_id;
logic [AXI_USER_WIDTH-1:0] aw_user;
logic aw_ready;
logic aw_valid;
logic [AXI_ADDR_WIDTH-1:0] ar_addr;
logic [2:0] ar_prot;
logic [3:0] ar_region;
logic [7:0] ar_len;
logic [2:0] ar_size;
logic [1:0] ar_burst;
logic ar_lock;
logic [3:0] ar_cache;
logic [3:0] ar_qos;
logic [AXI_ID_WIDTH-1:0] ar_id;
logic [AXI_USER_WIDTH-1:0] ar_user;
logic ar_ready;
logic ar_valid;
logic w_valid;
logic [AXI_DATA_WIDTH-1:0] w_data;
logic [AXI_STRB_WIDTH-1:0] w_strb;
logic [AXI_USER_WIDTH-1:0] w_user;
logic w_last;
logic w_ready;
logic [AXI_DATA_WIDTH-1:0] r_data;
logic [1:0] r_resp;
logic r_last;
logic [AXI_ID_WIDTH-1:0] r_id;
logic [AXI_USER_WIDTH-1:0] r_user;
logic r_ready;
logic r_valid;
logic [1:0] b_resp;
logic [AXI_ID_WIDTH-1:0] b_id;
logic [AXI_USER_WIDTH-1:0] b_user;
logic b_ready;
logic b_valid;
// Master Side
//***************************************
modport Master
(
output aw_valid, output aw_addr, output aw_prot, output aw_region,
output aw_len, output aw_size, output aw_burst, output aw_lock,
output aw_cache, output aw_qos, output aw_id, output aw_user,
input aw_ready,
output ar_valid, output ar_addr, output ar_prot, output ar_region,
output ar_len, output ar_size, output ar_burst, output ar_lock,
output ar_cache, output ar_qos, output ar_id, output ar_user,
input ar_ready,
output w_valid, output w_data, output w_strb, output w_user, output w_last,
input w_ready,
input r_valid, input r_data, input r_resp, input r_last, input r_id, input r_user,
output r_ready,
input b_valid, input b_resp, input b_id, input b_user,
output b_ready
);
// Slave Side
//***************************************
modport Slave
(
input aw_valid, input aw_addr, input aw_prot, input aw_region,
input aw_len, input aw_size, input aw_burst, input aw_lock,
input aw_cache, input aw_qos, input aw_id, input aw_user,
output aw_ready,
input ar_valid, input ar_addr, input ar_prot, input ar_region,
input ar_len, input ar_size, input ar_burst, input ar_lock,
input ar_cache, input ar_qos, input ar_id, input ar_user,
output ar_ready,
input w_valid, input w_data, input w_strb, input w_user, input w_last,
output w_ready,
output r_valid, output r_data, output r_resp, output r_last, output r_id, output r_user,
input r_ready,
output b_valid, output b_resp, output b_id, output b_user,
input b_ready
);
endinterface

321
include/axi_intf.sv Normal file
View file

@ -0,0 +1,321 @@
// Copyright (c) 2014-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.
//
// Fabian Schuiki <fschuiki@iis.ee.ethz.ch>
//
// This file defines the interfaces we support.
import axi_pkg::*;
/// An AXI4 interface.
interface AXI_BUS #(
parameter AXI_ADDR_WIDTH = -1,
parameter AXI_DATA_WIDTH = -1,
parameter AXI_ID_WIDTH = -1,
parameter AXI_USER_WIDTH = -1
);
localparam AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8;
typedef logic [AXI_ID_WIDTH-1:0] id_t;
typedef logic [AXI_ADDR_WIDTH-1:0] addr_t;
typedef logic [AXI_DATA_WIDTH-1:0] data_t;
typedef logic [AXI_STRB_WIDTH-1:0] strb_t;
typedef logic [AXI_USER_WIDTH-1:0] user_t;
id_t aw_id;
addr_t aw_addr;
logic [7:0] aw_len;
logic [2:0] aw_size;
burst_t aw_burst;
logic aw_lock;
cache_t aw_cache;
prot_t aw_prot;
qos_t aw_qos;
region_t aw_region;
user_t aw_user;
logic aw_valid;
logic aw_ready;
data_t w_data;
strb_t w_strb;
logic w_last;
user_t w_user;
logic w_valid;
logic w_ready;
id_t b_id;
resp_t b_resp;
user_t b_user;
logic b_valid;
logic b_ready;
id_t ar_id;
addr_t ar_addr;
logic [7:0] ar_len;
logic [2:0] ar_size;
burst_t ar_burst;
logic ar_lock;
cache_t ar_cache;
prot_t ar_prot;
qos_t ar_qos;
region_t ar_region;
user_t ar_user;
logic ar_valid;
logic ar_ready;
id_t r_id;
data_t r_data;
resp_t r_resp;
logic r_last;
user_t r_user;
logic r_valid;
logic r_ready;
modport Master (
output aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_user, aw_valid, input aw_ready,
output w_data, w_strb, w_last, w_user, w_valid, input w_ready,
input b_id, b_resp, b_user, b_valid, output b_ready,
output ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_valid, input ar_ready,
input r_id, r_data, r_resp, r_last, r_user, r_valid, output r_ready
);
modport Slave (
input aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_user, aw_valid, output aw_ready,
input w_data, w_strb, w_last, w_user, w_valid, output w_ready,
output b_id, b_resp, b_user, b_valid, input b_ready,
input ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_valid, output ar_ready,
output r_id, r_data, r_resp, r_last, r_user, r_valid, input r_ready
);
/// The interface as an output (issuing requests, initiator, master).
modport out (
output aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_user, aw_valid, input aw_ready,
output w_data, w_strb, w_last, w_user, w_valid, input w_ready,
input b_id, b_resp, b_user, b_valid, output b_ready,
output ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_valid, input ar_ready,
input r_id, r_data, r_resp, r_last, r_user, r_valid, output r_ready
);
/// The interface as an input (accepting requests, target, slave).
modport in (
input aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_user, aw_valid, output aw_ready,
input w_data, w_strb, w_last, w_user, w_valid, output w_ready,
output b_id, b_resp, b_user, b_valid, input b_ready,
input ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_valid, output ar_ready,
output r_id, r_data, r_resp, r_last, r_user, r_valid, input r_ready
);
endinterface
/// An asynchronous AXI4 interface.
interface AXI_BUS_ASYNC
#(
parameter AXI_ADDR_WIDTH = -1,
parameter AXI_DATA_WIDTH = -1,
parameter AXI_ID_WIDTH = -1,
parameter AXI_USER_WIDTH = -1,
parameter BUFFER_WIDTH = -1
);
localparam AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8;
logic [AXI_ID_WIDTH-1:0] aw_id;
logic [AXI_ADDR_WIDTH-1:0] aw_addr;
logic [7:0] aw_len;
logic [2:0] aw_size;
logic [1:0] aw_burst;
logic aw_lock;
logic [3:0] aw_cache;
logic [2:0] aw_prot;
logic [3:0] aw_qos;
logic [3:0] aw_region;
logic [AXI_USER_WIDTH-1:0] aw_user;
logic [BUFFER_WIDTH-1:0] aw_writetoken;
logic [BUFFER_WIDTH-1:0] aw_readpointer;
logic [AXI_DATA_WIDTH-1:0] w_data;
logic [AXI_STRB_WIDTH-1:0] w_strb;
logic w_last;
logic [AXI_USER_WIDTH-1:0] w_user;
logic [BUFFER_WIDTH-1:0] w_writetoken;
logic [BUFFER_WIDTH-1:0] w_readpointer;
logic [AXI_ID_WIDTH-1:0] b_id;
logic [1:0] b_resp;
logic [AXI_USER_WIDTH-1:0] b_user;
logic [BUFFER_WIDTH-1:0] b_writetoken;
logic [BUFFER_WIDTH-1:0] b_readpointer;
logic [AXI_ID_WIDTH-1:0] ar_id;
logic [AXI_ADDR_WIDTH-1:0] ar_addr;
logic [7:0] ar_len;
logic [2:0] ar_size;
logic [1:0] ar_burst;
logic ar_lock;
logic [3:0] ar_cache;
logic [2:0] ar_prot;
logic [3:0] ar_qos;
logic [3:0] ar_region;
logic [AXI_USER_WIDTH-1:0] ar_user;
logic [BUFFER_WIDTH-1:0] ar_writetoken;
logic [BUFFER_WIDTH-1:0] ar_readpointer;
logic [AXI_ID_WIDTH-1:0] r_id;
logic [AXI_DATA_WIDTH-1:0] r_data;
logic [1:0] r_resp;
logic r_last;
logic [AXI_USER_WIDTH-1:0] r_user;
logic [BUFFER_WIDTH-1:0] r_writetoken;
logic [BUFFER_WIDTH-1:0] r_readpointer;
modport Master (
output aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_user, aw_writetoken, input aw_readpointer,
output w_data, w_strb, w_last, w_user, w_writetoken, input w_readpointer,
input b_id, b_resp, b_user, b_writetoken, output b_readpointer,
output ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_writetoken, input ar_readpointer,
input r_id, r_data, r_resp, r_last, r_user, r_writetoken, output r_readpointer
);
modport Slave (
input aw_id, aw_addr, aw_len, aw_size, aw_burst, aw_lock, aw_cache, aw_prot, aw_qos, aw_region, aw_user, aw_writetoken, output aw_readpointer,
input w_data, w_strb, w_last, w_user, w_writetoken, output w_readpointer,
output b_id, b_resp, b_user, b_writetoken, input b_readpointer,
input ar_id, ar_addr, ar_len, ar_size, ar_burst, ar_lock, ar_cache, ar_prot, ar_qos, ar_region, ar_user, ar_writetoken, output ar_readpointer,
output r_id, r_data, r_resp, r_last, r_user, r_writetoken, input r_readpointer
);
endinterface
/// An AXI4-Lite interface.
interface AXI_LITE #(
parameter AXI_ADDR_WIDTH = -1,
parameter AXI_DATA_WIDTH = -1
);
localparam AXI_STRB_WIDTH = AXI_DATA_WIDTH / 8;
typedef logic [AXI_ADDR_WIDTH-1:0] addr_t;
typedef logic [AXI_DATA_WIDTH-1:0] data_t;
typedef logic [AXI_STRB_WIDTH-1:0] strb_t;
// AW channel
addr_t aw_addr;
logic aw_valid;
logic aw_ready;
data_t w_data;
strb_t w_strb;
logic w_valid;
logic w_ready;
resp_t b_resp;
logic b_valid;
logic b_ready;
addr_t ar_addr;
logic ar_valid;
logic ar_ready;
data_t r_data;
resp_t r_resp;
logic r_valid;
logic r_ready;
modport Master (
output aw_addr, aw_valid, input aw_ready,
output w_data, w_strb, w_valid, input w_ready,
input b_resp, b_valid, output b_ready,
output ar_addr, ar_valid, input ar_ready,
input r_data, r_resp, r_valid, output r_ready
);
modport Slave (
input aw_addr, aw_valid, output aw_ready,
input w_data, w_strb, w_valid, output w_ready,
output b_resp, b_valid, input b_ready,
input ar_addr, ar_valid, output ar_ready,
output r_data, r_resp, r_valid, input r_ready
);
/// The interface as an output (issuing requests, initiator, master).
modport out (
output aw_addr, aw_valid, input aw_ready,
output w_data, w_strb, w_valid, input w_ready,
input b_resp, b_valid, output b_ready,
output ar_addr, ar_valid, input ar_ready,
input r_data, r_resp, r_valid, output r_ready
);
/// The interface as an input (accepting requests, target, slave).
modport in (
input aw_addr, aw_valid, output aw_ready,
input w_data, w_strb, w_valid, output w_ready,
output b_resp, b_valid, input b_ready,
input ar_addr, ar_valid, output ar_ready,
output r_data, r_resp, r_valid, input r_ready
);
endinterface
/// An AXI routing table.
///
/// For each slave, multiple rules can be defined. Each rule consists of an
/// address mask and a base. Addresses are masked and then compared against the
/// base to decide where transfers need to go.
interface AXI_ROUTING_RULES #(
/// The address width.
parameter int AXI_ADDR_WIDTH = -1,
/// The number of slaves in the routing table.
parameter int NUM_SLAVE = -1,
/// The number of rules in the routing table.
parameter int NUM_RULES = -1
);
struct packed {
logic enabled;
logic [AXI_ADDR_WIDTH-1:0] mask;
logic [AXI_ADDR_WIDTH-1:0] base;
} [NUM_RULES-1:0] rules [NUM_SLAVE];
modport xbar(input rules);
modport cfg(output rules);
endinterface
/// An AXI arbitration interface.
interface AXI_ARBITRATION #(
/// The number of requestors.
parameter int NUM_REQ = -1
);
// Incoming requests.
logic [NUM_REQ-1:0] in_req;
logic [NUM_REQ-1:0] in_ack;
// Outgoing request.
logic out_req;
logic out_ack;
logic [$clog2(NUM_REQ)-1:0] out_sel;
// The arbiter side of the interface.
modport arb(input in_req, out_ack, output out_req, out_sel, in_ack);
// The requestor side of the interface.
modport req(output in_req, out_ack, input out_req, out_sel, in_ack);
endinterface

View file

@ -32,7 +32,6 @@ module ariane #(
)(
input logic clk_i,
input logic rst_ni,
input logic test_en_i, // enable all clock gates for testing
// Core ID, Cluster ID and boot address are considered more or less static
input logic [63:0] boot_addr_i, // reset boot address
input logic [ 3:0] core_id_i, // core id in a multicore environment (reflected in a CSR)

View file

@ -131,6 +131,8 @@ module axi_adapter #(
axi.w_valid = 1'b1;
// its a single write
if (type_i == SINGLE_REQ) begin
// only a single write so the data is already the last one
axi.w_last = 1'b1;
// single req can be granted here
gnt_o = axi.aw_ready & axi.w_ready;
gnt_id_o = id_i;

@ -1 +0,0 @@
Subproject commit f8886bd3f2d4967aaccff15b67bf1f9e1a0e3453

View file

@ -6,6 +6,6 @@ The CLINT plugs into an existing AXI Bus with an AXI 4 Lite interface. The IP mi
| Address | Description | Note |
|-------------------|-------------|------------------------------------------------|
| `BASE` + `0xo` | msip | Machine mode software interrupt (IPI) |
| `BASE` + `0x0` | msip | Machine mode software interrupt (IPI) |
| `BASE` + `0x4000` | mtimecmp | Machine mode timer compare register for Hart 0 |
| `BASE` + `0xBFF8` | mtime | Timer register |

View file

@ -27,9 +27,7 @@ module clint #(
AXI_BUS.Slave slave,
input logic halted_i, // cores are halted, also halt timer
input logic rtc_i, // Real-time clock in (usually 32.768 kHz)
output logic [63:0] time_o, // Global Time out, this is the time-base of the whole SoC
output logic [NR_CORES-1:0] timer_irq_o, // Timer interrupts
output logic [NR_CORES-1:0] ipi_o // software interrupt (a.k.a inter-process-interrupt)
);
@ -54,9 +52,6 @@ module clint #(
// increase the timer
logic increase_timer;
// directly output the mtime_q register - this needs synchronization (but in the core).
assign time_o = mtime_q;
// -----------------------------
// AXI Interface Logic
// -----------------------------
@ -82,7 +77,7 @@ module clint #(
mtimecmp_n = mtimecmp_q;
msip_n = msip_q;
// RTC says we should increase the timer
if (increase_timer && !halted_i)
if (increase_timer)
mtime_n = mtime_q + 1;
// written from APB bus - gets priority

@ -1 +1 @@
Subproject commit 4ddb77914eed42f7980a45c16f58fd82dd8b2292
Subproject commit 9278bc769f3efd006864a7ef7721f2796ed968e6

View file

@ -24,14 +24,11 @@ module dm_csrs #(
input logic dmi_rst_ni, // Debug Module Interface reset, active-low
input logic dmi_req_valid_i,
output logic dmi_req_ready_o,
input logic [ 6:0] dmi_req_bits_addr_i,
input logic [ 1:0] dmi_req_bits_op_i, // 0 = nop, 1 = read, 2 = write
input logic [31:0] dmi_req_bits_data_i,
input dm::dmi_req_t dmi_req_i,
// every request needs a response one cycle later
output logic dmi_resp_valid_o,
input logic dmi_resp_ready_i,
output logic [ 1:0] dmi_resp_bits_resp_o,
output logic [31:0] dmi_resp_bits_data_o,
output dm::dmi_resp_t dmi_resp_o,
// global ctrl
output logic ndmreset_o, // non-debug module reset, active-high
output logic dmactive_o, // 1 -> debug-module is active, 0 -> synchronous re-set
@ -47,9 +44,9 @@ module dm_csrs #(
output logic cmd_valid_o, // debugger is writing to the command field
output dm::command_t cmd_o, // abstract command
input logic [NrHarts-1:0] cmderror_valid_i, // an error occured
input dm::cmderr_t [NrHarts-1:0] cmderror_i, // this error occured
input logic [NrHarts-1:0] cmdbusy_i, // cmd is currently busy executing
input logic cmderror_valid_i, // an error occured
input dm::cmderr_t cmderror_i, // this error occured
input logic cmdbusy_i, // cmd is currently busy executing
output logic [dm::ProgBufSize-1:0][31:0] progbuf_o, // to system bus
output logic [dm::DataCount-1:0][31:0] data_o,
@ -80,7 +77,7 @@ module dm_csrs #(
// the amount of bits we need to represent all harts
localparam HartSelLen = (NrHarts == 1) ? 1 : $clog2(NrHarts);
dm::dtm_op_t dtm_op;
assign dtm_op = dm::dtm_op_t'(dmi_req_bits_op_i);
assign dtm_op = dm::dtm_op_t'(dmi_req_i.op);
logic resp_queue_full;
logic resp_queue_empty;
@ -121,7 +118,7 @@ module dm_csrs #(
logic [NrHarts-1:0] selected_hart;
// a successful response returns zero
assign dmi_resp_bits_resp_o = dm::DTM_SUCCESS;
assign dmi_resp_o.resp = dm::DTM_SUCCESS;
assign dmi_resp_valid_o = ~resp_queue_empty;
assign dmi_req_ready_o = ~resp_queue_full;
assign resp_queue_push = dmi_req_valid_i & dmi_req_ready_o;
@ -171,7 +168,7 @@ module dm_csrs #(
abstractcs = '0;
abstractcs.datacount = dm::DataCount;
abstractcs.progbufsize = dm::ProgBufSize;
abstractcs.busy = cmdbusy_i[selected_hart];
abstractcs.busy = cmdbusy_i;
abstractcs.cmderr = cmderr_q;
// abstractautoexec
@ -197,14 +194,14 @@ module dm_csrs #(
// reads
if (dmi_req_ready_o && dmi_req_valid_i && dtm_op == dm::DTM_READ) begin
unique case ({1'b0, dmi_req_bits_addr_i}) inside
unique case ({1'b0, dmi_req_i.addr}) inside
[(dm::Data0):DataEnd]: begin
if (dm::DataCount > 0) begin
resp_queue_data = data_q[dmi_req_bits_addr_i[4:0]];
resp_queue_data = data_q[dmi_req_i.addr[4:0]];
end
if (!cmdbusy_i) begin
// check whether we need to re-execute the command (just give a cmd_valid)
cmd_valid_o = abstractauto_q.autoexecdata[dmi_req_bits_addr_i[3:0] - dm::Data0];
cmd_valid_o = abstractauto_q.autoexecdata[dmi_req_i.addr[3:0] - dm::Data0];
end
end
dm::DMControl: resp_queue_data = dmcontrol_q;
@ -215,10 +212,10 @@ module dm_csrs #(
// command is read-only
dm::Command: resp_queue_data = '0;
[(dm::ProgBuf0):ProgBufEnd]: begin
resp_queue_data = progbuf_q[dmi_req_bits_addr_i[4:0]];
resp_queue_data = progbuf_q[dmi_req_i.addr[4:0]];
if (!cmdbusy_i) begin
// check whether we need to re-execute the command (just give a cmd_valid)
cmd_valid_o = abstractauto_q.autoexecprogbuf[dmi_req_bits_addr_i[3:0]];
cmd_valid_o = abstractauto_q.autoexecprogbuf[dmi_req_i.addr[3:0]];
end
end
dm::HaltSum0: resp_queue_data = haltsum0;
@ -269,23 +266,23 @@ module dm_csrs #(
// write
if (dmi_req_ready_o && dmi_req_valid_i && dtm_op == dm::DTM_WRITE) begin
unique case (dm::dm_csr_t'({1'b0, dmi_req_bits_addr_i})) inside
unique case (dm::dm_csr_t'({1'b0, dmi_req_i.addr})) inside
[(dm::Data0):DataEnd]: begin
// attempts to write them while busy is set does not change their value
if (!cmdbusy_i && dm::DataCount > 0) begin
data_d[dmi_req_bits_addr_i[4:0]] = dmi_req_bits_data_i;
data_d[dmi_req_i.addr[4:0]] = dmi_req_i.data;
// check whether we need to re-execute the command (just give a cmd_valid)
cmd_valid_o = abstractauto_q.autoexecdata[dmi_req_bits_addr_i[3:0] - dm::Data0];
cmd_valid_o = abstractauto_q.autoexecdata[dmi_req_i.addr[3:0] - dm::Data0];
end
end
dm::DMControl: begin
automatic dm::dmcontrol_t dmcontrol;
dmcontrol = dm::dmcontrol_t'(dmi_req_bits_data_i);
dmcontrol = dm::dmcontrol_t'(dmi_req_i.data);
// clear the havreset of the selected hart
if (dmcontrol.ackhavereset) begin
havereset_d[selected_hart] = 1'b0;
end
dmcontrol_d = dmi_req_bits_data_i;
dmcontrol_d = dmi_req_i.data;
end
dm::DMStatus:; // write are ignored to R/O register
dm::Hartinfo:; // hartinfo is R/O
@ -296,7 +293,7 @@ module dm_csrs #(
// them. No abstract command is started until the value is
// reset to 0.
automatic dm::abstractcs_t a_abstractcs;
a_abstractcs = dm::abstractcs_t'(dmi_req_bits_data_i);
a_abstractcs = dm::abstractcs_t'(dmi_req_i.data);
// reads during abstract command execution are not allowed
if (!cmdbusy_i) begin
cmderr_d = dm::cmderr_t'(~a_abstractcs.cmderr & cmderr_q);
@ -309,7 +306,7 @@ module dm_csrs #(
// writes are ignored if a command is already busy
if (!cmdbusy_i) begin
cmd_valid_o = 1'b1;
command_d = dm::command_t'(dmi_req_bits_data_i);
command_d = dm::command_t'(dmi_req_i.data);
// if there was an attempted to write during a busy execution
// and the cmderror field is zero set the busy error
end else if (cmderr_q == dm::CmdErrNone) begin
@ -319,7 +316,7 @@ module dm_csrs #(
dm::AbstractAuto: begin
// this field can only be written legally when there is no command executing
if (!cmdbusy_i) begin
abstractauto_d = {dmi_req_bits_data_i[31:16], 4'b0, dmi_req_bits_data_i[11:0]};
abstractauto_d = {dmi_req_i.data[31:16], 4'b0, dmi_req_i.data[11:0]};
end else if (cmderr_q == dm::CmdErrNone) begin
cmderr_d = dm::CmdErrBusy;
end
@ -327,10 +324,10 @@ module dm_csrs #(
[(dm::ProgBuf0):ProgBufEnd]: begin
// attempts to write them while busy is set does not change their value
if (!cmdbusy_i) begin
progbuf_d[dmi_req_bits_addr_i[4:0]] = dmi_req_bits_data_i;
progbuf_d[dmi_req_i.addr[4:0]] = dmi_req_i.data;
// check whether we need to re-execute the command (just give a cmd_valid)
// this should probably throw an error if executed during another command was busy
cmd_valid_o = abstractauto_q.autoexecprogbuf[dmi_req_bits_addr_i[3:0]];
cmd_valid_o = abstractauto_q.autoexecprogbuf[dmi_req_i.addr[3:0]];
end
end
dm::SBCS: begin
@ -338,7 +335,7 @@ module dm_csrs #(
if (sbbusy_i) begin
sbcs_d.sbbusyerror = 1'b1;
end begin
automatic dm::sbcs_t sbcs = dm::sbcs_t'(dmi_req_bits_data_i);
automatic dm::sbcs_t sbcs = dm::sbcs_t'(dmi_req_i.data);
sbcs_d = sbcs;
// R/W1C
sbcs_d.sbbusyerror = sbcs_q.sbbusyerror & (~sbcs.sbbusyerror);
@ -350,7 +347,7 @@ module dm_csrs #(
if (sbbusy_i) begin
sbcs_d.sbbusyerror = 1'b1;
end begin
sbaddr_d[31:0] = dmi_req_bits_data_i;
sbaddr_d[31:0] = dmi_req_i.data;
sbaddress_write_valid_o = (sbcs_q.sberror == '0);
end
end
@ -359,7 +356,7 @@ module dm_csrs #(
if (sbbusy_i) begin
sbcs_d.sbbusyerror = 1'b1;
end begin
sbaddr_d[63:32] = dmi_req_bits_data_i;
sbaddr_d[63:32] = dmi_req_i.data;
end
end
dm::SBData0: begin
@ -367,7 +364,7 @@ module dm_csrs #(
if (sbbusy_i) begin
sbcs_d.sbbusyerror = 1'b1;
end begin
sbdata_d[31:0] = dmi_req_bits_data_i;
sbdata_d[31:0] = dmi_req_i.data;
sbdata_write_valid_o = (sbcs_q.sberror == '0);
end
end
@ -376,15 +373,15 @@ module dm_csrs #(
if (sbbusy_i) begin
sbcs_d.sbbusyerror = 1'b1;
end begin
sbdata_d[63:32] = dmi_req_bits_data_i;
sbdata_d[63:32] = dmi_req_i.data;
end
end
default:;
endcase
end
// hart threw a command error and has precedence over bus writes
if (cmderror_valid_i[selected_hart]) begin
cmderr_d = cmderror_i[selected_hart];
if (cmderror_valid_i) begin
cmderr_d = cmderror_i;
end
// update data registers
@ -448,7 +445,7 @@ module dm_csrs #(
assign data_o = data_q;
assign resp_queue_pop = dmi_resp_ready_i & ~resp_queue_empty;
// response FIFO
fifo_v2 #(
.dtype ( logic [31:0] ),
@ -464,7 +461,7 @@ module dm_csrs #(
.alm_empty_o ( ),
.data_i ( resp_queue_data ),
.push_i ( resp_queue_push ),
.data_o ( dmi_resp_bits_data_o ),
.data_o ( dmi_resp_o.data ),
.pop_i ( resp_queue_pop )
);

View file

@ -22,7 +22,7 @@ module dm_mem #(
input logic clk_i, // Clock
input logic dmactive_i, // debug module reset
output logic debug_req_o,
output logic [NrHarts-1:0] debug_req_o,
input logic [19:0] hartsel_i,
// from Ctrl and Status register
input logic [NrHarts-1:0] haltreq_i,

View file

@ -203,4 +203,15 @@ package dm;
localparam logic[1:0] DTM_SUCCESS = 2'h0;
typedef struct packed {
logic [6:0] addr;
dtm_op_t op;
logic [31:0] data;
} dmi_req_t;
typedef struct packed {
logic [31:0] data;
logic [1:0] resp;
} dmi_resp_t;
endpackage

View file

@ -38,14 +38,11 @@ module dm_top #(
input logic dmi_rst_ni,
input logic dmi_req_valid_i,
output logic dmi_req_ready_o,
input logic [ 6:0] dmi_req_bits_addr_i,
input logic [ 1:0] dmi_req_bits_op_i, // 0 = nop, 1 = read, 2 = write
input logic [31:0] dmi_req_bits_data_i,
input dm::dmi_req_t dmi_req_i,
output logic dmi_resp_valid_o,
input logic dmi_resp_ready_i,
output logic [ 1:0] dmi_resp_bits_resp_o,
output logic [31:0] dmi_resp_bits_data_o
output dm::dmi_resp_t dmi_resp_o
);
// Debug CSRs
@ -65,9 +62,9 @@ module dm_top #(
logic [63:0] wdata;
logic [63:0] rdata;
logic [NrHarts-1:0] cmderror_valid;
dm::cmderr_t [NrHarts-1:0] cmderror;
logic [NrHarts-1:0] cmdbusy;
logic cmderror_valid;
dm::cmderr_t cmderror;
logic cmdbusy;
logic [dm::ProgBufSize-1:0][31:0] progbuf;
logic [dm::DataCount-1:0][31:0] data_csrs_mem;
logic [dm::DataCount-1:0][31:0] data_mem_csrs;
@ -102,16 +99,13 @@ module dm_top #(
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.testmode_i ( testmode_i ),
.dmi_rst_ni ( dmi_rst_ni ),
.dmi_req_valid_i ( dmi_req_valid_i ),
.dmi_req_ready_o ( dmi_req_ready_o ),
.dmi_req_bits_addr_i ( dmi_req_bits_addr_i ),
.dmi_req_bits_op_i ( dmi_req_bits_op_i ),
.dmi_req_bits_data_i ( dmi_req_bits_data_i ),
.dmi_resp_valid_o ( dmi_resp_valid_o ),
.dmi_resp_ready_i ( dmi_resp_ready_i ),
.dmi_resp_bits_resp_o ( dmi_resp_bits_resp_o ),
.dmi_resp_bits_data_o ( dmi_resp_bits_data_o ),
.dmi_rst_ni,
.dmi_req_valid_i,
.dmi_req_ready_o,
.dmi_req_i,
.dmi_resp_valid_o,
.dmi_resp_ready_i,
.dmi_resp_o,
.ndmreset_o ( ndmreset_o ),
.dmactive_o ( dmactive_o ),
.hartsel_o ( hartsel ),

View file

@ -18,498 +18,55 @@
*/
module dmi_cdc (
// JTAG side (master side)
input logic tck_i,
input logic trst_ni,
input logic tck_i,
input logic trst_ni,
input logic mem_valid_i,
output logic mem_gnt_o,
input logic [6:0] mem_addr_i,
input logic mem_we_i,
input logic [31:0] mem_wdata_i,
output logic [31:0] mem_rdata_o,
output logic mem_rvalid_o,
input dm::dmi_req_t jtag_dmi_req_i,
output logic jtag_dmi_ready_o,
input logic jtag_dmi_valid_i,
// Memory -> Slave side
input logic clk_i,
input logic rst_ni,
output dm::dmi_resp_t jtag_dmi_resp_o,
output logic jtag_dmi_valid_o,
input logic jtag_dmi_ready_i,
output logic dmi_req_valid_o,
input logic dmi_req_ready_i,
// core side (slave side)
input logic clk_i,
input logic rst_ni,
output logic [ 6:0] dmi_req_bits_addr_o,
output logic [ 1:0] dmi_req_bits_op_o,
output logic [31:0] dmi_req_bits_data_o,
output dm::dmi_req_t core_dmi_req_o,
output logic core_dmi_valid_o,
input logic core_dmi_ready_i,
input logic dmi_resp_valid_i,
output logic dmi_resp_ready_o,
input logic [ 1:0] dmi_resp_bits_resp_i,
input logic [31:0] dmi_resp_bits_data_i
);
input dm::dmi_resp_t core_dmi_resp_i,
output logic core_dmi_ready_o,
input logic core_dmi_valid_i
);
logic mem_we;
// we will always be ready to receive the request we made
assign dmi_resp_ready_o = 1'b1;
// very "cheap" protocol conversion
assign dmi_req_bits_op_o = (mem_we) ? dm::DTM_WRITE : dm::DTM_READ;
cdc_2phase #(.T(dm::dmi_req_t)) i_cdc_req (
.src_rst_ni ( trst_ni ),
.src_clk_i ( tck_i ),
.src_data_i ( jtag_dmi_req_i ),
.src_valid_i ( jtag_dmi_valid_i ),
.src_ready_o ( jtag_dmi_ready_o ),
localparam int unsigned AddrWidth = 7;
localparam int unsigned DataWidth = 32;
.dst_rst_ni ( rst_ni ),
.dst_clk_i ( clk_i ),
.dst_data_o ( core_dmi_req_o ),
.dst_valid_o ( core_dmi_valid_o ),
.dst_ready_i ( core_dmi_ready_i )
);
logic cdc_req_a;
logic cdc_ack_a;
logic [AddrWidth-1:0] cdc_addr_a;
logic cdc_we_a;
logic [DataWidth/8-1:0] cdc_be_a;
logic [DataWidth-1:0] cdc_wdata_a;
logic cdc_clear_a;
logic cdc_rreq_a;
logic cdc_rack_a;
logic [DataWidth-1:0] cdc_rdata_a;
logic cdc_rerror_a;
cdc_2phase #(.T(dm::dmi_resp_t)) i_cdc_resp (
.src_rst_ni ( rst_ni ),
.src_clk_i ( clk_i ),
.src_data_i ( core_dmi_resp_i ),
.src_valid_i ( core_dmi_valid_i ),
.src_ready_o ( core_dmi_ready_o ),
// lets re-use most of the debug facilities which are already in PULP
dmi_cdc_jtag #(
.ADDR_WIDTH (AddrWidth),
.DATA_WIDTH (DataWidth)
) i_dmi_cdc_jtag (
.tck_i,
.trst_ni,
.mem_req_i ( mem_valid_i ),
.mem_gnt_o,
.mem_addr_i,
.mem_we_i,
.mem_be_i ( '1 ),
.mem_wdata_i,
.mem_rdata_o,
.mem_rvalid_o,
// we are not managing any errors here
// a more elaborate implementation should probably handle this more gracefully
.mem_rerror_o ( ),
.mem_clear_i ( 1'b0 ),
.cdc_req_ao ( cdc_req_a ),
.cdc_ack_ai ( cdc_ack_a ),
.cdc_addr_ao ( cdc_addr_a ),
.cdc_we_ao ( cdc_we_a ),
.cdc_be_ao ( cdc_be_a ),
.cdc_wdata_ao ( cdc_wdata_a ),
.cdc_clear_ao ( cdc_clear_a ),
.cdc_rreq_ai ( cdc_rreq_a ),
.cdc_rack_ao ( cdc_rack_a ),
.cdc_rdata_ai ( cdc_rdata_a ),
.cdc_rerror_ai ( cdc_rerror_a )
);
dmi_cdc_mem #(
.ADDR_WIDTH (AddrWidth),
.DATA_WIDTH (DataWidth)
) i_dmi_cdc_mem (
.clk_i,
.rst_ni,
.mem_req_o ( dmi_req_valid_o ),
.mem_gnt_i ( dmi_req_ready_i ),
.mem_addr_o ( dmi_req_bits_addr_o ),
.mem_we_o ( mem_we ),
// don't care we always write whole words
.mem_be_o ( ),
.mem_wdata_o ( dmi_req_bits_data_o ),
.mem_rdata_i ( dmi_resp_bits_data_i ),
.mem_rvalid_i ( dmi_resp_valid_i ),
// don't care about clearing an error flag
// that is handled differently in the RISC-V implementation
.mem_rerror_i ( 1'b0 ),
.mem_clear_o ( ),
.cdc_req_ai ( cdc_req_a ),
.cdc_ack_ao ( cdc_ack_a ),
.cdc_addr_ai ( cdc_addr_a ),
.cdc_we_ai ( cdc_we_a ),
.cdc_be_ai ( cdc_be_a ),
.cdc_wdata_ai ( cdc_wdata_a ),
.cdc_clear_ai ( cdc_clear_a ),
.cdc_rreq_ao ( cdc_rreq_a ),
.cdc_rack_ai ( cdc_rack_a ),
.cdc_rdata_ao ( cdc_rdata_a ),
.cdc_rerror_ao ( cdc_rerror_a )
);
endmodule
module dmi_cdc_jtag #(
parameter int unsigned ADDR_WIDTH = 32,
parameter int unsigned DATA_WIDTH = 64
)(
// JTAG side
input logic tck_i,
input logic trst_ni,
input logic mem_req_i,
output logic mem_gnt_o,
input logic [ADDR_WIDTH-1:0] mem_addr_i,
input logic mem_we_i,
input logic [DATA_WIDTH/8-1:0] mem_be_i,
input logic [DATA_WIDTH-1:0] mem_wdata_i,
output logic [DATA_WIDTH-1:0] mem_rdata_o,
output logic mem_rvalid_o,
output logic mem_rerror_o,
input logic mem_clear_i,
// CDC side
output logic cdc_req_ao,
input logic cdc_ack_ai,
output logic [ADDR_WIDTH-1:0] cdc_addr_ao,
output logic cdc_we_ao,
output logic [DATA_WIDTH/8-1:0] cdc_be_ao,
output logic [DATA_WIDTH-1:0] cdc_wdata_ao,
output logic cdc_clear_ao,
input logic cdc_rreq_ai,
output logic cdc_rack_ao,
input logic [DATA_WIDTH-1:0] cdc_rdata_ai,
input logic cdc_rerror_ai
);
enum logic [1:0] { IDLE, WAIT_ACK_LOW, WAIT_ACK_HIGH, READY_ACK_LOW } req_state_p, req_state_n;
enum logic [0:0] { RIDLE, WAIT_REQ_LOW } resp_state_p, resp_state_n;
logic [ADDR_WIDTH-1:0] cdc_addr_p;
logic cdc_we_p;
logic [DATA_WIDTH/8-1:0] cdc_be_p;
logic [DATA_WIDTH-1:0] cdc_wdata_p;
logic cdc_clear_p;
logic cdc_ack;
logic cdc_rreq;
always_comb
begin
req_state_n = req_state_p;
mem_gnt_o = 1'b0;
cdc_req_ao = 1'b0;
unique case (req_state_p)
IDLE: begin
if (mem_req_i) begin
req_state_n = WAIT_ACK_HIGH;
mem_gnt_o = 1'b1;
end
end
WAIT_ACK_HIGH: begin
cdc_req_ao = 1'b1;
if (cdc_ack) begin
req_state_n = WAIT_ACK_LOW;
end
end
WAIT_ACK_LOW: begin
if (mem_req_i)
mem_gnt_o = 1'b1;
if (~cdc_ack) begin
if (mem_req_i)
req_state_n = WAIT_ACK_HIGH;
else
req_state_n = IDLE;
end else begin
if (mem_req_i)
req_state_n = READY_ACK_LOW;
end
end
READY_ACK_LOW: begin
if (~cdc_ack) begin
req_state_n = WAIT_ACK_HIGH;
end
end
default:; // make unique case happy during reset
endcase
end
always_comb
begin
resp_state_n = resp_state_p;
mem_rvalid_o = 1'b0;
cdc_rack_ao = 1'b0;
unique case (resp_state_p)
RIDLE: begin
if (cdc_rreq) begin
resp_state_n = WAIT_REQ_LOW;
mem_rvalid_o = 1'b1;
end
end
WAIT_REQ_LOW: begin
cdc_rack_ao = 1'b1;
if (~cdc_rreq) begin
resp_state_n = RIDLE;
end
end
default:; // make unique case happy during reset
endcase
end
always_ff @(posedge tck_i, negedge trst_ni)
begin
if (~trst_ni) begin
req_state_p <= IDLE;
resp_state_p <= RIDLE;
cdc_addr_p <= '0;
cdc_we_p <= '0;
cdc_be_p <= '0;
cdc_wdata_p <= '0;
cdc_clear_p <= '0;
end else begin
req_state_p <= req_state_n;
resp_state_p <= resp_state_n;
if (mem_gnt_o) begin
cdc_addr_p <= mem_addr_i;
cdc_we_p <= mem_we_i;
cdc_be_p <= mem_be_i;
cdc_wdata_p <= mem_wdata_i;
cdc_clear_p <= mem_clear_i;
end
end
end
assign cdc_addr_ao = cdc_addr_p;
assign cdc_we_ao = cdc_we_p;
assign cdc_be_ao = cdc_be_p;
assign cdc_wdata_ao = cdc_wdata_p;
assign cdc_clear_ao = cdc_clear_p;
pulp_sync i_sync_ack (
.clk_i ( tck_i ),
.rstn_i ( trst_ni ) ,
.serial_i ( cdc_ack_ai ),
.serial_o ( cdc_ack )
);
pulp_sync i_sync_rreq (
.clk_i ( tck_i ),
.rstn_i ( trst_ni ) ,
.serial_i ( cdc_rreq_ai ),
.serial_o ( cdc_rreq )
);
assign mem_rerror_o = cdc_rerror_ai;
assign mem_rdata_o = cdc_rdata_ai;
endmodule
module dmi_cdc_mem #(
parameter int unsigned ADDR_WIDTH = 32,
parameter int unsigned DATA_WIDTH = 64
)(
// mem side
input logic clk_i,
input logic rst_ni,
output logic mem_req_o,
input logic mem_gnt_i,
output logic [ADDR_WIDTH-1:0] mem_addr_o,
output logic mem_we_o,
output logic [DATA_WIDTH/8-1:0] mem_be_o,
output logic [DATA_WIDTH-1:0] mem_wdata_o,
input logic [DATA_WIDTH-1:0] mem_rdata_i,
input logic mem_rvalid_i,
input logic mem_rerror_i,
output logic mem_clear_o,
// CDC side
input logic cdc_req_ai,
output logic cdc_ack_ao,
input logic [ADDR_WIDTH-1:0] cdc_addr_ai,
input logic cdc_we_ai,
input logic [DATA_WIDTH/8-1:0] cdc_be_ai,
input logic [DATA_WIDTH-1:0] cdc_wdata_ai,
input logic cdc_clear_ai,
output logic cdc_rreq_ao,
input logic cdc_rack_ai,
output logic [DATA_WIDTH-1:0] cdc_rdata_ao,
output logic cdc_rerror_ao
);
enum logic [1:0] { IDLE, REQUEST, WAIT_REQ_LOW } req_state_p, req_state_n;
enum logic [1:0] { RIDLE, WAIT_ACK_HIGH, WAIT_ACK_LOW } resp_state_p, resp_state_n;
logic [ADDR_WIDTH-1:0] mem_addr_p;
logic mem_we_p;
logic [DATA_WIDTH/8-1:0] mem_be_p;
logic [DATA_WIDTH-1:0] mem_wdata_p;
logic mem_clear_p;
logic cdc_req;
logic cdc_clear;
logic cdc_sample;
logic cdc_rack;
logic [DATA_WIDTH-1:0] cdc_rdata_p;
logic cdc_rerror_p;
always_comb
begin
req_state_n = req_state_p;
cdc_ack_ao = 1'b0;
cdc_sample = 1'b0;
mem_req_o = 1'b0;
unique case (req_state_p)
IDLE: begin
if (cdc_req) begin
req_state_n = REQUEST;
cdc_sample = 1'b1;
end
end
REQUEST: begin
mem_req_o = 1'b1;
cdc_ack_ao = 1'b1;
if (mem_gnt_i) begin
req_state_n = WAIT_REQ_LOW;
end
end
WAIT_REQ_LOW: begin
cdc_ack_ao = 1'b1;
if (~cdc_req) begin
req_state_n = IDLE;
end
end
default:; // make unique case happy during reset
endcase
if (cdc_clear)
req_state_n = IDLE;
end
always_comb
begin
resp_state_n = resp_state_p;
cdc_rreq_ao = 1'b0;
unique case (resp_state_p)
RIDLE: begin
if (mem_rvalid_i) begin
resp_state_n = WAIT_ACK_HIGH;
end
end
WAIT_ACK_HIGH: begin
cdc_rreq_ao = 1'b1;
if (cdc_rack) begin
resp_state_n = WAIT_ACK_LOW;
end
end
WAIT_ACK_LOW: begin
cdc_rreq_ao = 1'b0;
if (~cdc_rack) begin
resp_state_n = RIDLE;
end
end
default:; // make unique case happy during reset
endcase
if (cdc_clear)
resp_state_n = RIDLE;
end
always_ff @(posedge clk_i, negedge rst_ni)
begin
if (~rst_ni) begin
req_state_p <= IDLE;
resp_state_p <= RIDLE;
mem_addr_p <= '0;
mem_we_p <= '0;
mem_be_p <= '0;
mem_wdata_p <= '0;
mem_clear_p <= '0;
cdc_rdata_p <= '0;
cdc_rerror_p <= '0;
end else begin
req_state_p <= req_state_n;
resp_state_p <= resp_state_n;
if (cdc_sample) begin
mem_addr_p <= cdc_addr_ai;
mem_we_p <= cdc_we_ai;
mem_be_p <= cdc_be_ai;
mem_wdata_p <= cdc_wdata_ai;
mem_clear_p <= cdc_clear_ai;
end else begin
mem_clear_p <= '0;
end
if (mem_rvalid_i) begin
cdc_rdata_p <= mem_rdata_i;
cdc_rerror_p <= mem_rerror_i;
end
end
end
assign mem_addr_o = mem_addr_p;
assign mem_we_o = mem_we_p;
assign mem_be_o = mem_be_p;
assign mem_wdata_o = mem_wdata_p;
assign mem_clear_o = mem_clear_p;
assign cdc_rdata_ao = cdc_rdata_p;
assign cdc_rerror_ao = cdc_rerror_p;
pulp_sync i_sync_req (
.clk_i ( clk_i ),
.rstn_i ( rst_ni ) ,
.serial_i ( cdc_req_ai ),
.serial_o ( cdc_req )
);
pulp_sync i_sync_clear (
.clk_i ( clk_i ),
.rstn_i ( rst_ni ),
.serial_i ( cdc_clear_ai ),
.serial_o ( cdc_clear )
);
pulp_sync i_sync_rack (
.clk_i ( clk_i ),
.rstn_i ( rst_ni ) ,
.serial_i ( cdc_rack_ai ),
.serial_o ( cdc_rack )
);
//----------------------------------------------------------------------------
// Assertions
//----------------------------------------------------------------------------
`ifndef SYNTHESIS
`ifndef verilator
assert property (
@(posedge clk_i) (mem_req_o) |-> (!$isunknown(mem_addr_o) && !$isunknown(mem_we_o)
&& !$isunknown(mem_be_o) && !$isunknown(mem_wdata_o)))
else $warning("mem request data may never be unknown");
assert property (
@(posedge clk_i) (!$isunknown(mem_gnt_i))) else $warning("memory grant may never be unknown");
`endif
`endif
.dst_rst_ni ( trst_ni ),
.dst_clk_i ( tck_i ),
.dst_data_o ( jtag_dmi_resp_o ),
.dst_valid_o ( jtag_dmi_valid_o ),
.dst_ready_i ( jtag_dmi_ready_i )
);
endmodule

View file

@ -17,27 +17,25 @@
*/
module dmi_jtag (
input logic clk_i, // DMI Clock
input logic rst_ni, // Asynchronous reset active low
input logic clk_i, // DMI Clock
input logic rst_ni, // Asynchronous reset active low
output logic dmi_rst_no, // hard reset
output logic dmi_rst_no, // hard reset
output logic dmi_req_valid_o,
input logic dmi_req_ready_i,
output logic [ 6:0] dmi_req_bits_addr_o,
output logic [ 1:0] dmi_req_bits_op_o, // 0 = nop, 1 = read, 2 = write
output logic [31:0] dmi_req_bits_data_o,
input logic dmi_resp_valid_i,
output logic dmi_resp_ready_o,
input logic [ 1:0] dmi_resp_bits_resp_i,
input logic [31:0] dmi_resp_bits_data_i,
output dm::dmi_req_t dmi_req_o,
output logic dmi_req_valid_o,
input logic dmi_req_ready_i,
input logic tck_i, // JTAG test clock pad
input logic tms_i, // JTAG test mode select pad
input logic trst_ni, // JTAG test reset pad
input logic td_i, // JTAG test data input pad
output logic td_o, // JTAG test data output pad
output logic tdo_oe_o // Data out output enable
input dm::dmi_resp_t dmi_resp_i,
output logic dmi_resp_ready_o,
input logic dmi_resp_valid_i,
input logic tck_i, // JTAG test clock pad
input logic tms_i, // JTAG test mode select pad
input logic trst_ni, // JTAG test reset pad
input logic td_i, // JTAG test data input pad
output logic td_o, // JTAG test data output pad
output logic tdo_oe_o // Data out output enable
);
assign dmi_rst_no = 1'b1;
@ -51,13 +49,13 @@ module dmi_jtag (
logic dmi_tdi;
logic dmi_tdo;
logic mem_valid;
logic mem_gnt;
logic [6:0] mem_addr;
logic mem_we;
logic [31:0] mem_wdata;
logic [31:0] mem_rdata;
logic mem_rvalid;
dm::dmi_req_t dmi_req;
logic dmi_req_ready;
logic dmi_req_valid;
dm::dmi_resp_t dmi_resp;
logic dmi_resp_valid;
logic dmi_resp_ready;
typedef struct packed {
logic [6:0] address;
@ -77,10 +75,12 @@ module dmi_jtag (
logic [31:0] data_d, data_q;
dmi_t dmi;
assign dmi = dmi_t'(dr_q);
assign mem_addr = address_q;
assign mem_wdata = data_q;
assign mem_we = (state_q == Write);
assign dmi = dmi_t'(dr_q);
assign dmi_req.addr = address_q;
assign dmi_req.data = data_q;
assign dmi_req.op = (state_q == Write) ? dm::DTM_WRITE : dm::DTM_READ;
// we'will always be ready to accept the data we requested
assign dmi_resp_ready = 1'b1;
logic error_dmi_busy;
dmi_error_t error_d, error_q;
@ -93,7 +93,7 @@ module dmi_jtag (
data_d = data_q;
error_d = error_q;
mem_valid = 1'b0;
dmi_req_valid = 1'b0;
case (state_q)
Idle: begin
@ -112,31 +112,31 @@ module dmi_jtag (
end
Read: begin
mem_valid = 1'b1;
if (mem_gnt) begin
dmi_req_valid = 1'b1;
if (dmi_req_ready) begin
state_d = WaitReadValid;
end
end
WaitReadValid: begin
// load data into register and shift out
if (mem_rvalid) begin
data_d = mem_rdata;
if (dmi_resp_valid) begin
data_d = dmi_resp.data;
state_d = Idle;
end
end
Write: begin
mem_valid = 1'b1;
dmi_req_valid = 1'b1;
// got a valid answer go back to idle
if (mem_gnt) begin
if (dmi_req_ready) begin
state_d = Idle;
end
end
WaitWriteValid: begin
// just wait for idle here
if (mem_rvalid) begin
if (dmi_resp_valid) begin
state_d = Idle;
end
end
@ -237,26 +237,21 @@ module dmi_jtag (
// JTAG side (master side)
.tck_i,
.trst_ni,
.mem_valid_i ( mem_valid ),
.mem_gnt_o ( mem_gnt ),
.mem_addr_i ( mem_addr ),
.mem_we_i ( mem_we ),
.mem_wdata_i ( mem_wdata ),
.mem_rdata_o ( mem_rdata ),
.mem_rvalid_o ( mem_rvalid ),
.jtag_dmi_req_i ( dmi_req ),
.jtag_dmi_ready_o ( dmi_req_ready ),
.jtag_dmi_valid_i ( dmi_req_valid ),
.jtag_dmi_resp_o ( dmi_resp ),
.jtag_dmi_valid_o ( dmi_resp_valid ),
.jtag_dmi_ready_i ( dmi_resp_ready ),
// core side
.clk_i,
.rst_ni,
.dmi_req_valid_o,
.dmi_req_ready_i,
.dmi_req_bits_addr_o,
.dmi_req_bits_op_o,
.dmi_req_bits_data_o,
.dmi_resp_valid_i,
.dmi_resp_ready_o,
.dmi_resp_bits_resp_i,
.dmi_resp_bits_data_i
.core_dmi_req_o ( dmi_req_o ),
.core_dmi_valid_o ( dmi_req_valid_o ),
.core_dmi_ready_i ( dmi_req_ready_i ),
.core_dmi_resp_i ( dmi_resp_i ),
.core_dmi_ready_o ( dmi_resp_ready_o ),
.core_dmi_valid_i ( dmi_resp_valid_i )
);
endmodule

View file

@ -20,7 +20,6 @@ module issue_read_operands #(
)(
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
input logic test_en_i,
// flush
input logic flush_i,
// coming from rename
@ -282,7 +281,7 @@ module issue_read_operands #(
// Clock and Reset
.clk ( clk_i ),
.rst_n ( rst_ni ),
.test_en_i ( test_en_i ),
.test_en_i ( 1'b0 ),
.raddr_a_i ( issue_instr_i.rs1[4:0] ),
.rdata_a_o ( operand_a_regfile ),

View file

@ -22,7 +22,6 @@ module issue_stage #(
)(
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
input logic test_en_i, // Test Enable
input logic flush_unissued_instr_i,
input logic flush_i,

View file

@ -34,9 +34,9 @@ module ariane_tb;
logic [31:0] exit_o;
ariane_testharness dut (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.exit_o ( exit_o )
.clk_i,
.rst_ni,
.exit_o
);
// Clock process

View file

@ -30,7 +30,7 @@ module ariane_testharness #(
logic test_en;
logic ndmreset;
logic ndmreset_n;
logic debug_req;
logic debug_req_core;
int jtag_enable;
logic init_done;
@ -45,9 +45,6 @@ module ariane_testharness #(
logic debug_req_valid;
logic debug_req_ready;
logic [6:0] debug_req_bits_addr;
logic [1:0] debug_req_bits_op;
logic [31:0] debug_req_bits_data;
logic debug_resp_valid;
logic debug_resp_ready;
logic [1:0] debug_resp_bits_resp;
@ -71,7 +68,8 @@ module ariane_testharness #(
assign ndmreset_n = ~ndmreset ;
localparam NB_SLAVE = 4;
localparam NB_MASTER = 3;
localparam NB_MASTER = 4;
localparam AXI_ID_WIDTH_SLAVES = AXI_ID_WIDTH + $clog2(NB_SLAVE);
AXI_BUS #(
@ -97,12 +95,16 @@ module ariane_testharness #(
if (!$value$plusargs("jtag_rbb_enable=%b", jtag_enable)) jtag_enable = 'h0;
end
dm::dmi_req_t jtag_dmi_req;
dm::dmi_req_t dmi_req;
dm::dmi_req_t debug_req;
dm::dmi_resp_t debug_resp;
// debug if MUX
assign debug_req_valid = (jtag_enable[0]) ? jtag_req_valid : dmi_req_valid;
assign debug_req_bits_addr = (jtag_enable[0]) ? jtag_req_bits_addr : dmi_req_bits_addr;
assign debug_req_bits_op = (jtag_enable[0]) ? jtag_req_bits_op : dmi_req_bits_op;
assign debug_req_bits_data = (jtag_enable[0]) ? jtag_req_bits_data : dmi_req_bits_data;
assign debug_resp_ready = (jtag_enable[0]) ? jtag_resp_ready : dmi_resp_ready;
assign debug_req = (jtag_enable[0]) ? jtag_dmi_req : dmi_req;
assign exit_o = (jtag_enable[0]) ? jtag_exit : dmi_exit;
assign jtag_resp_valid = (jtag_enable[0]) ? debug_resp_valid : 1'b0;
assign dmi_resp_valid = (jtag_enable[0]) ? 1'b0 : debug_resp_valid;
@ -124,42 +126,39 @@ module ariane_testharness #(
);
dmi_jtag i_dmi_jtag (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.dmi_rst_no ( ),
.dmi_req_valid_o ( jtag_req_valid ),
.dmi_req_ready_i ( debug_req_ready ),
.dmi_req_bits_addr_o ( jtag_req_bits_addr ),
.dmi_req_bits_op_o ( jtag_req_bits_op ),
.dmi_req_bits_data_o ( jtag_req_bits_data ),
.dmi_resp_valid_i ( jtag_resp_valid ),
.dmi_resp_ready_o ( jtag_resp_ready ),
.dmi_resp_bits_resp_i ( debug_resp_bits_resp ),
.dmi_resp_bits_data_i ( debug_resp_bits_data ),
.tck_i ( jtag_TCK ),
.tms_i ( jtag_TMS ),
.trst_ni ( jtag_TRSTn ),
.td_i ( jtag_TDI ),
.td_o ( jtag_TDO_data ),
.tdo_oe_o ( jtag_TDO_driven )
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.dmi_req_o ( jtag_dmi_req ),
.dmi_req_valid_o ( jtag_req_valid ),
.dmi_req_ready_i ( debug_req_ready ),
.dmi_resp_i ( debug_resp ),
.dmi_resp_ready_o ( jtag_resp_ready ),
.dmi_resp_valid_i ( jtag_resp_valid ),
.dmi_rst_no ( ), // not connected
.tck_i ( jtag_TCK ),
.tms_i ( jtag_TMS ),
.trst_ni ( jtag_TRSTn ),
.td_i ( jtag_TDI ),
.td_o ( jtag_TDO_data ),
.tdo_oe_o ( jtag_TDO_driven )
);
// SiFive's SimDTM Module
// Converts to DPI calls
logic [1:0] debug_req_bits_op;
assign dmi_req.op = dm::dtm_op_t'(debug_req_bits_op);
SimDTM i_SimDTM (
.clk ( clk_i ),
.reset ( ~rst_ni ),
.debug_req_valid ( dmi_req_valid ),
.debug_req_ready ( debug_req_ready ),
.debug_req_bits_addr ( dmi_req_bits_addr ),
.debug_req_bits_op ( dmi_req_bits_op ),
.debug_req_bits_data ( dmi_req_bits_data ),
.debug_req_bits_addr ( dmi_req.addr ),
.debug_req_bits_op ( debug_req_bits_op ),
.debug_req_bits_data ( dmi_req.data ),
.debug_resp_valid ( dmi_resp_valid ),
.debug_resp_ready ( dmi_resp_ready ),
.debug_resp_bits_resp ( debug_resp_bits_resp ),
.debug_resp_bits_data ( debug_resp_bits_data ),
.debug_resp_bits_resp ( debug_resp.resp ),
.debug_resp_bits_data ( debug_resp.data ),
.exit ( dmi_exit )
);
@ -177,20 +176,17 @@ module ariane_testharness #(
.testmode_i ( test_en ),
.ndmreset_o ( ndmreset ),
.dmactive_o ( ), // active debug session
.debug_req_o ( debug_req ),
.debug_req_o ( debug_req_core ),
.unavailable_i ( '0 ),
.axi_master ( slave[3] ),
.axi_slave ( master[2] ),
.axi_slave ( master[3] ),
.dmi_rst_ni ( rst_ni ),
.dmi_req_valid_i ( debug_req_valid ),
.dmi_req_ready_o ( debug_req_ready ),
.dmi_req_bits_addr_i ( debug_req_bits_addr ),
.dmi_req_bits_op_i ( debug_req_bits_op ),
.dmi_req_bits_data_i ( debug_req_bits_data ),
.dmi_req_i ( debug_req ),
.dmi_resp_valid_o ( debug_resp_valid ),
.dmi_resp_ready_i ( debug_resp_ready ),
.dmi_resp_bits_resp_o ( debug_resp_bits_resp ),
.dmi_resp_bits_data_o ( debug_resp_bits_data )
.dmi_resp_o ( debug_resp )
);
// ---------------
@ -208,7 +204,7 @@ module ariane_testharness #(
) i_axi2rom (
.clk_i ( clk_i ),
.rst_ni ( ndmreset_n ),
.slave ( master[1] ),
.slave ( master[2] ),
.req_o ( rom_req ),
.we_o ( ),
.addr_o ( rom_addr ),
@ -234,7 +230,7 @@ module ariane_testharness #(
logic [AXI_DATA_WIDTH-1:0] wdata;
logic [AXI_DATA_WIDTH-1:0] rdata;
axi2mem #(
.AXI_ID_WIDTH ( AXI_ID_WIDTH_SLAVES ),
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
@ -278,13 +274,33 @@ module ariane_testharness #(
.AXI_USER_WIDTH ( AXI_USER_WIDTH ),
.AXI_ID_WIDTH ( AXI_ID_WIDTH )
) i_axi_xbar (
.clk ( clk_i ),
.rst_n ( ndmreset_n ),
.test_en_i ( test_en ),
.slave ( slave ),
.master ( master ),
.start_addr_i ( {64'h0, 64'h10000, CACHE_START_ADDR} ),
.end_addr_i ( {64'hFFF, 64'h1FFFF, CACHE_START_ADDR + 2**24} )
.clk ( clk_i ),
.rst_n ( ndmreset_n ),
.test_en_i ( test_en ),
.slave ( slave ),
.master ( master ),
.start_addr_i ( {64'h0, 64'h10000, 64'h2000000, CACHE_START_ADDR} ),
.end_addr_i ( {64'hFFF, 64'h1FFFF, 64'h2FFFFFF, CACHE_START_ADDR + 2**24} )
);
// ---------------
// CLINT
// ---------------
logic ipi;
logic timer_irq;
clint #(
.AXI_ADDR_WIDTH ( AXI_ADDRESS_WIDTH ),
.AXI_DATA_WIDTH ( AXI_DATA_WIDTH ),
.AXI_ID_WIDTH ( AXI_ID_WIDTH_SLAVES ),
.NR_CORES ( 1 )
) i_clint (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.slave ( master[1] ),
.rtc_i ( 1'b0 ),
.timer_irq_o ( timer_irq ),
.ipi_o ( ipi )
);
// ---------------
@ -297,14 +313,13 @@ module ariane_testharness #(
) i_ariane (
.clk_i ( clk_i ),
.rst_ni ( ndmreset_n ),
.test_en_i ( test_en ),
.boot_addr_i ( 64'h10000 ), // start fetching from ROM
.core_id_i ( '0 ),
.cluster_id_i ( '0 ),
.irq_i ( '0 ),
.ipi_i ( '0 ),
.time_irq_i ( '0 ),
.debug_req_i ( debug_req ),
.irq_i ( '0 ), // we do not specify other interrupts in this TB
.ipi_i ( ipi ),
.time_irq_i ( timer_irq ),
.debug_req_i ( debug_req_core ),
.data_if ( slave[2] ),
.bypass_if ( slave[1] ),
.instr_if ( slave[0] )