├── .gitignore ├── src ├── rtl │ ├── testbench │ │ ├── flow_pifo │ │ │ ├── .gitignore │ │ │ ├── flow_pifo_tb_headers.vh │ │ │ ├── flow_pifo_tb.include │ │ │ ├── globals_tb.v │ │ │ └── flow_pifo_tb.v │ │ ├── dumps │ │ │ └── .gitignore │ │ ├── logs │ │ │ └── .gitignore │ │ ├── support │ │ │ ├── globals.v │ │ │ └── clock_generator.v │ │ ├── .gitignore │ │ ├── common │ │ │ ├── common_tb_headers.vh │ │ │ ├── globals_common.v │ │ │ ├── traffic_receiver.v │ │ │ ├── traffic_generator.v │ │ │ └── linear_feedback_shift_register.v │ │ ├── pifo_set │ │ │ ├── pifo_set_tb_headers.vh │ │ │ ├── pifo_set_tb.include │ │ │ ├── globals_tb.v │ │ │ └── pifo_set_tb.v │ │ ├── Makefile │ │ └── Makefile.inc.template │ └── design │ │ ├── flow_pifo_headers.vh │ │ ├── globals_top.v │ │ ├── priority_encode_log.v │ │ ├── clock_gater.v │ │ ├── counter.v │ │ ├── fifo.v │ │ ├── prefetch_buffer.v │ │ ├── fifo_bank.v │ │ ├── fifo_base_bypass.v │ │ ├── fifo_init.v │ │ ├── fifo_base.v │ │ ├── flow_pifo.v │ │ ├── pifo.v │ │ └── pifo_set.v └── scripts │ ├── pifo_set │ ├── Makefile.include │ └── dc │ │ ├── libs.tcl │ │ ├── synth.sdc │ │ ├── Makefile │ │ └── synth.tcl │ └── flow_pifo │ ├── Makefile.include │ └── dc │ ├── libs.tcl │ ├── synth.sdc │ ├── Makefile │ └── synth.tcl ├── Makefile.common.template ├── Makefile ├── README.md └── example └── range_cam.v /.gitignore: -------------------------------------------------------------------------------- 1 | Makefile.common 2 | -------------------------------------------------------------------------------- /src/rtl/testbench/flow_pifo/.gitignore: -------------------------------------------------------------------------------- 1 | temp 2 | -------------------------------------------------------------------------------- /src/rtl/testbench/dumps/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /src/rtl/testbench/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /src/rtl/testbench/support/globals.v: -------------------------------------------------------------------------------- 1 | 2 | `define STRINGIFY(x) `"x`" 3 | 4 | -------------------------------------------------------------------------------- /src/rtl/testbench/.gitignore: -------------------------------------------------------------------------------- 1 | Makefile.inc 2 | *.exec 3 | *.exec.* 4 | *.log 5 | ucli.key 6 | *.daidir 7 | csrc 8 | DVEfiles 9 | -------------------------------------------------------------------------------- /src/rtl/design/flow_pifo_headers.vh: -------------------------------------------------------------------------------- 1 | // `ifndef _pifo_incl_vh_ 2 | // `define _pifo_incl_vh_ 3 | 4 | import FlowPifoPkg::*; 5 | 6 | // `endif 7 | -------------------------------------------------------------------------------- /src/rtl/testbench/common/common_tb_headers.vh: -------------------------------------------------------------------------------- 1 | // `ifndef _common_tb_incl_vh_ 2 | // `define _common_tb_incl_vh_ 3 | import CommonTbPkg::*; 4 | import FlowPifoPkg::NUM_FLOWS; 5 | 6 | // `endif 7 | -------------------------------------------------------------------------------- /src/scripts/pifo_set/Makefile.include: -------------------------------------------------------------------------------- 1 | 2 | TOPLEVEL := pifo_set 3 | 4 | RTL_FILES_ROOT := $(PROJ_DIR)/src/rtl/design 5 | 6 | RTL_FILES := \ 7 | $(RTL_FILES_ROOT)/globals_top.v \ 8 | $(RTL_FILES_ROOT)/pifo_set.v 9 | -------------------------------------------------------------------------------- /src/rtl/testbench/pifo_set/pifo_set_tb_headers.vh: -------------------------------------------------------------------------------- 1 | // `ifndef _pifo_tb_incl_vh_ 2 | // `define _pifo_tb_incl_vh_ 3 | import PifoSetTbPkg::*; 4 | import InterfacePkg::*; 5 | import CommonTbPkg::*; 6 | import FlowPifoPkg::*; 7 | 8 | // `endif 9 | -------------------------------------------------------------------------------- /src/rtl/testbench/flow_pifo/flow_pifo_tb_headers.vh: -------------------------------------------------------------------------------- 1 | // `ifndef _flow_pifo_tb_incl_vh_ 2 | // `define _flow_pifo_tb_incl_vh_ 3 | import FlowPifoTbPkg::*; 4 | import InterfacePkg::*; 5 | import CommonTbPkg::*; 6 | import FlowPifoPkg::*; 7 | 8 | // `endif 9 | -------------------------------------------------------------------------------- /Makefile.common.template: -------------------------------------------------------------------------------- 1 | 2 | PROJ_DIR = /path/to/pifo/pifo-hardware 3 | 4 | SRC_DIR = $(PROJ_DIR)/src 5 | BUILD_DIR = $(PROJ_DIR)/build 6 | 7 | # [ssub] Eventually there will be a entire host of files required 8 | # for Synopsys DC, Encounter etc. here (eg: path to standard cell 9 | # libraries etc.). Will add them as required. 10 | -------------------------------------------------------------------------------- /src/rtl/testbench/pifo_set/pifo_set_tb.include: -------------------------------------------------------------------------------- 1 | ../design/globals_top.v 2 | pifo_set/globals_tb.v 3 | common/globals_common.v 4 | 5 | support/globals.v 6 | support/clock_generator.v 7 | 8 | ../design/pifo_set.v 9 | 10 | common/linear_feedback_shift_register.v 11 | common/traffic_generator.v 12 | common/traffic_receiver.v 13 | 14 | pifo_set/pifo_set_tb.v 15 | -------------------------------------------------------------------------------- /src/scripts/flow_pifo/Makefile.include: -------------------------------------------------------------------------------- 1 | 2 | TOPLEVEL := flow_pifo 3 | 4 | RTL_FILES_ROOT := $(PROJ_DIR)/src/rtl/design 5 | 6 | RTL_FILES := \ 7 | $(RTL_FILES_ROOT)/globals_top.v \ 8 | $(RTL_FILES_ROOT)/clock_gater.v \ 9 | $(RTL_FILES_ROOT)/counter_base.v \ 10 | $(RTL_FILES_ROOT)/counter.v \ 11 | $(RTL_FILES_ROOT)/fifo_base.v \ 12 | $(RTL_FILES_ROOT)/fifo_base_bypass.v \ 13 | $(RTL_FILES_ROOT)/fifo_init.v \ 14 | $(RTL_FILES_ROOT)/fifo_bank.v \ 15 | $(RTL_FILES_ROOT)/flow_pifo.v \ 16 | $(RTL_FILES_ROOT)/prefetch_buffer.v \ 17 | $(RTL_FILES_ROOT)/pifo_set.v 18 | -------------------------------------------------------------------------------- /src/rtl/testbench/Makefile: -------------------------------------------------------------------------------- 1 | 2 | include Makefile.inc 3 | 4 | .PHONY: clean 5 | 6 | all: 7 | ifeq ($(RUN_VCS),1) 8 | echo "Build model" 9 | $(RM) -rf csrc $(SIMV_NAME).* $(SIMV_NAME) 10 | vcs -f $(INCLUDE_FILE) $(VCS_OPTIONS) -l simv.log 11 | endif 12 | mkdir -p $(LOG_FOLDER) 13 | date 14 | ifeq ($(REDIRECT_LOG), 1) 15 | ./$(SIMV_NAME) $(SIMV_OPTIONS) > $(LOG_FOLDER)/$(LOG_NAME) 16 | else 17 | ./$(SIMV_NAME) $(SIMV_OPTIONS) 18 | endif 19 | date 20 | 21 | clean: 22 | $(RM) simv.log srec_parse.log ucli.key 23 | $(RM) -rf csrc $(SIMV_NAME).* $(SIMV_NAME) 24 | 25 | -------------------------------------------------------------------------------- /src/rtl/testbench/flow_pifo/flow_pifo_tb.include: -------------------------------------------------------------------------------- 1 | ../design/globals_top.v 2 | flow_pifo/globals_tb.v 3 | common/globals_common.v 4 | 5 | support/globals.v 6 | support/clock_generator.v 7 | 8 | ../design/clock_gater.v 9 | ../design/counter.v 10 | ../design/fifo.v 11 | ../design/fifo_base.v 12 | ../design/fifo_base_bypass.v 13 | ../design/fifo_init.v 14 | ../design/pifo_set.v 15 | ../design/prefetch_buffer.v 16 | ../design/fifo_bank.v 17 | ../design/flow_pifo.v 18 | 19 | common/linear_feedback_shift_register.v 20 | common/traffic_generator.v 21 | common/traffic_receiver.v 22 | 23 | flow_pifo/flow_pifo_tb.v 24 | -------------------------------------------------------------------------------- /src/scripts/flow_pifo/dc/libs.tcl: -------------------------------------------------------------------------------- 1 | #========================================================================= 2 | # TCL Script File for DC Compiler Library Setup 3 | #------------------------------------------------------------------------- 4 | 5 | # The makefile will generate various variables which we now read in 6 | 7 | source make_generated_vars.tcl 8 | 9 | # The following commands setup the standard cell libraries 10 | 11 | set target_library "$SYNTH_LIB" 12 | set link_library "* $SYNTH_LIB" 13 | 14 | # The search path needs to point to the verilog source directory 15 | 16 | set search_path [concat $DESIGN_RTL_DIR $search_path ] 17 | 18 | -------------------------------------------------------------------------------- /src/scripts/pifo_set/dc/libs.tcl: -------------------------------------------------------------------------------- 1 | #========================================================================= 2 | # TCL Script File for DC Compiler Library Setup 3 | #------------------------------------------------------------------------- 4 | 5 | # The makefile will generate various variables which we now read in 6 | 7 | source make_generated_vars.tcl 8 | 9 | # The following commands setup the standard cell libraries 10 | 11 | set target_library "$SYNTH_LIB" 12 | set link_library "* $SYNTH_LIB" 13 | 14 | # The search path needs to point to the verilog source directory 15 | 16 | set search_path [concat $DESIGN_RTL_DIR $search_path ] 17 | 18 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | include Makefile.common 3 | 4 | .phony: help 5 | 6 | # create folder if needed 7 | %/.created: 8 | mkdir -p $(dir $@) 9 | touch $@ 10 | 11 | $(BUILD): $(BUILD_DIR)/$(DESIGN)/$(BUILD)/.created 12 | cd $(BUILD_DIR)/$(DESIGN)/$(BUILD); \ 13 | cp $(SRC_DIR)/scripts/$(DESIGN)/Makefile.include .; \ 14 | cp $(SRC_DIR)/scripts/$(DESIGN)/$(BUILD)/* .; \ 15 | make -I $(PROJ_DIR); \ 16 | cd $(PROJ_DIR); 17 | 18 | link: $(BUILD_DIR)/$(DESIGN)/$(BUILD)/.created 19 | ln -s $(BUILD_DIR)/$(DESIGN)/$(BUILD)/$(shell readlink $(BUILD_DIR)/$(DESIGN)/$(BUILD)/current) $(BUILD_DIR)/$(DESIGN)/$(BUILD)/$(NAME) 20 | 21 | 22 | help: 23 | echo "make DESIGN=design_name BUILD=[dc|enc]" 24 | -------------------------------------------------------------------------------- /src/rtl/testbench/common/globals_common.v: -------------------------------------------------------------------------------- 1 | package CommonTbPkg; 2 | 3 | import FlowPifoPkg::Priority; 4 | import FlowPifoPkg::FlowId; 5 | 6 | // ssub: Whichever testbench is using the traffic generator/receiver should 7 | // define an InterfacePkg and set these appropriately. 8 | import InterfacePkg::InjectionRate; 9 | import InterfacePkg::EjectionRate; 10 | import InterfacePkg::CounterSignal; 11 | 12 | typedef struct { 13 | FlowId flow_id_seed; 14 | Priority priority_seed; 15 | InjectionRate injrate_seed; 16 | 17 | InjectionRate injrate; 18 | CounterSignal total_packets; 19 | } TGConfig; 20 | 21 | typedef struct { 22 | EjectionRate ejrate_seed; 23 | EjectionRate ejrate; 24 | } TRConfig; 25 | 26 | endpackage 27 | -------------------------------------------------------------------------------- /src/rtl/design/globals_top.v: -------------------------------------------------------------------------------- 1 | `ifndef SYNTHESIS 2 | timeunit 1ns; 3 | timeprecision 1ps; 4 | `endif 5 | 6 | `define MAX(x, y) ((x>=y) ? (x) : (y)) 7 | 8 | package FlowPifoPkg; 9 | 10 | localparam MAX_PACKET_PRIORITY = (255); // Packet priorities should be in the range [0, MAX_PACKET_PRIORITY] (integers) 11 | localparam PRIORITY_WIDTH = $clog2(MAX_PACKET_PRIORITY+1); 12 | localparam PACKET_POINTER_WIDTH = (8); 13 | localparam NUM_FLOWS = (4); 14 | localparam FIFO_DEPTH = (10); 15 | localparam PREFETCH_BUFFER_DEPTH = (1); 16 | localparam FLOW_ID_WIDTH = $clog2(NUM_FLOWS+1); 17 | 18 | typedef logic [PRIORITY_WIDTH-1:0] Priority; 19 | typedef logic [FLOW_ID_WIDTH-1:0] FlowId; 20 | 21 | 22 | endpackage 23 | 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pifo-hardware 2 | 3 | * Clone/pull the git repository 4 | 5 | * Do: 6 | > $ cd /path/to/pifo-hardware/ 7 | > $ cp Makefile.common.template Makefile.common 8 | 9 | Edit Makefile.common --> just change PROJ_DIR path. 10 | If you have the time, try to automate this. 11 | 12 | * To test out the design: 13 | > $ cd .../src/rtl/testbench 14 | > $ make 15 | 16 | Feel free to edit parameters in: 17 | .../src/rtl/testbench/{pifo_set,flow_pifo}/globals_tb.v 18 | .../src/rtl/design/globals_top.v 19 | 20 | * You can find the actual design at .../src/rtl/design/ 21 | You can find the testbench at .../src/rtl/testbench/ 22 | 23 | * Currently testbench does not "print" anything. If you want to view the operation: 24 | > $ dve -vpd dumps/{pifo_set, flow_pifo}_tb.vpd 25 | Eyeball the waveform for now to make sure things are working correctly. 26 | I will add a text dump later. 27 | -------------------------------------------------------------------------------- /src/rtl/testbench/pifo_set/globals_tb.v: -------------------------------------------------------------------------------- 1 | `define MAX_PACKETS (16) 2 | 3 | package PifoSetTbPkg; 4 | 5 | localparam PRIORITY_SEED = 8'b00000010; // Number of bits needs to be set based on MAX_PACKET_PRIORITY 6 | localparam PRIORITY_SEED2 = 8'b01000010; 7 | localparam PKT_FLOWID_SEED = 2'b10; 8 | localparam PKT_INJRATE_SEED = 10'b0010001001; 9 | localparam PKT_EJRATE_SEED = 10'b1000100101; 10 | localparam PKT_RIRATE_SEED = 10'b1110100100; 11 | localparam MAX_PACKETS = `MAX_PACKETS; 12 | localparam NUM_ELEMENTS = 4; // Number of elements in the pifo set 13 | localparam PKT_INJRATE = 1023; // Number of packets per 1024 cycles 14 | localparam PKT_EJRATE = 1023; 15 | localparam PKT_RIRATE = 512; // PKT_RIRATE/1024 gives the probability of a 16 | // dequeued flow being reinserted into the pifo-set 17 | endpackage 18 | 19 | package InterfacePkg; 20 | typedef logic [9:0] InjectionRate; 21 | typedef logic [9:0] EjectionRate; 22 | typedef logic [9:0] CounterSignal; 23 | endpackage 24 | -------------------------------------------------------------------------------- /src/rtl/testbench/flow_pifo/globals_tb.v: -------------------------------------------------------------------------------- 1 | `define MAX_PACKETS (200) 2 | 3 | package FlowPifoTbPkg; 4 | 5 | localparam MAX_PKTS_PER_PHASE = `MAX_PACKETS / 10; 6 | localparam PRIORITY_SEED = 8'b00000010; // Number of bits needs to be set based on MAX_PACKET_PRIORITY 7 | localparam PRIORITY_SEED2 = 8'b01000010; 8 | localparam PKT_FLOWID_SEED = 8'b00001100; 9 | localparam PKT_INJRATE_SEED = 10'b0010001001; 10 | localparam PKT_EJRATE_SEED = 10'b1000100101; 11 | localparam PKT_RIRATE_SEED = 10'b1110100100; 12 | localparam MAX_PACKETS = `MAX_PACKETS; 13 | localparam NUM_ELEMENTS = 4; // Number of elements in the pifo set 14 | localparam PKT_INJRATE = 1023; // Number of packets per 1024 cycles 15 | localparam PKT_EJRATE = 1023; 16 | localparam PKT_RIRATE = 512; // PKT_RIRATE/1024 gives the probability of a 17 | // dequeued flow being reinserted into the pifo-set 18 | endpackage 19 | 20 | package InterfacePkg; 21 | typedef logic [9:0] InjectionRate; 22 | typedef logic [9:0] EjectionRate; 23 | typedef logic [9:0] CounterSignal; 24 | endpackage 25 | -------------------------------------------------------------------------------- /src/rtl/testbench/support/clock_generator.v: -------------------------------------------------------------------------------- 1 | 2 | module clock_generator( 3 | clk, 4 | clk_delay, 5 | clk_count 6 | ); 7 | 8 | parameter HALF_CYCLE = 0.5; 9 | parameter SCAN_CLOCK = 0; 10 | parameter INIT_VALUE = 1'b1; 11 | 12 | output logic clk; 13 | output logic clk_delay; 14 | output integer clk_count; 15 | 16 | initial 17 | begin 18 | clk = INIT_VALUE; 19 | clk_count = 0; 20 | end 21 | 22 | generate 23 | if(SCAN_CLOCK == 1) 24 | begin: scan_clock 25 | always 26 | begin 27 | if(clk == 1'b1) 28 | begin 29 | #(HALF_CYCLE/2); 30 | clk = 1'b0; 31 | #(HALF_CYCLE/2); 32 | end 33 | else 34 | begin 35 | #(HALF_CYCLE); 36 | clk = 1'b1; 37 | end 38 | end 39 | end 40 | else 41 | begin: normal_clock 42 | always #(HALF_CYCLE) 43 | begin 44 | clk = ~clk; 45 | end 46 | end 47 | endgenerate 48 | 49 | always @ (posedge clk) 50 | begin 51 | clk_count <= clk_count + 1; 52 | end 53 | 54 | assign #(HALF_CYCLE-0.01) clk_delay = clk; 55 | 56 | endmodule 57 | 58 | -------------------------------------------------------------------------------- /src/rtl/design/priority_encode_log.v: -------------------------------------------------------------------------------- 1 | module priority_encode_log ( 2 | clk,rst, 3 | decode, 4 | encode,valid 5 | ); 6 | 7 | parameter width = 1024; 8 | parameter log_width = 10; 9 | 10 | localparam pot_width = 1 << log_width; 11 | 12 | input clk; 13 | input rst; 14 | input [width-1:0] decode; 15 | output [log_width-1:0] encode; 16 | output valid; 17 | 18 | wire [pot_width-1:0] pot_decode = {pot_width{1'b0}} | decode; 19 | 20 | reg [pot_width-1:0] part_idx [0:log_width-1]; 21 | 22 | always_comb begin 23 | part_idx[0] = 0; 24 | for(integer i=0; i=min_mem[bmp_int]) && (sr_rng_reg<=max_mem[bmp_int]); 49 | 50 | reg [NUMADDR-1:0] sr_bmp; 51 | always @(posedge clk) 52 | sr_bmp <= sr_bmp_tmp; 53 | 54 | endmodule 55 | 56 | -------------------------------------------------------------------------------- /src/rtl/testbench/Makefile.inc.template: -------------------------------------------------------------------------------- 1 | 2 | # Name of the testbench 3 | TESTBENCH_FOLDER= pifo_set 4 | TESTBENCH = pifo_set 5 | INCLUDE_FILE = $(TESTBENCH_FOLDER)/$(TESTBENCH)_tb.include 6 | 7 | # Whether it is a gate level simulation 8 | GATE_SIM = 0 9 | 10 | # Number of simulation cycles 11 | NUM_SIM_CYCLES = 20000 12 | 13 | # Whether to enable debug message 14 | DEBUG_ENABLE = 1 15 | 16 | # Whether to dump waveform (VPD, VCD) 17 | DUMP_WAVE = 1 18 | WAVE_FORMAT = VPD 19 | 20 | # Whether to run vcs (0, 1) 21 | RUN_VCS = 1 22 | 23 | # VCS executable name 24 | SIMV_NAME = run.exec 25 | 26 | # Simulation log/trace folder 27 | LOG_FOLDER = logs/$(TESTBENCH_FOLDER) 28 | LOG_NAME = $(TESTBENCH).log 29 | 30 | # VCS options 31 | VCS_OPTIONS = +v2k -sverilog +lint=all,noVCDE +warn=all -notice 32 | VCS_OPTIONS += -j16 -O3 33 | VCS_OPTIONS += -o $(SIMV_NAME) 34 | VCS_OPTIONS += +vcs+loopreport +vcs+loopdetect 35 | VCS_OPTIONS += +nospecify 36 | VCS_OPTIONS += +incdir+../design +incdir+pifo_set +incdir+common 37 | 38 | ifeq ($(DUMP_WAVE),1) 39 | VCS_OPTIONS += +define+$(WAVE_FORMAT) -debug_pp -PP 40 | endif 41 | 42 | ifeq ($(DEBUG_ENABLE),1) 43 | VCS_OPTIONS += +define+DEBUG_ENABLE 44 | endif 45 | 46 | # Simulation options 47 | SIMV_OPTIONS = +NUM_SIM_CYCLES=$(NUM_SIM_CYCLES) 48 | SIMV_OPTIONS += +DEBUG_ROUTER=$(DEBUG_ROUTER) +DEBUG_NIC=$(DEBUG_NIC) 49 | 50 | # Gate level simulation options 51 | 52 | ifeq ($(GATE_SIM),1) 53 | CLOCK_PERIOD= 1ns 54 | VCS_OPTIONS += +vcs+initreg+random 55 | SIMV_OPTIONS+= +vcs+initreg+random 56 | else 57 | VCS_OPTIONS += +memcbk 58 | VCS_OPTIONS += -parallel+vpd=10 59 | endif 60 | 61 | VCS_OPTIONS += $(EXTRA_VCS_OPTIONS) 62 | SIMV_OPTIONS += $(EXTRA_SIMV_OPTIONS) 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/scripts/pifo_set/dc/Makefile: -------------------------------------------------------------------------------- 1 | #======================================================================= 2 | # 6.375 Makefile for dc-synth 3 | #----------------------------------------------------------------------- 4 | # 5 | # This makefile will use Cadence RTL Compiler to synthesize 6 | # your RTL into a gate-level verilog netlist. 7 | # 8 | 9 | default : all 10 | 11 | #basedir = $(PROJ_DIR) 12 | 13 | #-------------------------------------------------------------------- 14 | # Sources 15 | #-------------------------------------------------------------------- 16 | 17 | include Makefile.common 18 | 19 | # get source verilog filenames and toplevel module name 20 | include Makefile.include 21 | 22 | # default clock frequency of 1 GHz 23 | CLOCK_PERIOD = 1000.0 24 | IS_SET_FROM_CMD = 0 25 | 26 | #-------------------------------------------------------------------- 27 | # Build rules 28 | #-------------------------------------------------------------------- 29 | 30 | build_suffix := $(shell date +%Y-%m-%d_%H-%M-%S) 31 | build_dir := build-$(build_suffix) 32 | curr_build_dir := current 33 | curr_build_dir_tstamp := current/timestamp.txt 34 | 35 | synth_tcl := synth.tcl 36 | libs_tcl := libs.tcl 37 | synth_sdc := synth.sdc 38 | scripts := $(synth_tcl) $(libs_tcl) $(synth_sdc) 39 | makegen_tcl := make_generated_vars.tcl 40 | 41 | synth_vars = \ 42 | set DESIGN_RTL_DIR { $(RTL_FILES_ROOT) $(SEARCH_PATHS) }; \ 43 | set DESIGN_RTL { $(RTL_FILES) }; \ 44 | set DESIGN_TOPLEVEL $(TOPLEVEL); \ 45 | set SYNTH_LIB { $(SYNTH_LIB) }; \ 46 | set CLOCK_PERIOD $(CLOCK_PERIOD); \ 47 | set IS_SET_FROM_CMD $(IS_SET_FROM_CMD); \ 48 | 49 | define new-build-dir-cmds 50 | mkdir $(build_dir) 51 | rm -f $(curr_build_dir) 52 | ln -s $(build_dir) $(curr_build_dir) 53 | cp $(scripts) $(curr_build_dir) 54 | echo '$(synth_vars)' > $(curr_build_dir)/$(makegen_tcl) 55 | endef 56 | 57 | new-build-dir : 58 | $(new-build-dir-cmds) 59 | 60 | %.v : 61 | true 62 | 63 | synth : $(vsrcs) $(scripts) 64 | $(new-build-dir-cmds) 65 | cd $(curr_build_dir); \ 66 | dc_shell-xg-t -64bit $(OPTS) -f $(synth_tcl) | tee dc.log; \ 67 | 68 | 69 | junk += 70 | 71 | .PHONY : synth new-build-dir 72 | 73 | #-------------------------------------------------------------------- 74 | # Default make target 75 | #-------------------------------------------------------------------- 76 | 77 | all : synth 78 | 79 | #-------------------------------------------------------------------- 80 | # Clean up 81 | #-------------------------------------------------------------------- 82 | 83 | clean : 84 | rm -rf build-[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]_[0-9][0-9]-[0-9][0-9] \ 85 | current $(junk) *~ \#* 86 | -------------------------------------------------------------------------------- /src/scripts/flow_pifo/dc/Makefile: -------------------------------------------------------------------------------- 1 | #======================================================================= 2 | # 6.375 Makefile for dc-synth 3 | #----------------------------------------------------------------------- 4 | # 5 | # This makefile will use Cadence RTL Compiler to synthesize 6 | # your RTL into a gate-level verilog netlist. 7 | # 8 | 9 | default : all 10 | 11 | #basedir = $(PROJ_DIR) 12 | 13 | #-------------------------------------------------------------------- 14 | # Sources 15 | #-------------------------------------------------------------------- 16 | 17 | include Makefile.common 18 | 19 | # get source verilog filenames and toplevel module name 20 | include Makefile.include 21 | 22 | # default clock frequency of 1 GHz 23 | CLOCK_PERIOD = 1000.0 24 | IS_SET_FROM_CMD = 0 25 | 26 | #-------------------------------------------------------------------- 27 | # Build rules 28 | #-------------------------------------------------------------------- 29 | 30 | build_suffix := $(shell date +%Y-%m-%d_%H-%M-%S) 31 | build_dir := build-$(build_suffix) 32 | curr_build_dir := current 33 | curr_build_dir_tstamp := current/timestamp.txt 34 | 35 | synth_tcl := synth.tcl 36 | libs_tcl := libs.tcl 37 | synth_sdc := synth.sdc 38 | scripts := $(synth_tcl) $(libs_tcl) $(synth_sdc) 39 | makegen_tcl := make_generated_vars.tcl 40 | 41 | synth_vars = \ 42 | set DESIGN_RTL_DIR { $(RTL_FILES_ROOT) $(SEARCH_PATHS) }; \ 43 | set DESIGN_RTL { $(RTL_FILES) }; \ 44 | set DESIGN_TOPLEVEL $(TOPLEVEL); \ 45 | set SYNTH_LIB { $(SYNTH_LIB) }; \ 46 | set CLOCK_PERIOD $(CLOCK_PERIOD); \ 47 | set IS_SET_FROM_CMD $(IS_SET_FROM_CMD); \ 48 | 49 | define new-build-dir-cmds 50 | mkdir $(build_dir) 51 | rm -f $(curr_build_dir) 52 | ln -s $(build_dir) $(curr_build_dir) 53 | cp $(scripts) $(curr_build_dir) 54 | echo '$(synth_vars)' > $(curr_build_dir)/$(makegen_tcl) 55 | endef 56 | 57 | new-build-dir : 58 | $(new-build-dir-cmds) 59 | 60 | %.v : 61 | true 62 | 63 | synth : $(vsrcs) $(scripts) 64 | $(new-build-dir-cmds) 65 | cd $(curr_build_dir); \ 66 | dc_shell-xg-t -64bit $(OPTS) -f $(synth_tcl) | tee dc.log; \ 67 | 68 | 69 | junk += 70 | 71 | .PHONY : synth new-build-dir 72 | 73 | #-------------------------------------------------------------------- 74 | # Default make target 75 | #-------------------------------------------------------------------- 76 | 77 | all : synth 78 | 79 | #-------------------------------------------------------------------- 80 | # Clean up 81 | #-------------------------------------------------------------------- 82 | 83 | clean : 84 | rm -rf build-[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]_[0-9][0-9]-[0-9][0-9] \ 85 | current $(junk) *~ \#* 86 | -------------------------------------------------------------------------------- /src/rtl/testbench/common/traffic_receiver.v: -------------------------------------------------------------------------------- 1 | module traffic_receiver ( 2 | clk, 3 | reset, 4 | 5 | i__config, 6 | i__receive_phase, 7 | i__phase_count, 8 | 9 | i__pifo_ready, 10 | i__packet_flow_id, 11 | i__packet_priority, 12 | 13 | o__dequeue 14 | ); 15 | 16 | `include "common_tb_headers.vh" 17 | 18 | //------------------------------------------------------------------------------ 19 | // Interface signals 20 | //------------------------------------------------------------------------------ 21 | input logic clk; 22 | input logic reset; 23 | input TRConfig i__config; 24 | input logic i__receive_phase; 25 | input CounterSignal i__phase_count; 26 | input logic i__pifo_ready; 27 | input FlowId i__packet_flow_id; 28 | input Priority i__packet_priority; 29 | output logic o__dequeue; 30 | 31 | //------------------------------------------------------------------------------ 32 | // Internal signals 33 | //------------------------------------------------------------------------------ 34 | TRConfig w__config; 35 | InjectionRate w__lfsr_ejrate; 36 | CounterSignal r__num_pkts_recvd__pff; 37 | logic w__receive_packet; 38 | 39 | //------------------------------------------------------------------------------ 40 | // Output signal assignments 41 | //------------------------------------------------------------------------------ 42 | assign o__dequeue = w__receive_packet; 43 | 44 | //------------------------------------------------------------------------------ 45 | // Sub-modules 46 | //------------------------------------------------------------------------------ 47 | linear_feedback_shift_register 48 | #( 49 | .NUM_BITS ($bits(EjectionRate)) 50 | ) lfsr_ejrate ( 51 | .clk (clk), 52 | .reset (reset), 53 | .i__seed (w__config.ejrate_seed), 54 | .i__next (w__receive_packet), 55 | .o__value (w__lfsr_ejrate) 56 | ); 57 | 58 | //------------------------------------------------------------------------------ 59 | // Combinational logic 60 | //------------------------------------------------------------------------------ 61 | assign w__config = i__config; 62 | assign w__receive_packet = i__receive_phase && i__pifo_ready && (w__lfsr_ejrate < w__config.ejrate); 63 | 64 | //------------------------------------------------------------------------------ 65 | // Sequential logic 66 | //------------------------------------------------------------------------------ 67 | always @(posedge clk) 68 | begin 69 | if (reset) 70 | r__num_pkts_recvd__pff <= '0; 71 | else 72 | r__num_pkts_recvd__pff <= w__receive_packet ? (r__num_pkts_recvd__pff + 1'b1) : r__num_pkts_recvd__pff; 73 | end 74 | 75 | endmodule 76 | -------------------------------------------------------------------------------- /src/rtl/design/clock_gater.v: -------------------------------------------------------------------------------- 1 | 2 | module clock_gater( 3 | //-------------------------------------------------------------------------- 4 | // Global signals 5 | //-------------------------------------------------------------------------- 6 | clk, 7 | reset, 8 | 9 | //-------------------------------------------------------------------------- 10 | // Input interface 11 | //-------------------------------------------------------------------------- 12 | i__enable, 13 | 14 | //-------------------------------------------------------------------------- 15 | // Output interface 16 | //-------------------------------------------------------------------------- 17 | o__gated_clk 18 | ); 19 | 20 | //------------------------------------------------------------------------------ 21 | // Global signals 22 | //------------------------------------------------------------------------------ 23 | input logic clk; 24 | input logic reset; 25 | //------------------------------------------------------------------------------ 26 | 27 | //------------------------------------------------------------------------------ 28 | // Iuput interface 29 | //------------------------------------------------------------------------------ 30 | input logic i__enable; 31 | //------------------------------------------------------------------------------ 32 | 33 | //------------------------------------------------------------------------------ 34 | // Output interface 35 | //------------------------------------------------------------------------------ 36 | output logic o__gated_clk; 37 | //------------------------------------------------------------------------------ 38 | 39 | //------------------------------------------------------------------------------ 40 | // Signals 41 | //------------------------------------------------------------------------------ 42 | logic w__enable_latched; 43 | //------------------------------------------------------------------------------ 44 | 45 | //------------------------------------------------------------------------------ 46 | // Generate gated clock 47 | //------------------------------------------------------------------------------ 48 | `ifndef USE_STDCELL_LATCH 49 | always_latch 50 | begin 51 | if(clk == 1'b0) 52 | begin 53 | w__enable_latched <= i__enable; 54 | end 55 | end 56 | 57 | always_comb 58 | begin 59 | o__gated_clk = clk & w__enable_latched; 60 | end 61 | `else 62 | //PREICG_X1B_A12TH 63 | // latch ( 64 | // .CK (clk), 65 | // .SE (reset), 66 | // .E (i__enable), 67 | // .ECK (o__gated_clk) 68 | // ); 69 | `endif 70 | //------------------------------------------------------------------------------ 71 | 72 | endmodule 73 | 74 | -------------------------------------------------------------------------------- /src/scripts/pifo_set/dc/synth.tcl: -------------------------------------------------------------------------------- 1 | #========================================================================= 2 | # TCL Script File for Synthesis using Cadence RTL Compiler 3 | #------------------------------------------------------------------------- 4 | 5 | # 6 | 7 | # The makefile will generate various variables which we now read in 8 | # and then display 9 | 10 | source make_generated_vars.tcl 11 | 12 | echo "=================================" 13 | echo ${DESIGN_RTL_DIR} "\n" 14 | echo ${DESIGN_RTL} "\n" 15 | echo ${DESIGN_TOPLEVEL} "\n" 16 | echo "=================================" 17 | 18 | set_host_options \ 19 | -max_cores 10 20 | 21 | # The library setup is kept in a separate tcl file which we now source 22 | 23 | source libs.tcl 24 | 25 | set alib_library_analysis_path "/homes/owenhsin/share/ibm_soi12s0_alib/alib" 26 | 27 | set hdlin_sverilog_std 2009 28 | set hdlin_ff_always_async_set_reset true 29 | set hdlin_ff_always_sync_set_reset true 30 | set hdlin_auto_save_templates true 31 | #set hdlin_mux_size_limit 128 32 | # set hdlin_check_no_latch true 33 | set verilogout_show_unconnected_pins true 34 | set compile_fix_multiple_port_ets true 35 | 36 | set fsm_auto_inferring true 37 | set fsm_enable_state_minimization true 38 | set fsm_export_formality_state_info true 39 | 40 | # set hdlin_check_no_latch true 41 | define_name_rules nameRules -restricted "!@#$%^&*()\\-" -case_insensitive 42 | set verilogout_show_unconnected_pins "true" 43 | 44 | sh mkdir analyzed 45 | define_design_lib WORK -path analyzed 46 | 47 | # These two commands read in your verilog source and elaborate it 48 | 49 | analyze -f sverilog ${DESIGN_RTL} -vcs "+define+USE_STDCELL_LATCH" 50 | elaborate -lib WORK ${DESIGN_TOPLEVEL} -update 51 | #elaborate -lib WORK router -update 52 | 53 | set_fix_multiple_port_nets -all -buffer_constants [get_designs *] 54 | 55 | # This command will check your design for any errors 56 | 57 | current_design ${DESIGN_TOPLEVEL} 58 | check_design 59 | 60 | #ungroup rtr -flatten 61 | #ungroup -all -flatten 62 | 63 | link 64 | uniquify 65 | check_design 66 | 67 | # We now load in the constraints file 68 | 69 | source synth.sdc 70 | 71 | report_timing -loops 72 | 73 | # This actually does the synthesis. The -effort option indicates 74 | # how much time the synthesizer should spend optimizing your design to 75 | # gates. Setting it to high means synthesis will take longer but will 76 | # probably produce better results. 77 | 78 | echo "======START COMPILATION===========================\n\n\n" 79 | #list_designs 80 | 81 | compile_ultra -timing_high_effort_script 82 | 83 | #compile -map_effort medium 84 | #compile -map_effort high 85 | #compile_ultra -timing_high_effort_script -no_autoungroup 86 | #compile_ultra 87 | #compile_ultra -no_autoungroup 88 | #compile_ultra -timing_high_effort_script 89 | 90 | echo "======END COMPILATION=============================\n\n\n" 91 | 92 | 93 | report_timing -loops 94 | 95 | # Make sure we are at the top level 96 | set current_design ${DESIGN_TOPLEVEL} 97 | change_names -rules verilog -hierarchy -verbose 98 | change_names -rules nameRules -hierarchy -verbose 99 | 100 | # We write out the results as a verilog netlist 101 | 102 | write -format verilog -hierarchy -output [format "%s%s" ${DESIGN_TOPLEVEL} ".gate.v"] 103 | 104 | # Write out the delay information to the sdf file 105 | write_sdf [format "%s%s" ${DESIGN_TOPLEVEL} ".gate.sdf"] 106 | write_sdc [format "%s%s" ${DESIGN_TOPLEVEL} ".gate.sdc"] 107 | 108 | # We create a timing report for the worst case timing path, 109 | # an area report for each reference in the heirachy and a DRC report 110 | 111 | report_timing > [format "%s%s" ${DESIGN_TOPLEVEL} ".timing.rpt"] 112 | report_area -hierarchy > [format "%s%s" ${DESIGN_TOPLEVEL} ".area.rpt"] 113 | report_power > [format "%s%s" ${DESIGN_TOPLEVEL} ".power.rpt"] 114 | 115 | # Used to exit the Design Compiler 116 | 117 | quit 118 | -------------------------------------------------------------------------------- /src/scripts/flow_pifo/dc/synth.tcl: -------------------------------------------------------------------------------- 1 | #========================================================================= 2 | # TCL Script File for Synthesis using Cadence RTL Compiler 3 | #------------------------------------------------------------------------- 4 | 5 | # 6 | 7 | # The makefile will generate various variables which we now read in 8 | # and then display 9 | 10 | source make_generated_vars.tcl 11 | 12 | echo "=================================" 13 | echo ${DESIGN_RTL_DIR} "\n" 14 | echo ${DESIGN_RTL} "\n" 15 | echo ${DESIGN_TOPLEVEL} "\n" 16 | echo "=================================" 17 | 18 | set_host_options \ 19 | -max_cores 10 20 | 21 | # The library setup is kept in a separate tcl file which we now source 22 | 23 | source libs.tcl 24 | 25 | set alib_library_analysis_path "/homes/owenhsin/share/ibm_soi12s0_alib/alib" 26 | 27 | set hdlin_sverilog_std 2009 28 | set hdlin_ff_always_async_set_reset true 29 | set hdlin_ff_always_sync_set_reset true 30 | set hdlin_auto_save_templates true 31 | #set hdlin_mux_size_limit 128 32 | # set hdlin_check_no_latch true 33 | set verilogout_show_unconnected_pins true 34 | set compile_fix_multiple_port_ets true 35 | 36 | set fsm_auto_inferring true 37 | set fsm_enable_state_minimization true 38 | set fsm_export_formality_state_info true 39 | 40 | # set hdlin_check_no_latch true 41 | define_name_rules nameRules -restricted "!@#$%^&*()\\-" -case_insensitive 42 | set verilogout_show_unconnected_pins "true" 43 | 44 | sh mkdir analyzed 45 | define_design_lib WORK -path analyzed 46 | 47 | # These two commands read in your verilog source and elaborate it 48 | 49 | analyze -f sverilog ${DESIGN_RTL} -vcs "+define+USE_STDCELL_LATCH" 50 | elaborate -lib WORK ${DESIGN_TOPLEVEL} -update 51 | #elaborate -lib WORK router -update 52 | 53 | set_fix_multiple_port_nets -all -buffer_constants [get_designs *] 54 | 55 | # This command will check your design for any errors 56 | 57 | current_design ${DESIGN_TOPLEVEL} 58 | check_design 59 | 60 | #ungroup rtr -flatten 61 | #ungroup -all -flatten 62 | 63 | link 64 | uniquify 65 | check_design 66 | 67 | # We now load in the constraints file 68 | 69 | source synth.sdc 70 | 71 | report_timing -loops 72 | 73 | # This actually does the synthesis. The -effort option indicates 74 | # how much time the synthesizer should spend optimizing your design to 75 | # gates. Setting it to high means synthesis will take longer but will 76 | # probably produce better results. 77 | 78 | echo "======START COMPILATION===========================\n\n\n" 79 | #list_designs 80 | 81 | #compile_ultra -timing_high_effort_script 82 | 83 | 84 | compile_ultra -timing_high_effort_script 85 | 86 | #compile -map_effort medium 87 | #compile -map_effort high 88 | #compile_ultra -timing_high_effort_script -no_autoungroup 89 | #compile_ultra 90 | #compile_ultra -no_autoungroup 91 | #compile_ultra -timing_high_effort_script 92 | 93 | echo "======END COMPILATION=============================\n\n\n" 94 | 95 | 96 | report_timing -loops 97 | 98 | # Make sure we are at the top level 99 | set current_design ${DESIGN_TOPLEVEL} 100 | change_names -rules verilog -hierarchy -verbose 101 | change_names -rules nameRules -hierarchy -verbose 102 | 103 | # We write out the results as a verilog netlist 104 | 105 | write -format verilog -hierarchy -output [format "%s%s" ${DESIGN_TOPLEVEL} ".gate.v"] 106 | 107 | # Write out the delay information to the sdf file 108 | write_sdf [format "%s%s" ${DESIGN_TOPLEVEL} ".gate.sdf"] 109 | write_sdc [format "%s%s" ${DESIGN_TOPLEVEL} ".gate.sdc"] 110 | 111 | # We create a timing report for the worst case timing path, 112 | # an area report for each reference in the heirachy and a DRC report 113 | 114 | report_timing > [format "%s%s" ${DESIGN_TOPLEVEL} ".timing.rpt"] 115 | report_area -hierarchy > [format "%s%s" ${DESIGN_TOPLEVEL} ".area.rpt"] 116 | report_power > [format "%s%s" ${DESIGN_TOPLEVEL} ".power.rpt"] 117 | 118 | # Used to exit the Design Compiler 119 | 120 | quit 121 | -------------------------------------------------------------------------------- /src/rtl/testbench/common/traffic_generator.v: -------------------------------------------------------------------------------- 1 | module traffic_generator ( 2 | clk, 3 | reset, 4 | 5 | i__config, 6 | i__generate_phase, 7 | i__phase_count, 8 | i__pifo_ready, 9 | 10 | o__packet_flow_id, 11 | o__packet_priority, 12 | o__valid_packet_generated, 13 | o__num_pkts_sent 14 | ); 15 | 16 | `include "common_tb_headers.vh" 17 | 18 | //------------------------------------------------------------------------------ 19 | // Interface signals 20 | //------------------------------------------------------------------------------ 21 | input logic clk; 22 | input logic reset; 23 | input TGConfig i__config; 24 | input logic i__generate_phase; 25 | input CounterSignal i__phase_count; 26 | input logic i__pifo_ready; 27 | 28 | output FlowId o__packet_flow_id; 29 | output Priority o__packet_priority; 30 | output logic o__valid_packet_generated; 31 | output CounterSignal o__num_pkts_sent; 32 | 33 | //------------------------------------------------------------------------------ 34 | // Internal signals 35 | //------------------------------------------------------------------------------ 36 | TGConfig w__config; 37 | InjectionRate w__lfsr_injrate; 38 | FlowId w__packet_flow_id; 39 | Priority w__packet_priority; 40 | logic w__generate_packet; 41 | 42 | CounterSignal r__num_pkts_sent__pff; 43 | logic r__initial__pff; 44 | 45 | //------------------------------------------------------------------------------ 46 | // Output signal assignments 47 | //------------------------------------------------------------------------------ 48 | assign o__packet_flow_id = w__packet_flow_id % NUM_FLOWS; 49 | assign o__packet_priority = w__packet_priority; 50 | assign o__valid_packet_generated = w__generate_packet; 51 | assign o__num_pkts_sent = r__num_pkts_sent__pff; 52 | 53 | //------------------------------------------------------------------------------ 54 | // Sub-modules 55 | //------------------------------------------------------------------------------ 56 | linear_feedback_shift_register 57 | #( 58 | .NUM_BITS ($bits(InjectionRate)) 59 | ) lfsr_injrate ( 60 | .clk (clk), 61 | .reset (reset), 62 | .i__seed (w__config.injrate_seed), 63 | .i__next (i__generate_phase), 64 | .o__value (w__lfsr_injrate) 65 | ); 66 | 67 | linear_feedback_shift_register 68 | #( 69 | .NUM_BITS ($bits(Priority)) 70 | ) lfsr_prio ( 71 | .clk (clk), 72 | .reset (reset), 73 | .i__seed (w__config.priority_seed), 74 | .i__next (w__generate_packet), 75 | .o__value (w__packet_priority) 76 | ); 77 | 78 | linear_feedback_shift_register 79 | #( 80 | .NUM_BITS ($bits(FlowId)) 81 | ) lfsr_pkt_pointer ( 82 | .clk (clk), 83 | .reset (reset), 84 | .i__seed (w__config.flow_id_seed), 85 | .i__next (w__generate_packet), 86 | .o__value (w__packet_flow_id) 87 | ); 88 | 89 | //------------------------------------------------------------------------------ 90 | // Combinational logic 91 | //------------------------------------------------------------------------------ 92 | assign w__config = i__config; 93 | assign w__generate_packet = i__generate_phase && i__pifo_ready && (r__num_pkts_sent__pff < w__config.total_packets) 94 | && (w__lfsr_injrate < w__config.injrate) && r__initial__pff; 95 | 96 | //------------------------------------------------------------------------------ 97 | // Sequential logic 98 | //------------------------------------------------------------------------------ 99 | always_ff @(posedge clk) 100 | begin 101 | if (reset) 102 | begin 103 | r__num_pkts_sent__pff <= '0; 104 | r__initial__pff <= 1'b0; 105 | end 106 | else 107 | begin 108 | r__num_pkts_sent__pff <= w__generate_packet ? (r__num_pkts_sent__pff + 1'b1) : r__num_pkts_sent__pff; 109 | r__initial__pff <= 1'b1; 110 | end 111 | end 112 | 113 | 114 | endmodule 115 | -------------------------------------------------------------------------------- /src/rtl/design/counter.v: -------------------------------------------------------------------------------- 1 | module counter( 2 | //-------------------------------------------------------------------------- 3 | // Global signals 4 | //-------------------------------------------------------------------------- 5 | clk, 6 | reset, 7 | 8 | //-------------------------------------------------------------------------- 9 | // Input interface 10 | //-------------------------------------------------------------------------- 11 | i__inc, 12 | 13 | //-------------------------------------------------------------------------- 14 | // Output interface 15 | //-------------------------------------------------------------------------- 16 | o__count, 17 | o__count__next 18 | ); 19 | 20 | //------------------------------------------------------------------------------ 21 | // Parameters 22 | //------------------------------------------------------------------------------ 23 | parameter NUM_COUNT = 8; 24 | parameter COUNT_WIDTH = $clog2(NUM_COUNT); 25 | parameter INIT_VALUE = 1'b0; 26 | //------------------------------------------------------------------------------ 27 | 28 | //------------------------------------------------------------------------------ 29 | // Global signals 30 | //------------------------------------------------------------------------------ 31 | input logic clk; 32 | input logic reset; 33 | //------------------------------------------------------------------------------ 34 | 35 | //------------------------------------------------------------------------------ 36 | // Input interface 37 | //------------------------------------------------------------------------------ 38 | input logic i__inc; 39 | //------------------------------------------------------------------------------ 40 | 41 | //------------------------------------------------------------------------------ 42 | // Output interface 43 | //------------------------------------------------------------------------------ 44 | output logic [COUNT_WIDTH-1:0] o__count; 45 | output logic [COUNT_WIDTH-1:0] o__count__next; 46 | //------------------------------------------------------------------------------ 47 | 48 | //------------------------------------------------------------------------------ 49 | // Internal signals 50 | //------------------------------------------------------------------------------ 51 | logic [COUNT_WIDTH-1:0] w__max_count; 52 | logic [COUNT_WIDTH-1:0] r__count__pff; 53 | logic [COUNT_WIDTH-1:0] w__count__next; 54 | //------------------------------------------------------------------------------ 55 | 56 | //------------------------------------------------------------------------------ 57 | // Output assignments 58 | //------------------------------------------------------------------------------ 59 | assign o__count = r__count__pff; 60 | assign o__count__next = w__count__next; 61 | //------------------------------------------------------------------------------ 62 | 63 | //------------------------------------------------------------------------------ 64 | // Max count logic 65 | //------------------------------------------------------------------------------ 66 | always_comb 67 | begin 68 | // To eliminate the 32-bit to ?-bit conversion warnings 69 | w__max_count = NUM_COUNT - 1'b1; 70 | end 71 | //------------------------------------------------------------------------------ 72 | 73 | //------------------------------------------------------------------------------ 74 | // Count logic 75 | //------------------------------------------------------------------------------ 76 | always_comb 77 | begin 78 | w__count__next = r__count__pff; 79 | 80 | if(i__inc == 1'b1) 81 | begin 82 | if(r__count__pff == w__max_count) 83 | begin 84 | w__count__next = '0; 85 | end 86 | else 87 | begin 88 | w__count__next = r__count__pff + 1'b1; 89 | end 90 | end 91 | end 92 | 93 | always_ff @ (posedge clk) 94 | begin 95 | if(reset == 1'b1) 96 | begin 97 | r__count__pff <= INIT_VALUE; 98 | end 99 | else 100 | begin 101 | r__count__pff <= w__count__next; 102 | end 103 | end 104 | //------------------------------------------------------------------------------ 105 | 106 | endmodule 107 | 108 | -------------------------------------------------------------------------------- /src/rtl/design/fifo.v: -------------------------------------------------------------------------------- 1 | 2 | // First-word fall-through synchronous FIFO with synchronous reset 3 | module fifo( 4 | //-------------------------------------------------------------------------- 5 | // Global signals 6 | //-------------------------------------------------------------------------- 7 | clk, 8 | reset, 9 | 10 | //-------------------------------------------------------------------------- 11 | // Input interface 12 | //-------------------------------------------------------------------------- 13 | i__data_in_valid, 14 | i__data_in, 15 | o__data_in_ready, 16 | o__data_in_ready__next, 17 | 18 | //-------------------------------------------------------------------------- 19 | // Output interface 20 | //-------------------------------------------------------------------------- 21 | o__data_out_valid, 22 | o__data_out, 23 | i__data_out_ready 24 | ); 25 | 26 | //------------------------------------------------------------------------------ 27 | // Parameters 28 | //------------------------------------------------------------------------------ 29 | parameter MULTI_ISSUE = 1'b0; 30 | parameter BYPASS_ENABLE = 1'b0; 31 | parameter DATA_WIDTH = 64; 32 | parameter DEPTH = 3; 33 | //------------------------------------------------------------------------------ 34 | 35 | //------------------------------------------------------------------------------ 36 | // Constants 37 | //------------------------------------------------------------------------------ 38 | localparam ADDR_WIDTH = $clog2(DEPTH); 39 | //------------------------------------------------------------------------------ 40 | 41 | //------------------------------------------------------------------------------ 42 | // Global signals 43 | //------------------------------------------------------------------------------ 44 | input logic clk; 45 | input logic reset; 46 | //------------------------------------------------------------------------------ 47 | 48 | //------------------------------------------------------------------------------ 49 | // Input interface 50 | //------------------------------------------------------------------------------ 51 | input logic i__data_in_valid; 52 | input logic [DATA_WIDTH-1:0] i__data_in; 53 | output logic o__data_in_ready; 54 | output logic o__data_in_ready__next; 55 | //------------------------------------------------------------------------------ 56 | 57 | //------------------------------------------------------------------------------ 58 | // Output interface 59 | //------------------------------------------------------------------------------ 60 | output logic o__data_out_valid; 61 | output logic [DATA_WIDTH-1:0] o__data_out; 62 | input logic i__data_out_ready; 63 | //------------------------------------------------------------------------------ 64 | 65 | 66 | //------------------------------------------------------------------------------ 67 | // Sub-modules 68 | //------------------------------------------------------------------------------ 69 | generate 70 | if(BYPASS_ENABLE == 1'b0) 71 | begin: no_bypass 72 | fifo_base 73 | #( 74 | .DATA_WIDTH (DATA_WIDTH), 75 | .DEPTH (DEPTH), 76 | .MULTI_ISSUE (MULTI_ISSUE) 77 | ) 78 | base( 79 | .clk (clk), 80 | .reset (reset), 81 | 82 | .i__data_in_valid (i__data_in_valid), 83 | .i__data_in (i__data_in), 84 | .o__data_in_ready (o__data_in_ready), 85 | .o__data_in_ready__next (o__data_in_ready__next), 86 | 87 | .o__data_out_valid (o__data_out_valid), 88 | .o__data_out (o__data_out), 89 | .i__data_out_ready (i__data_out_ready), 90 | .oa__all_data (), 91 | .i__clear_all ('0) 92 | ); 93 | end 94 | else 95 | begin: bypass 96 | fifo_base_bypass 97 | #( 98 | .DATA_WIDTH (DATA_WIDTH), 99 | .DEPTH (DEPTH), 100 | .MULTI_ISSUE (MULTI_ISSUE) 101 | ) 102 | base ( 103 | .clk (clk), 104 | .reset (reset), 105 | 106 | .i__data_in_valid (i__data_in_valid), 107 | .i__data_in (i__data_in), 108 | .o__data_in_ready (o__data_in_ready), 109 | .o__data_in_ready__next (o__data_in_ready__next), 110 | 111 | .o__data_out_valid (o__data_out_valid), 112 | .o__data_out (o__data_out), 113 | .i__data_out_ready (i__data_out_ready), 114 | .oa__all_data (), 115 | .i__clear_all ('0) 116 | ); 117 | end 118 | endgenerate 119 | 120 | endmodule 121 | 122 | -------------------------------------------------------------------------------- /src/rtl/design/prefetch_buffer.v: -------------------------------------------------------------------------------- 1 | module prefetch_buffer ( 2 | //-------------------------------------------------------------------------- 3 | // Global signals 4 | //-------------------------------------------------------------------------- 5 | clk, 6 | reset, 7 | 8 | //-------------------------------------------------------------------------- 9 | // Input interface 10 | //-------------------------------------------------------------------------- 11 | i__push_valid, 12 | i__push_flow_id, 13 | i__push_data, // For our application, this will be priority 14 | o__push_flow_not_full, 15 | 16 | i__reinsert_valid, 17 | i__reinsert_data, 18 | 19 | //-------------------------------------------------------------------------- 20 | // Output interface 21 | //-------------------------------------------------------------------------- 22 | o__pop_data, 23 | o__pop_valid, 24 | i__pop_flow_id, 25 | i__pop 26 | ); 27 | 28 | //------------------------------------------------------------------------------ 29 | // Parameters 30 | //------------------------------------------------------------------------------ 31 | parameter NUM_FLOWS = (16); 32 | parameter DEPTH = (1); 33 | parameter DATA_WIDTH = (8); 34 | 35 | //------------------------------------------------------------------------------ 36 | // Constants 37 | //------------------------------------------------------------------------------ 38 | localparam IDX_WIDTH = $clog2(NUM_FLOWS+1); 39 | 40 | //------------------------------------------------------------------------------ 41 | // Global signals 42 | //------------------------------------------------------------------------------ 43 | input logic clk; 44 | input logic reset; 45 | 46 | //------------------------------------------------------------------------------ 47 | // Input interface 48 | //------------------------------------------------------------------------------ 49 | input logic i__push_valid; 50 | input logic [IDX_WIDTH-1:0] i__push_flow_id; 51 | input logic [DATA_WIDTH-1:0] i__push_data; 52 | output logic o__push_flow_not_full; 53 | 54 | input logic i__reinsert_valid; 55 | input logic [DATA_WIDTH-1:0] i__reinsert_data; 56 | 57 | //------------------------------------------------------------------------------ 58 | // Output interface 59 | //------------------------------------------------------------------------------ 60 | output logic [DATA_WIDTH-1:0] o__pop_data; 61 | output logic o__pop_valid; 62 | input logic [IDX_WIDTH-1:0] i__pop_flow_id; 63 | input logic i__pop; 64 | 65 | //------------------------------------------------------------------------------ 66 | // Signals 67 | //------------------------------------------------------------------------------ 68 | logic [NUM_FLOWS-1:0] w__fifo_enqueue; 69 | logic [DATA_WIDTH-1:0] w__fifo_data_out [NUM_FLOWS-1:0]; 70 | logic [DATA_WIDTH-1:0] w__fifo_data_in [NUM_FLOWS-1:0]; 71 | logic [NUM_FLOWS-1:0] w__fifo_data_in_ready; 72 | logic [NUM_FLOWS-1:0] w__fifo_data_in_ready__next; 73 | logic [NUM_FLOWS-1:0] w__fifo_data_out_ready; 74 | logic [NUM_FLOWS-1:0] w__fifo_data_out_valid; 75 | 76 | 77 | //------------------------------------------------------------------------------ 78 | // Sub-modules 79 | //------------------------------------------------------------------------------ 80 | genvar flow_idx; 81 | generate for(flow_idx = 0; flow_idx < NUM_FLOWS; flow_idx = flow_idx + 1) 82 | begin: gen_prefetch_fifo 83 | fifo #( 84 | .BYPASS_ENABLE (1'b0), 85 | .DATA_WIDTH (DATA_WIDTH), 86 | .MULTI_ISSUE (1'b1), 87 | .DEPTH (DEPTH) 88 | ) prefetch_fifo ( 89 | .clk (clk), 90 | .reset (reset), 91 | 92 | .i__data_in_valid (w__fifo_enqueue[flow_idx]), 93 | .i__data_in (w__fifo_data_in[flow_idx]), 94 | .o__data_in_ready (w__fifo_data_in_ready[flow_idx]), 95 | .o__data_in_ready__next (w__fifo_data_in_ready__next[flow_idx]), 96 | 97 | .o__data_out_valid (w__fifo_data_out_valid[flow_idx]), 98 | .o__data_out (w__fifo_data_out[flow_idx]), 99 | .i__data_out_ready (w__fifo_data_out_ready[flow_idx]) 100 | ); 101 | end 102 | endgenerate 103 | 104 | //------------------------------------------------------------------------------ 105 | // Output assignments 106 | //------------------------------------------------------------------------------ 107 | assign o__pop_data = w__fifo_data_out[i__pop_flow_id]; 108 | assign o__push_flow_not_full= w__fifo_data_in_ready[i__push_flow_id]; 109 | assign o__pop_valid = w__fifo_data_out_valid[i__pop_flow_id]; 110 | 111 | //------------------------------------------------------------------------------ 112 | // Combinational logic 113 | //------------------------------------------------------------------------------ 114 | genvar fid; 115 | generate for(fid = 0; fid < NUM_FLOWS; fid = fid + 1) 116 | begin: gen_flow_fifo 117 | always_comb 118 | begin 119 | if ( (i__push_valid && (i__push_flow_id == fid)) || 120 | (i__reinsert_valid && (i__pop_flow_id == fid)) ) 121 | w__fifo_enqueue[fid] = 1'b1; 122 | else 123 | w__fifo_enqueue[fid] = 1'b0; 124 | end 125 | 126 | always_comb 127 | begin 128 | if (i__push_valid && (i__push_flow_id == fid)) 129 | w__fifo_data_in[fid] = i__push_data; 130 | else if (i__reinsert_valid && (i__pop_flow_id == fid)) 131 | w__fifo_data_in[fid] = i__reinsert_data; 132 | else 133 | w__fifo_data_in[fid] = '0; 134 | end 135 | 136 | always_comb 137 | begin 138 | if (i__pop && (i__pop_flow_id == fid)) 139 | w__fifo_data_out_ready[fid] = 1'b1; 140 | else 141 | w__fifo_data_out_ready[fid] = 1'b0; 142 | end 143 | 144 | end 145 | endgenerate 146 | 147 | 148 | 149 | endmodule 150 | -------------------------------------------------------------------------------- /src/rtl/design/fifo_bank.v: -------------------------------------------------------------------------------- 1 | // [ssub] The fifo bank is identical (behaviorally) to the prefetch buffer. The 2 | // only difference is how the actual elements are stored (registers/FFs or 3 | // SRAM). For now, both use registers, but feel free to change the 4 | // "sub-modules" below to use SRAMs or other memory elements are required. 5 | // There is an opportunity to get more modularity here, since now we just have 6 | // replicated code, which is not good. FIXME 7 | module fifo_bank ( 8 | //-------------------------------------------------------------------------- 9 | // Global signals 10 | //-------------------------------------------------------------------------- 11 | clk, 12 | reset, 13 | 14 | //-------------------------------------------------------------------------- 15 | // Input interface 16 | //-------------------------------------------------------------------------- 17 | i__push_valid, 18 | i__push_flow_id, 19 | i__push_data, // For our application, this will be priority 20 | o__push_flow_not_full, 21 | 22 | i__reinsert_valid, 23 | i__reinsert_data, 24 | 25 | //-------------------------------------------------------------------------- 26 | // Output interface 27 | //-------------------------------------------------------------------------- 28 | o__pop_data, 29 | o__pop_valid, 30 | i__pop_flow_id, 31 | i__pop 32 | ); 33 | 34 | //------------------------------------------------------------------------------ 35 | // Parameters 36 | //------------------------------------------------------------------------------ 37 | parameter NUM_FLOWS = (16); 38 | parameter DEPTH = (10); 39 | parameter DATA_WIDTH = (8); 40 | 41 | //------------------------------------------------------------------------------ 42 | // Constants 43 | //------------------------------------------------------------------------------ 44 | localparam IDX_WIDTH = $clog2(NUM_FLOWS+1); 45 | 46 | //------------------------------------------------------------------------------ 47 | // Global signals 48 | //------------------------------------------------------------------------------ 49 | input logic clk; 50 | input logic reset; 51 | 52 | //------------------------------------------------------------------------------ 53 | // Input interface 54 | //------------------------------------------------------------------------------ 55 | input logic i__push_valid; 56 | input logic [IDX_WIDTH-1:0] i__push_flow_id; 57 | input logic [DATA_WIDTH-1:0] i__push_data; 58 | output logic o__push_flow_not_full; 59 | 60 | input logic i__reinsert_valid; 61 | input logic [DATA_WIDTH-1:0] i__reinsert_data; 62 | 63 | //------------------------------------------------------------------------------ 64 | // Output interface 65 | //------------------------------------------------------------------------------ 66 | output logic [DATA_WIDTH-1:0] o__pop_data; 67 | output logic o__pop_valid; 68 | input logic [IDX_WIDTH-1:0] i__pop_flow_id; 69 | input logic i__pop; 70 | 71 | //------------------------------------------------------------------------------ 72 | // Signals 73 | //------------------------------------------------------------------------------ 74 | logic [NUM_FLOWS-1:0] w__fifo_enqueue; 75 | logic [DATA_WIDTH-1:0] w__fifo_data_out [NUM_FLOWS-1:0]; 76 | logic [DATA_WIDTH-1:0] w__fifo_data_in [NUM_FLOWS-1:0]; 77 | logic [NUM_FLOWS-1:0] w__fifo_data_in_ready; 78 | logic [NUM_FLOWS-1:0] w__fifo_data_in_ready__next; 79 | logic [NUM_FLOWS-1:0] w__fifo_data_out_ready; 80 | logic [NUM_FLOWS-1:0] w__fifo_data_out_valid; 81 | 82 | 83 | //------------------------------------------------------------------------------ 84 | // Sub-modules 85 | //------------------------------------------------------------------------------ 86 | genvar flow_idx; 87 | generate for(flow_idx = 0; flow_idx < NUM_FLOWS; flow_idx = flow_idx + 1) 88 | begin: gen_prefetch_fifo 89 | fifo #( 90 | .BYPASS_ENABLE (1'b0), 91 | .DATA_WIDTH (DATA_WIDTH), 92 | .MULTI_ISSUE (1'b0), // TODO This can optionally be made MULTI_ISSUE 93 | .DEPTH (DEPTH) 94 | ) fifobank_fifo ( 95 | .clk (clk), 96 | .reset (reset), 97 | 98 | .i__data_in_valid (w__fifo_enqueue[flow_idx]), 99 | .i__data_in (w__fifo_data_in[flow_idx]), 100 | .o__data_in_ready (w__fifo_data_in_ready[flow_idx]), 101 | .o__data_in_ready__next (w__fifo_data_in_ready__next[flow_idx]), 102 | 103 | .o__data_out_valid (w__fifo_data_out_valid[flow_idx]), 104 | .o__data_out (w__fifo_data_out[flow_idx]), 105 | .i__data_out_ready (w__fifo_data_out_ready[flow_idx]) 106 | ); 107 | end 108 | endgenerate 109 | 110 | //------------------------------------------------------------------------------ 111 | // Output assignments 112 | //------------------------------------------------------------------------------ 113 | assign o__pop_data = w__fifo_data_out[i__pop_flow_id]; 114 | assign o__push_flow_not_full= w__fifo_data_in_ready[i__push_flow_id]; 115 | assign o__pop_valid = w__fifo_data_out_valid[i__pop_flow_id]; 116 | 117 | //------------------------------------------------------------------------------ 118 | // Combinational logic 119 | //------------------------------------------------------------------------------ 120 | genvar fid; 121 | generate for(fid = 0; fid < NUM_FLOWS; fid = fid + 1) 122 | begin: gen_flow_fifo 123 | always_comb 124 | begin 125 | if ( (i__push_valid && (i__push_flow_id == fid)) || 126 | (i__reinsert_valid && (i__pop_flow_id == fid)) ) 127 | w__fifo_enqueue[fid] = 1'b1; 128 | else 129 | w__fifo_enqueue[fid] = 1'b0; 130 | end 131 | 132 | always_comb 133 | begin 134 | if (i__push_valid && (i__push_flow_id == fid)) 135 | w__fifo_data_in[fid] = i__push_data; 136 | else if (i__reinsert_valid && (i__pop_flow_id == fid)) 137 | w__fifo_data_in[fid] = i__reinsert_data; 138 | else 139 | w__fifo_data_in[fid] = '0; 140 | end 141 | 142 | always_comb 143 | begin 144 | if (i__pop && (i__pop_flow_id == fid)) 145 | w__fifo_data_out_ready[fid] = 1'b1; 146 | else 147 | w__fifo_data_out_ready[fid] = 1'b0; 148 | end 149 | 150 | end 151 | endgenerate 152 | 153 | 154 | 155 | endmodule 156 | -------------------------------------------------------------------------------- /src/rtl/design/fifo_base_bypass.v: -------------------------------------------------------------------------------- 1 | 2 | // First-word fall-through synchronous FIFO with synchronous reset 3 | module fifo_base_bypass( 4 | //-------------------------------------------------------------------------- 5 | // Global signals 6 | //-------------------------------------------------------------------------- 7 | clk, 8 | reset, 9 | 10 | //-------------------------------------------------------------------------- 11 | // Input interface 12 | //-------------------------------------------------------------------------- 13 | i__data_in_valid, 14 | i__data_in, 15 | o__data_in_ready, 16 | o__data_in_ready__next, 17 | 18 | //-------------------------------------------------------------------------- 19 | // Output interface 20 | //-------------------------------------------------------------------------- 21 | o__data_out_valid, 22 | o__data_out, 23 | i__data_out_ready, 24 | i__clear_all, 25 | oa__all_data 26 | ); 27 | 28 | //------------------------------------------------------------------------------ 29 | // Parameters 30 | //------------------------------------------------------------------------------ 31 | parameter MULTI_ISSUE = 1'b0; 32 | parameter DATA_WIDTH = 64; 33 | parameter DEPTH = 3; 34 | //------------------------------------------------------------------------------ 35 | 36 | //------------------------------------------------------------------------------ 37 | // Constants 38 | //------------------------------------------------------------------------------ 39 | localparam ADDR_WIDTH = $clog2(DEPTH); 40 | //------------------------------------------------------------------------------ 41 | 42 | //------------------------------------------------------------------------------ 43 | // Global signals 44 | //------------------------------------------------------------------------------ 45 | input logic clk; 46 | input logic reset; 47 | //------------------------------------------------------------------------------ 48 | 49 | //------------------------------------------------------------------------------ 50 | // Input interface 51 | //------------------------------------------------------------------------------ 52 | input logic i__data_in_valid; 53 | input logic [DATA_WIDTH-1:0] i__data_in; 54 | output logic o__data_in_ready; 55 | output logic o__data_in_ready__next; 56 | //------------------------------------------------------------------------------ 57 | 58 | //------------------------------------------------------------------------------ 59 | // Output interface 60 | //------------------------------------------------------------------------------ 61 | output logic o__data_out_valid; 62 | output logic [DATA_WIDTH-1:0] o__data_out; 63 | input logic i__data_out_ready; 64 | input logic i__clear_all; 65 | output logic [DATA_WIDTH-1:0] oa__all_data [0:DEPTH-1]; 66 | //------------------------------------------------------------------------------ 67 | 68 | // Wires 69 | logic w__data_in_valid; 70 | logic [DATA_WIDTH-1:0] w__data_in; 71 | logic w__data_in_ready; 72 | logic w__data_in_ready__next; 73 | logic w__data_out_valid; 74 | logic [DATA_WIDTH-1:0] w__data_out; 75 | logic w__data_out_ready; 76 | 77 | 78 | //------------------------------------------------------------------------------ 79 | // Sub-modules 80 | //------------------------------------------------------------------------------ 81 | fifo_base 82 | #( 83 | .DATA_WIDTH (DATA_WIDTH), 84 | .DEPTH (DEPTH), 85 | .MULTI_ISSUE (MULTI_ISSUE) 86 | ) 87 | base ( 88 | .clk (clk), 89 | .reset (reset), 90 | 91 | .i__data_in_valid (w__data_in_valid), 92 | .i__data_in (w__data_in), 93 | .o__data_in_ready (w__data_in_ready), 94 | .o__data_in_ready__next (w__data_in_ready__next), 95 | 96 | .o__data_out_valid (w__data_out_valid), 97 | .o__data_out (w__data_out), 98 | .i__data_out_ready (w__data_out_ready), 99 | .oa__all_data (oa__all_data), 100 | .i__clear_all (i__clear_all) 101 | ); 102 | //------------------------------------------------------------------------------ 103 | 104 | 105 | //------------------------------------------------------------------------------ 106 | // FIFO base input interface logic 107 | //------------------------------------------------------------------------------ 108 | always_comb 109 | begin 110 | w__data_in_valid = i__data_in_valid; 111 | w__data_in = i__data_in; 112 | 113 | if(w__data_out_valid == 1'b0) 114 | begin 115 | // FIFO base is empty 116 | if((i__data_in_valid == 1'b1) && (i__data_out_ready == 1'b1)) 117 | begin 118 | // If there is a valid incoming data and it is popped out in the same cycle 119 | // - Deassert the data in valid bit so that nothing is inserted into the FIFO 120 | w__data_in_valid = 1'b0; 121 | end 122 | end 123 | end 124 | 125 | always_comb 126 | begin 127 | o__data_in_ready = w__data_in_ready; 128 | o__data_in_ready__next = w__data_in_ready__next; 129 | end 130 | //------------------------------------------------------------------------------ 131 | 132 | //------------------------------------------------------------------------------ 133 | // FIFO base output interface logic 134 | //------------------------------------------------------------------------------ 135 | always_comb 136 | begin 137 | o__data_out_valid = w__data_out_valid; 138 | o__data_out = w__data_out; 139 | 140 | if((w__data_out_valid == 1'b0) && (reset == 1'b0)) 141 | begin 142 | // FIFO base is empty and not in reset phase 143 | if(i__data_in_valid == 1'b1) 144 | begin 145 | // If there is a valid incoming data 146 | // - Assert data out valid bit 147 | // - Forward the incoming data to the output 148 | o__data_out_valid = 1'b1; 149 | o__data_out = i__data_in; 150 | end 151 | end 152 | end 153 | 154 | always_comb 155 | begin 156 | // The FIFO base ignores the ready signal if there is no element in the FIFO 157 | // so it is valid to pass ready signal directly to the FIFO base without any 158 | // condition 159 | w__data_out_ready = i__data_out_ready; 160 | end 161 | //------------------------------------------------------------------------------ 162 | 163 | endmodule 164 | 165 | -------------------------------------------------------------------------------- /src/rtl/design/fifo_init.v: -------------------------------------------------------------------------------- 1 | 2 | module fifo_init( 3 | //-------------------------------------------------------------------------- 4 | // Global signals 5 | //-------------------------------------------------------------------------- 6 | clk, 7 | reset, 8 | 9 | //-------------------------------------------------------------------------- 10 | // Input interface 11 | //-------------------------------------------------------------------------- 12 | i__data_in_valid, 13 | i__data_in, 14 | o__data_in_ready, 15 | 16 | //-------------------------------------------------------------------------- 17 | // Output interface 18 | //-------------------------------------------------------------------------- 19 | o__data_out_valid, 20 | o__data_out, 21 | i__data_out_ready 22 | ); 23 | 24 | //------------------------------------------------------------------------------ 25 | // Parameters 26 | //------------------------------------------------------------------------------ 27 | parameter MULTI_ISSUE = 1'b0; 28 | parameter INIT_VAL = 1'b0; 29 | parameter INC_INIT = 1'b1; 30 | parameter DATA_WIDTH = 64; 31 | parameter DEPTH = 3; 32 | //------------------------------------------------------------------------------ 33 | 34 | //------------------------------------------------------------------------------ 35 | // Constants 36 | //------------------------------------------------------------------------------ 37 | localparam ADDR_WIDTH = $clog2(DEPTH); 38 | typedef enum logic 39 | { 40 | RESET, 41 | READY 42 | } fifo_init_state; 43 | //------------------------------------------------------------------------------ 44 | 45 | //------------------------------------------------------------------------------ 46 | // Global signals 47 | //------------------------------------------------------------------------------ 48 | input logic clk; 49 | input logic reset; 50 | //------------------------------------------------------------------------------ 51 | 52 | //------------------------------------------------------------------------------ 53 | // Input interface 54 | //------------------------------------------------------------------------------ 55 | input logic i__data_in_valid; 56 | input logic [DATA_WIDTH-1:0] i__data_in; 57 | output logic o__data_in_ready; 58 | //------------------------------------------------------------------------------ 59 | 60 | //------------------------------------------------------------------------------ 61 | // Output interface 62 | //------------------------------------------------------------------------------ 63 | output logic o__data_out_valid; 64 | output logic [DATA_WIDTH-1:0] o__data_out; 65 | input logic i__data_out_ready; 66 | //------------------------------------------------------------------------------ 67 | 68 | //------------------------------------------------------------------------------ 69 | // Signals 70 | //------------------------------------------------------------------------------ 71 | logic w__data_in_valid; 72 | logic [DATA_WIDTH-1:0] w__data_in; 73 | logic w__data_in_ready; 74 | logic w__data_out_valid; 75 | logic [DATA_WIDTH-1:0] w__data_out; 76 | logic w__data_out_ready; 77 | logic w__init; 78 | logic w__init_clk; 79 | //------------------------------------------------------------------------------ 80 | 81 | //------------------------------------------------------------------------------ 82 | // States and next signals 83 | //------------------------------------------------------------------------------ 84 | fifo_init_state w__state__next; 85 | fifo_init_state r__state__pff; 86 | logic [ADDR_WIDTH-1:0] w__init_addr__next; 87 | logic [ADDR_WIDTH-1:0] r__init_addr__pff; 88 | //------------------------------------------------------------------------------ 89 | 90 | //------------------------------------------------------------------------------ 91 | // Submodules 92 | //------------------------------------------------------------------------------ 93 | fifo #( .DATA_WIDTH (DATA_WIDTH), 94 | .MULTI_ISSUE (MULTI_ISSUE), 95 | .DEPTH (DEPTH) 96 | ) 97 | fifo ( 98 | .clk (clk), 99 | .reset (reset), 100 | .i__data_in_valid (w__data_in_valid), 101 | .i__data_in (w__data_in), 102 | .o__data_in_ready (w__data_in_ready), 103 | .o__data_in_ready__next (), 104 | .o__data_out_valid (w__data_out_valid), 105 | .o__data_out (w__data_out), 106 | .i__data_out_ready (w__data_out_ready) 107 | ); 108 | 109 | clock_gater 110 | gate_init_clk ( 111 | .clk (clk), 112 | .reset (reset), 113 | .i__enable (w__init), 114 | .o__gated_clk (w__init_clk) 115 | ); 116 | //------------------------------------------------------------------------------ 117 | 118 | //------------------------------------------------------------------------------ 119 | // Block inputs/outputs while resetting 120 | //------------------------------------------------------------------------------ 121 | always_comb 122 | begin 123 | w__data_in_valid = i__data_in_valid; 124 | w__data_in = i__data_in; 125 | o__data_in_ready = w__data_in_ready; 126 | o__data_out_valid = w__data_out_valid; 127 | o__data_out = w__data_out; 128 | w__data_out_ready = i__data_out_ready; 129 | 130 | if(r__state__pff == RESET) 131 | begin 132 | w__data_in_valid = 1'b1; 133 | w__data_in = r__init_addr__pff + INIT_VAL; 134 | o__data_in_ready = 1'b0; 135 | o__data_out_valid = 1'b0; 136 | w__data_out_ready = 1'b0; 137 | end 138 | end 139 | //------------------------------------------------------------------------------ 140 | 141 | //------------------------------------------------------------------------------ 142 | // Switch states between reset and ready mode 143 | //------------------------------------------------------------------------------ 144 | always_comb 145 | begin 146 | w__init_addr__next = r__init_addr__pff; 147 | 148 | if(r__state__pff == RESET) 149 | begin 150 | w__init_addr__next = r__init_addr__pff + 1'b1; 151 | end 152 | end 153 | 154 | always_comb 155 | begin 156 | w__init = 1'b0; 157 | 158 | if((r__state__pff == RESET) || (reset == 1'b1)) 159 | begin 160 | w__init = 1'b1; 161 | end 162 | end 163 | 164 | always_comb 165 | begin 166 | w__state__next = r__state__pff; 167 | 168 | if(r__init_addr__pff == {$unsigned(DEPTH-1)}) 169 | begin 170 | w__state__next = READY; 171 | end 172 | end 173 | 174 | always_ff @ (posedge w__init_clk) 175 | begin 176 | if(reset == 1'b1) 177 | begin 178 | r__state__pff <= RESET; 179 | r__init_addr__pff <= '0; 180 | end 181 | else 182 | begin 183 | r__state__pff <= w__state__next; 184 | r__init_addr__pff <= w__init_addr__next; 185 | end 186 | end 187 | //------------------------------------------------------------------------------ 188 | 189 | endmodule 190 | 191 | -------------------------------------------------------------------------------- /src/rtl/testbench/common/linear_feedback_shift_register.v: -------------------------------------------------------------------------------- 1 | module linear_feedback_shift_register( 2 | clk, 3 | reset, 4 | 5 | i__seed, 6 | 7 | i__next, 8 | o__value 9 | ); 10 | 11 | //------------------------------------------------------------------------------ 12 | // Parameters 13 | //------------------------------------------------------------------------------ 14 | parameter NUM_BITS = 16; 15 | //------------------------------------------------------------------------------ 16 | 17 | //------------------------------------------------------------------------------ 18 | // IO 19 | //------------------------------------------------------------------------------ 20 | input logic clk; 21 | input logic reset; 22 | 23 | input logic [NUM_BITS-1:0] i__seed; 24 | input logic i__next; 25 | output logic [NUM_BITS-1:0] o__value; 26 | //------------------------------------------------------------------------------ 27 | 28 | //------------------------------------------------------------------------------ 29 | // Internal signals 30 | //------------------------------------------------------------------------------ 31 | logic [NUM_BITS-1:0] w__feedback_poly; 32 | logic [NUM_BITS-1:0] w__value__next; 33 | logic [NUM_BITS-1:0] r__value__pff; 34 | //------------------------------------------------------------------------------ 35 | 36 | //------------------------------------------------------------------------------ 37 | // Get next value 38 | //------------------------------------------------------------------------------ 39 | assign o__value = r__value__pff; 40 | 41 | always_comb 42 | begin 43 | w__value__next = r__value__pff; 44 | 45 | if(i__next == 1'b1) 46 | begin 47 | w__value__next = (r__value__pff[0] == 1'b1)? ((r__value__pff >> 1) ^ w__feedback_poly) : (r__value__pff >> 1); 48 | end 49 | end 50 | 51 | always_ff @ (posedge clk) 52 | begin 53 | if(reset == 1'b1) 54 | begin 55 | r__value__pff <= i__seed; 56 | end 57 | else 58 | begin 59 | r__value__pff <= w__value__next; 60 | end 61 | end 62 | //------------------------------------------------------------------------------ 63 | 64 | //------------------------------------------------------------------------------ 65 | // Feedback polynomials 66 | // http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf 67 | //------------------------------------------------------------------------------ 68 | generate 69 | if(NUM_BITS == 2) 70 | begin: b2 71 | assign w__feedback_poly = 2'h3; 72 | end 73 | else if(NUM_BITS == 3) 74 | begin: b3 75 | assign w__feedback_poly = 3'h6; 76 | end 77 | else if(NUM_BITS == 4) 78 | begin: b4 79 | assign w__feedback_poly = 4'hC; 80 | end 81 | else if(NUM_BITS == 5) 82 | begin: b5 83 | assign w__feedback_poly = 5'h14; 84 | end 85 | else if(NUM_BITS == 6) 86 | begin: b6 87 | assign w__feedback_poly = 6'h30; 88 | end 89 | else if(NUM_BITS == 7) 90 | begin: b7 91 | assign w__feedback_poly = 7'h60; 92 | end 93 | else if(NUM_BITS == 8) 94 | begin: b8 95 | assign w__feedback_poly = 8'hB8; 96 | end 97 | else if(NUM_BITS == 9) 98 | begin: b9 99 | assign w__feedback_poly = 9'h110; 100 | end 101 | else if(NUM_BITS == 10) 102 | begin: b10 103 | assign w__feedback_poly = 10'h240; 104 | end 105 | else if(NUM_BITS == 11) 106 | begin: b11 107 | assign w__feedback_poly = 11'h500; 108 | end 109 | else if(NUM_BITS == 12) 110 | begin: b12 111 | assign w__feedback_poly = 12'h809; 112 | end 113 | else if(NUM_BITS == 13) 114 | begin: b13 115 | assign w__feedback_poly = 13'h100D; 116 | end 117 | else if(NUM_BITS == 14) 118 | begin: b14 119 | assign w__feedback_poly = 14'h2015; 120 | end 121 | else if(NUM_BITS == 15) 122 | begin: b15 123 | assign w__feedback_poly = 15'h6000; 124 | end 125 | else if(NUM_BITS == 16) 126 | begin: b16 127 | assign w__feedback_poly = 16'hD008; 128 | end 129 | else if(NUM_BITS == 17) 130 | begin: b17 131 | assign w__feedback_poly = 17'h1_2000; 132 | end 133 | else if(NUM_BITS == 18) 134 | begin: b18 135 | assign w__feedback_poly = 18'h2_0400; 136 | end 137 | else if(NUM_BITS == 19) 138 | begin: b19 139 | assign w__feedback_poly = 19'h4_0023; 140 | end 141 | else if(NUM_BITS == 20) 142 | begin: b20 143 | assign w__feedback_poly = 20'h9_0000; 144 | end 145 | else if(NUM_BITS == 21) 146 | begin: b21 147 | assign w__feedback_poly = 21'h14_0000; 148 | end 149 | else if(NUM_BITS == 22) 150 | begin: b22 151 | assign w__feedback_poly = 22'h30_0000; 152 | end 153 | else if(NUM_BITS == 23) 154 | begin: b23 155 | assign w__feedback_poly = 23'h42_0000; 156 | end 157 | else if(NUM_BITS == 24) 158 | begin: b24 159 | assign w__feedback_poly = 24'hE1_0000; 160 | end 161 | else if(NUM_BITS == 25) 162 | begin: b25 163 | assign w__feedback_poly = 25'h120_0000; 164 | end 165 | else if(NUM_BITS == 26) 166 | begin: b26 167 | assign w__feedback_poly = 26'h200_0023; 168 | end 169 | else if(NUM_BITS == 27) 170 | begin: b27 171 | assign w__feedback_poly = 27'h400_0013; 172 | end 173 | else if(NUM_BITS == 28) 174 | begin: b28 175 | assign w__feedback_poly = 28'h900_0000; 176 | end 177 | else if(NUM_BITS == 29) 178 | begin: b29 179 | assign w__feedback_poly = 29'h1400_0000; 180 | end 181 | else if(NUM_BITS == 30) 182 | begin: b30 183 | assign w__feedback_poly = 30'h2000_0029; 184 | end 185 | else if(NUM_BITS == 31) 186 | begin: b31 187 | assign w__feedback_poly = 31'h4800_0000; 188 | end 189 | else if(NUM_BITS == 32) 190 | begin: b32 191 | assign w__feedback_poly = 32'h8020_0003; 192 | end 193 | else if(NUM_BITS == 33) 194 | begin: b33 195 | assign w__feedback_poly = 33'h1_0008_0000; 196 | end 197 | else if(NUM_BITS == 34) 198 | begin: b34 199 | assign w__feedback_poly = 34'h2_0400_0003; 200 | end 201 | else if(NUM_BITS == 35) 202 | begin: b35 203 | assign w__feedback_poly = 35'h5_0000_0000; 204 | end 205 | else if(NUM_BITS == 36) 206 | begin: b36 207 | assign w__feedback_poly = 36'h8_0100_0000; 208 | end 209 | else if(NUM_BITS == 37) 210 | begin: b37 211 | assign w__feedback_poly = 37'h10_0000_001F; 212 | end 213 | else if(NUM_BITS == 38) 214 | begin: b38 215 | assign w__feedback_poly = 38'h20_0000_0031; 216 | end 217 | else if(NUM_BITS == 39) 218 | begin: b39 219 | assign w__feedback_poly = 39'h44_0000_0000; 220 | end 221 | else if(NUM_BITS == 40) 222 | begin: b40 223 | assign w__feedback_poly = 40'hA0_0014_0000; 224 | end 225 | else if(NUM_BITS == 41) 226 | begin: b41 227 | assign w__feedback_poly = 41'h120_0000_0000; 228 | end 229 | else if(NUM_BITS == 42) 230 | begin: b42 231 | assign w__feedback_poly = 42'h300_000C_0000; 232 | end 233 | else if(NUM_BITS == 43) 234 | begin: b43 235 | assign w__feedback_poly = 43'h630_0000_0000; 236 | end 237 | else if(NUM_BITS == 44) 238 | begin: b44 239 | assign w__feedback_poly = 44'hC00_0003_0000; 240 | end 241 | else if(NUM_BITS == 45) 242 | begin: b45 243 | assign w__feedback_poly = 45'h1B00_0000_0000; 244 | end 245 | else if(NUM_BITS == 46) 246 | begin: b46 247 | assign w__feedback_poly = 46'h3000_0300_0000; 248 | end 249 | else if(NUM_BITS == 47) 250 | begin: b47 251 | assign w__feedback_poly = 47'h4200_0000_0000; 252 | end 253 | else if(NUM_BITS == 48) 254 | begin: b48 255 | assign w__feedback_poly = 48'hC000_0018_0000; 256 | end 257 | else if(NUM_BITS == 49) 258 | begin: b49 259 | assign w__feedback_poly = 49'h1_0080_0000_0000; 260 | end 261 | else if(NUM_BITS == 50) 262 | begin: b50 263 | assign w__feedback_poly = 50'h3_0000_00C0_0000; 264 | end 265 | else if(NUM_BITS == 51) 266 | begin: b51 267 | assign w__feedback_poly = 51'h6_000C_0000_0000; 268 | end 269 | else if(NUM_BITS == 52) 270 | begin: b52 271 | assign w__feedback_poly = 52'h9_0000_0000_0000; 272 | end 273 | else 274 | begin: not_supported 275 | assign w__feedback_poly = 'bx; 276 | end 277 | endgenerate 278 | //------------------------------------------------------------------------------ 279 | 280 | endmodule 281 | 282 | -------------------------------------------------------------------------------- /src/rtl/design/fifo_base.v: -------------------------------------------------------------------------------- 1 | 2 | // First-word fall-through synchronous FIFO with synchronous reset 3 | module fifo_base ( 4 | //-------------------------------------------------------------------------- 5 | // Global signals 6 | //-------------------------------------------------------------------------- 7 | clk, 8 | reset, 9 | 10 | //-------------------------------------------------------------------------- 11 | // Input interface 12 | //-------------------------------------------------------------------------- 13 | i__data_in_valid, 14 | i__data_in, 15 | o__data_in_ready, 16 | o__data_in_ready__next, 17 | 18 | //-------------------------------------------------------------------------- 19 | // Output interface 20 | //-------------------------------------------------------------------------- 21 | o__data_out_valid, 22 | o__data_out, 23 | i__data_out_ready, 24 | i__clear_all, 25 | oa__all_data 26 | ); 27 | 28 | //------------------------------------------------------------------------------ 29 | // Parameters 30 | //------------------------------------------------------------------------------ 31 | parameter MULTI_ISSUE = 1'b0; 32 | parameter DATA_WIDTH = 64; 33 | parameter DEPTH = 3; 34 | //------------------------------------------------------------------------------ 35 | 36 | //------------------------------------------------------------------------------ 37 | // Constants 38 | //------------------------------------------------------------------------------ 39 | localparam ADDR_WIDTH = $clog2(DEPTH); 40 | //------------------------------------------------------------------------------ 41 | 42 | //------------------------------------------------------------------------------ 43 | // Global signals 44 | //------------------------------------------------------------------------------ 45 | input logic clk; 46 | input logic reset; 47 | //------------------------------------------------------------------------------ 48 | 49 | //------------------------------------------------------------------------------ 50 | // Input interface 51 | //------------------------------------------------------------------------------ 52 | input logic i__data_in_valid; 53 | input logic [DATA_WIDTH-1:0] i__data_in; 54 | output logic o__data_in_ready; 55 | output logic o__data_in_ready__next; 56 | //------------------------------------------------------------------------------ 57 | 58 | //------------------------------------------------------------------------------ 59 | // Output interface 60 | //------------------------------------------------------------------------------ 61 | output logic o__data_out_valid; 62 | output logic [DATA_WIDTH-1:0] o__data_out; 63 | input logic i__data_out_ready; 64 | input logic i__clear_all; 65 | output logic [DATA_WIDTH-1:0] oa__all_data [DEPTH-1:0]; 66 | //------------------------------------------------------------------------------ 67 | 68 | //------------------------------------------------------------------------------ 69 | // Signals 70 | //------------------------------------------------------------------------------ 71 | logic w__push; 72 | logic w__pop; 73 | logic w__wr_clk; 74 | //------------------------------------------------------------------------------ 75 | 76 | //------------------------------------------------------------------------------ 77 | // States and next signals 78 | //------------------------------------------------------------------------------ 79 | logic w__empty__next; 80 | logic r__empty__pff; 81 | logic w__full__next; 82 | logic r__full__pff; 83 | 84 | logic [ADDR_WIDTH-1:0] w__wr_addr; 85 | logic [ADDR_WIDTH-1:0] w__wr_addr_next; 86 | logic [ADDR_WIDTH-1:0] w__rd_addr; 87 | logic [ADDR_WIDTH-1:0] w__rd_addr_next; 88 | 89 | logic [DATA_WIDTH-1:0] r__buffer__pff [DEPTH-1:0]; 90 | //------------------------------------------------------------------------------ 91 | 92 | //------------------------------------------------------------------------------ 93 | // Output assignments 94 | //------------------------------------------------------------------------------ 95 | assign o__data_in_ready = ~r__full__pff & (~reset); // When reset, ready should be low 96 | assign o__data_in_ready__next = ~w__full__next; 97 | assign o__data_out_valid = ~r__empty__pff; // When reset, this _will_ be low 98 | assign o__data_out = r__buffer__pff[w__rd_addr]; 99 | 100 | always_comb 101 | begin 102 | integer i; 103 | for(i = 0 ; i < DEPTH ; i = i + 1) 104 | begin 105 | oa__all_data[i] = r__buffer__pff[i]; 106 | end 107 | end 108 | //------------------------------------------------------------------------------ 109 | 110 | //------------------------------------------------------------------------------ 111 | // Submodules 112 | //------------------------------------------------------------------------------ 113 | counter 114 | #( 115 | .NUM_COUNT (DEPTH), 116 | .COUNT_WIDTH (ADDR_WIDTH) 117 | ) 118 | m_write_addr ( 119 | .clk (clk), 120 | .reset (reset | i__clear_all), 121 | .i__inc (w__push), 122 | .o__count (w__wr_addr), 123 | .o__count__next (w__wr_addr_next) 124 | ); 125 | 126 | counter 127 | #( 128 | .NUM_COUNT (DEPTH), 129 | .COUNT_WIDTH (ADDR_WIDTH) 130 | ) 131 | m_read_addr ( 132 | .clk (clk), 133 | .reset (reset | i__clear_all), 134 | .i__inc (w__pop), 135 | .o__count (w__rd_addr), 136 | .o__count__next (w__rd_addr_next) 137 | ); 138 | 139 | clock_gater 140 | gate_update_clk ( 141 | .clk (clk), 142 | .reset (reset), 143 | .i__enable (w__push), 144 | .o__gated_clk (w__wr_clk) 145 | ); 146 | //------------------------------------------------------------------------------ 147 | 148 | //------------------------------------------------------------------------------ 149 | // Internal push and pop signals 150 | //------------------------------------------------------------------------------ 151 | generate 152 | if (MULTI_ISSUE == 1'b0) 153 | begin: single_issue_pp 154 | always_comb 155 | begin 156 | w__push = i__data_in_valid && o__data_in_ready; 157 | w__pop = o__data_out_valid && i__data_out_ready; 158 | end 159 | end 160 | else if (MULTI_ISSUE == 1'b1) 161 | begin: multi_issue_pp 162 | always_comb 163 | begin 164 | if (o__data_in_ready) 165 | w__push = i__data_in_valid; 166 | else if (~o__data_in_ready && i__data_out_ready) 167 | w__push = i__data_in_valid; 168 | else 169 | w__push = 1'b0; 170 | 171 | w__pop = o__data_out_valid && i__data_out_ready; 172 | end 173 | end 174 | endgenerate 175 | //------------------------------------------------------------------------------ 176 | 177 | //------------------------------------------------------------------------------ 178 | // Internal full and empty states 179 | //------------------------------------------------------------------------------ 180 | generate 181 | if (MULTI_ISSUE == 1'b0) 182 | begin: single_issue_fe 183 | always_comb 184 | begin 185 | w__empty__next = r__empty__pff; 186 | if(w__push == 1'b1) 187 | begin 188 | w__empty__next = 1'b0; 189 | end 190 | else if((w__pop == 1'b1) && (w__rd_addr_next == w__wr_addr)) 191 | begin 192 | w__empty__next = 1'b1; 193 | end 194 | 195 | w__full__next = r__full__pff; 196 | if(w__pop == 1'b1) 197 | begin 198 | w__full__next = 1'b0; 199 | end 200 | else if((w__push == 1'b1) && (w__wr_addr_next == w__rd_addr)) 201 | begin 202 | w__full__next = 1'b1; 203 | end 204 | end 205 | end 206 | else if (MULTI_ISSUE == 1'b1) 207 | begin: multi_issue_fe 208 | always_comb 209 | begin 210 | w__empty__next = r__empty__pff; 211 | if ((w__push == 1'b1) && (w__pop == 1'b1)) 212 | begin 213 | if (r__empty__pff) w__empty__next = 1'b1; 214 | else w__empty__next = 1'b0; 215 | end 216 | else if(w__push == 1'b1) 217 | begin 218 | w__empty__next = 1'b0; 219 | end 220 | else if((w__pop == 1'b1) && (w__rd_addr_next == w__wr_addr)) 221 | begin 222 | w__empty__next = 1'b1; 223 | end 224 | 225 | w__full__next = r__full__pff; 226 | if ((w__pop == 1'b1) && (w__push == 1'b1)) 227 | begin 228 | if (r__full__pff) w__full__next = 1'b1; 229 | else w__full__next = 1'b0; 230 | end 231 | else if(w__pop == 1'b1) 232 | begin 233 | w__full__next = 1'b0; 234 | end 235 | else if((w__push == 1'b1) && (w__wr_addr_next == w__rd_addr)) 236 | begin 237 | w__full__next = 1'b1; 238 | end 239 | end 240 | end 241 | endgenerate 242 | 243 | always_ff @ (posedge clk) 244 | begin 245 | if(reset == 1'b1) 246 | begin 247 | r__empty__pff <= 1'b1; 248 | r__full__pff <= 1'b0; 249 | end 250 | else 251 | begin 252 | r__empty__pff <= w__empty__next; 253 | r__full__pff <= w__full__next; 254 | end 255 | end 256 | //------------------------------------------------------------------------------ 257 | 258 | //------------------------------------------------------------------------------ 259 | // Internal full and empty states 260 | //------------------------------------------------------------------------------ 261 | always_ff @ (posedge w__wr_clk) 262 | begin 263 | if(w__push == 1'b1) 264 | begin 265 | r__buffer__pff[w__wr_addr] <= i__data_in; 266 | end 267 | end 268 | //------------------------------------------------------------------------------ 269 | 270 | //------------------------------------------------------------------------------ 271 | // Parameter checks 272 | //------------------------------------------------------------------------------ 273 | // `ifndef SYNTHESIS 274 | // initial 275 | // begin 276 | // if(DATA_WIDTH < 1) 277 | // begin 278 | // $display("[ERROR][fifo] Invalid data width: \"%d\"", DATA_WIDTH); 279 | // $finish; 280 | // end 281 | // if(DEPTH < 2) 282 | // begin 283 | // $display("[ERROR][fifo] Invalid depth: \"%d\"", DEPTH); 284 | // $finish; 285 | // end 286 | // end 287 | // `endif 288 | //------------------------------------------------------------------------------ 289 | 290 | endmodule 291 | 292 | -------------------------------------------------------------------------------- /src/rtl/testbench/pifo_set/pifo_set_tb.v: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // Preamble 3 | //------------------------------------------------------------------------------ 4 | // Simulation precision 5 | `timescale 1ns/1ps 6 | 7 | // Clock period 8 | `define CYCLE (1.0) 9 | `define HALF_CYCLE (`CYCLE / 2.0) 10 | 11 | // Active simulation cycles (started to count after all the initialization) 12 | `define NUM_SIM_CYCLES 100 13 | 14 | // Generic names to be used in the testbench 15 | `define TESTBENCH_NAME pifo_set_tb 16 | `define TEST_MODULE_NAME pifo_set_test 17 | `define TEST_INSTANCE_NAME `TEST_MODULE_NAME 18 | `define TEST_DUMP_NAME `TESTBENCH_NAME 19 | 20 | `include "pifo_set_tb_headers.vh" 21 | 22 | // Testbench 23 | module `TESTBENCH_NAME; 24 | //------------------------------------------------------------------------------ 25 | // Local data structures 26 | //------------------------------------------------------------------------------ 27 | typedef enum logic [1:0] { 28 | GENERATE, 29 | REINSERT, 30 | DRAIN 31 | } Phase; 32 | 33 | //------------------------------------------------------------------------------ 34 | // IO 35 | //------------------------------------------------------------------------------ 36 | logic clk; 37 | logic reset; 38 | integer clk_count; 39 | 40 | //------------------------------------------------------------------------------ 41 | // Simulation required signals 42 | //------------------------------------------------------------------------------ 43 | integer num_sim_cycles; 44 | 45 | //------------------------------------------------------------------------------ 46 | // Testbench signals 47 | //------------------------------------------------------------------------------ 48 | TGConfig w__traffic_generator_config; 49 | TGConfig w__reinsert_generator_config; 50 | TRConfig w__traffic_receiver_config; 51 | 52 | 53 | FlowId w__enqueue_flow_id; 54 | Priority w__enqueue_packet_priority; 55 | logic w__enqueue; 56 | 57 | FlowId w__dequeue_flow_id; 58 | Priority w__dequeue_packet_priority; 59 | logic w__dequeue; 60 | 61 | logic w__reinsert; 62 | Priority w__reinsert_packet_priority; 63 | 64 | logic w__pifo_empty; 65 | logic w__pifo_full; 66 | logic w__pifo_push_ready; 67 | logic w__pifo_pop_valid; 68 | 69 | Phase r__phase__pff; 70 | Phase w__phase__next; 71 | logic w__generate_phase; 72 | logic w__receive_phase; 73 | logic w__reinsert_phase; 74 | CounterSignal r__phase_count__pff; 75 | CounterSignal w__phase_count__next; 76 | 77 | CounterSignal w__reinserted_packet_count; 78 | CounterSignal w__last_reinsert_packet_count__next; 79 | CounterSignal r__last_reinsert_packet_count__pff; 80 | 81 | //------------------------------------------------------------------------------ 82 | // Test module instantiation 83 | //------------------------------------------------------------------------------ 84 | pifo_set #( 85 | .NUM_ELEMENTS (NUM_ELEMENTS), 86 | .MAX_PRIORITY (MAX_PACKET_PRIORITY), 87 | .DATA_WIDTH ($bits(FlowId)) 88 | ) pf ( 89 | .clk (clk), 90 | .reset (reset), 91 | 92 | .i__push_valid (w__enqueue), 93 | .i__push_priority (w__enqueue_packet_priority), 94 | .i__push_flow_id (w__enqueue_flow_id), 95 | .o__push_flow_empty (), // Unused: OK 96 | 97 | .o__pifo_set_ready (w__pifo_push_ready), 98 | .o__pifo_set_ready__next (), 99 | .i__reinsert_valid (w__reinsert), 100 | .i__reinsert_priority (w__reinsert_packet_priority), 101 | 102 | .o__pop_valid (w__pifo_pop_valid), 103 | .o__pop_priority (w__dequeue_packet_priority), 104 | .o__pop_flow_id (w__dequeue_flow_id), 105 | .i__pop (w__dequeue), 106 | .i__clear_all () 107 | ); 108 | 109 | //------------------------------------------------------------------------------ 110 | // Support modules instantiation 111 | //------------------------------------------------------------------------------ 112 | traffic_generator tg ( 113 | .clk (clk), 114 | .reset (reset), 115 | 116 | .i__config (w__traffic_generator_config), 117 | .i__generate_phase (w__generate_phase), 118 | .i__phase_count (r__phase_count__pff), 119 | .i__pifo_ready (~w__pifo_full), 120 | 121 | .o__packet_flow_id (w__enqueue_flow_id), 122 | .o__packet_priority (w__enqueue_packet_priority), 123 | .o__valid_packet_generated (w__enqueue), 124 | .o__num_pkts_sent () 125 | ); 126 | 127 | traffic_generator rig ( 128 | .clk (clk), 129 | .reset (reset), 130 | 131 | .i__config (w__reinsert_generator_config), 132 | .i__generate_phase (w__reinsert_phase), 133 | .i__phase_count (r__phase_count__pff), 134 | .i__pifo_ready (w__dequeue), 135 | 136 | .o__packet_flow_id (), // don't require this for this test 137 | .o__packet_priority (w__reinsert_packet_priority), 138 | .o__valid_packet_generated (w__reinsert), 139 | .o__num_pkts_sent (w__reinserted_packet_count) 140 | ); 141 | 142 | 143 | traffic_receiver tr ( 144 | .clk (clk), 145 | .reset (reset), 146 | 147 | .i__config (w__traffic_receiver_config), 148 | .i__receive_phase (w__receive_phase), 149 | .i__phase_count (r__phase_count__pff), 150 | 151 | .i__pifo_ready (~w__pifo_empty), 152 | .i__packet_priority (w__dequeue_packet_priority), 153 | .i__packet_flow_id (w__dequeue_flow_id), 154 | 155 | .o__dequeue (w__dequeue) 156 | ); 157 | 158 | clock_generator 159 | #( 160 | .HALF_CYCLE (`HALF_CYCLE) 161 | ) 162 | clock_generator( 163 | .clk (clk), 164 | .clk_delay (), 165 | .clk_count (clk_count) 166 | ); 167 | 168 | //------------------------------------------------------------------------------ 169 | // Auxiliary logic 170 | //------------------------------------------------------------------------------ 171 | always_comb 172 | begin 173 | w__pifo_full = ~w__pifo_push_ready; 174 | w__pifo_empty = ~w__pifo_pop_valid; 175 | end 176 | 177 | always_comb 178 | begin 179 | w__phase__next = r__phase__pff; 180 | w__last_reinsert_packet_count__next 181 | = r__last_reinsert_packet_count__pff; 182 | 183 | if (w__pifo_empty) 184 | w__phase__next = GENERATE; 185 | else if (w__pifo_full) 186 | w__phase__next = REINSERT; 187 | else if ((r__phase__pff == REINSERT) && (w__reinserted_packet_count != r__last_reinsert_packet_count__pff) 188 | && (w__reinserted_packet_count % NUM_ELEMENTS == 0)) // NOTE: Not synthesizable (or atleast not easily) 189 | begin 190 | w__phase__next = DRAIN; 191 | w__last_reinsert_packet_count__next = r__last_reinsert_packet_count__pff; 192 | end 193 | 194 | if ((r__phase__pff==DRAIN) && (w__phase__next == GENERATE)) 195 | w__phase_count__next = r__phase_count__pff + 1'b1; 196 | else w__phase_count__next = r__phase_count__pff; 197 | 198 | w__generate_phase = (r__phase__pff == GENERATE); 199 | w__receive_phase = ((r__phase__pff == DRAIN) || (r__phase__pff == REINSERT)); 200 | w__reinsert_phase = (r__phase__pff == REINSERT); 201 | end 202 | 203 | always_ff @(posedge clk) 204 | begin 205 | if (reset) 206 | begin 207 | r__phase__pff <= GENERATE; 208 | r__phase_count__pff <= '0; 209 | r__last_reinsert_packet_count__pff 210 | <= '0; 211 | end 212 | else 213 | begin 214 | r__phase__pff <= w__phase__next; 215 | r__phase_count__pff <= w__phase_count__next; 216 | r__last_reinsert_packet_count__pff 217 | <= w__last_reinsert_packet_count__next; 218 | end 219 | end 220 | 221 | always_comb 222 | begin 223 | w__traffic_generator_config.flow_id_seed = PKT_FLOWID_SEED; 224 | w__traffic_generator_config.priority_seed = PRIORITY_SEED; 225 | w__traffic_generator_config.injrate_seed = PKT_INJRATE_SEED; 226 | w__traffic_generator_config.injrate = PKT_INJRATE; 227 | w__traffic_generator_config.total_packets = MAX_PACKETS; 228 | 229 | w__reinsert_generator_config.flow_id_seed = PKT_FLOWID_SEED; 230 | w__reinsert_generator_config.priority_seed = PRIORITY_SEED2; 231 | w__reinsert_generator_config.injrate_seed = PKT_RIRATE_SEED; 232 | w__reinsert_generator_config.injrate = PKT_RIRATE; 233 | w__reinsert_generator_config.total_packets = MAX_PACKETS; 234 | 235 | 236 | w__traffic_receiver_config.ejrate_seed = PKT_EJRATE_SEED; 237 | w__traffic_receiver_config.ejrate = PKT_EJRATE; 238 | end 239 | 240 | //------------------------------------------------------------------------------ 241 | // Simulation control flow 242 | //------------------------------------------------------------------------------ 243 | initial 244 | begin: simulation_control_flow 245 | reset = 1'b0; 246 | 247 | // Free run the clock 248 | #(`CYCLE*3) 249 | reset = 1'b1; 250 | 251 | #(`CYCLE*3) 252 | reset = 1'b0; 253 | 254 | #(`CYCLE) 255 | 256 | // Determine the specified simulation cycle 257 | if(!$value$plusargs("NUM_SIM_CYCLES=%d", num_sim_cycles)) 258 | begin 259 | num_sim_cycles = `NUM_SIM_CYCLES; 260 | end 261 | 262 | // Wait until the specified simulation time and call $finish 263 | #(`CYCLE*num_sim_cycles) 264 | 265 | // Monitor any signals you want 266 | $monitor("\n\n======= STATS =======\nTotal packets generated: %d\nTotal packets reinserted: %d\nTotal packets received: %d\n\n", tg.r__num_pkts_sent__pff, rig.r__num_pkts_sent__pff, tr.r__num_pkts_recvd__pff); 267 | 268 | #(`CYCLE) 269 | $finish(); 270 | end 271 | 272 | //------------------------------------------------------------------------------ 273 | // Dump wave 274 | //------------------------------------------------------------------------------ 275 | initial 276 | begin: dump_wave 277 | `ifdef VPD 278 | string test_dump_name = $psprintf("dumps/%s.vpd", `STRINGIFY(`TEST_DUMP_NAME)); 279 | // Dump VCD+ (VPD) 280 | $vcdplusfile(test_dump_name); 281 | $vcdpluson; 282 | $vcdplusmemon; 283 | `endif 284 | 285 | `ifdef VCD 286 | // Dump VCD 287 | string test_dump_name = $psprintf("dumps/%s.vcd", `STRINGIFY(`TEST_DUMP_NAME)); 288 | $dumpfile(test_dump_name); 289 | $dumpvars(0, `TESTBENCH_NAME); 290 | `endif 291 | end 292 | 293 | endmodule 294 | -------------------------------------------------------------------------------- /src/rtl/testbench/flow_pifo/flow_pifo_tb.v: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // Preamble 3 | //------------------------------------------------------------------------------ 4 | // Simulation precision 5 | `timescale 1ns/1ps 6 | 7 | // Clock period 8 | `define CYCLE (1.0) 9 | `define HALF_CYCLE (`CYCLE / 2.0) 10 | 11 | // Active simulation cycles (started to count after all the initialization) 12 | `define NUM_SIM_CYCLES 100 13 | 14 | // Generic names to be used in the testbench 15 | `define TESTBENCH_NAME flow_pifo_tb 16 | `define TEST_MODULE_NAME flow_pifo_test 17 | `define TEST_INSTANCE_NAME `TEST_MODULE_NAME 18 | `define TEST_DUMP_NAME `TESTBENCH_NAME 19 | 20 | `include "flow_pifo_tb_headers.vh" 21 | 22 | // Testbench 23 | module `TESTBENCH_NAME; 24 | //------------------------------------------------------------------------------ 25 | // Local data structures 26 | //------------------------------------------------------------------------------ 27 | typedef enum logic [1:0] { 28 | DRAIN, 29 | GENERATE, 30 | REINSERT 31 | } Phase; 32 | 33 | //------------------------------------------------------------------------------ 34 | // IO 35 | //------------------------------------------------------------------------------ 36 | logic clk; 37 | logic reset; 38 | integer clk_count; 39 | 40 | //------------------------------------------------------------------------------ 41 | // Simulation required signals 42 | //------------------------------------------------------------------------------ 43 | integer num_sim_cycles; 44 | 45 | //------------------------------------------------------------------------------ 46 | // Testbench signals 47 | //------------------------------------------------------------------------------ 48 | TGConfig w__traffic_generator_config; 49 | TGConfig w__reinsert_generator_config; 50 | TRConfig w__traffic_receiver_config; 51 | 52 | 53 | FlowId w__enqueue_flow_id; 54 | Priority w__enqueue_packet_priority; 55 | logic w__enqueue; 56 | 57 | FlowId w__dequeue_flow_id; 58 | Priority w__dequeue_packet_priority; 59 | logic w__dequeue; 60 | 61 | logic w__generate; 62 | Priority w__generate_packet_priority; 63 | FlowId w__generate_packet_flow_id; 64 | logic w__reinsert; 65 | Priority w__reinsert_packet_priority; 66 | FlowId w__reinsert_packet_flow_id; 67 | 68 | logic w__pifo_empty; 69 | logic w__pifo_full; 70 | logic w__pifo_push_ready; 71 | logic w__pifo_pop_valid; 72 | 73 | Phase r__phase__pff; 74 | Phase w__phase__next; 75 | logic w__generate_phase; 76 | logic w__receive_phase; 77 | logic w__reinsert_phase; 78 | CounterSignal r__phase_count__pff; 79 | CounterSignal w__phase_count__next; 80 | 81 | CounterSignal w__total_packets__next; 82 | CounterSignal r__total_packets__pff; 83 | 84 | //------------------------------------------------------------------------------ 85 | // Test module instantiation 86 | //------------------------------------------------------------------------------ 87 | flow_pifo fp ( 88 | .clk (clk), 89 | .reset (reset), 90 | .i__enqueue (w__enqueue), 91 | .i__enqueue_priority (w__enqueue_packet_priority), 92 | .i__enqueue_flow_id (w__enqueue_flow_id), 93 | .i__dequeue (w__dequeue), 94 | .o__dequeue_priority (w__dequeue_packet_priority), 95 | .o__dequeue_flow_id (w__dequeue_flow_id) 96 | ); 97 | 98 | //------------------------------------------------------------------------------ 99 | // Support modules instantiation 100 | //------------------------------------------------------------------------------ 101 | traffic_generator tg ( 102 | .clk (clk), 103 | .reset (reset), 104 | 105 | .i__config (w__traffic_generator_config), 106 | .i__generate_phase (w__generate_phase), 107 | .i__phase_count (r__phase_count__pff), 108 | .i__pifo_ready (1'b1), // TODO Verify this is OK 109 | 110 | .o__packet_flow_id (w__generate_packet_flow_id), 111 | .o__packet_priority (w__generate_packet_priority), 112 | .o__valid_packet_generated (w__generate), 113 | .o__num_pkts_sent () // unused: OK 114 | ); 115 | 116 | traffic_generator rig ( 117 | .clk (clk), 118 | .reset (reset), 119 | 120 | .i__config (w__reinsert_generator_config), 121 | .i__generate_phase (w__reinsert_phase), 122 | .i__phase_count (r__phase_count__pff), 123 | .i__pifo_ready (w__dequeue), 124 | 125 | .o__packet_flow_id (), // don't require this for this test 126 | .o__packet_priority (w__reinsert_packet_priority), 127 | .o__valid_packet_generated (w__reinsert), 128 | .o__num_pkts_sent () // unused: OK 129 | ); 130 | 131 | 132 | traffic_receiver tr ( 133 | .clk (clk), 134 | .reset (reset), 135 | 136 | .i__config (w__traffic_receiver_config), 137 | .i__receive_phase (w__receive_phase), 138 | .i__phase_count (r__phase_count__pff), 139 | 140 | .i__pifo_ready (1'b1), // TODO Verify this is okay 141 | .i__packet_priority (w__dequeue_packet_priority), 142 | .i__packet_flow_id (w__dequeue_flow_id), 143 | 144 | .o__dequeue (w__dequeue) 145 | ); 146 | 147 | clock_generator 148 | #( 149 | .HALF_CYCLE (`HALF_CYCLE) 150 | ) 151 | clock_generator( 152 | .clk (clk), 153 | .clk_delay (), 154 | .clk_count (clk_count) 155 | ); 156 | 157 | //------------------------------------------------------------------------------ 158 | // Auxiliary logic 159 | //------------------------------------------------------------------------------ 160 | always_comb 161 | begin 162 | w__enqueue = (r__phase__pff == GENERATE) ? w__generate : (r__phase__pff == REINSERT) ? w__reinsert : 1'b0; 163 | w__enqueue_flow_id = w__generate ? w__generate_packet_flow_id : w__dequeue_flow_id; 164 | w__enqueue_packet_priority 165 | = w__generate ? w__generate_packet_priority : w__reinsert_packet_priority; 166 | end 167 | 168 | //------------------------------------------------------------------------------ 169 | // Traffic phase 170 | //------------------------------------------------------------------------------ 171 | logic w__switch_phase; 172 | always_comb 173 | begin 174 | w__phase__next = r__phase__pff; 175 | 176 | // Decide whether to switch phase 177 | if ((r__total_packets__pff % MAX_PKTS_PER_PHASE == 0) && 178 | r__total_packets__pff != '0) 179 | w__switch_phase = 1'b1; 180 | else w__switch_phase = 1'b0; 181 | 182 | // Switch phase if required 183 | if ((w__switch_phase) && (r__phase__pff == GENERATE)) 184 | w__phase__next = REINSERT; 185 | else if ((w__switch_phase) && (r__phase__pff == REINSERT)) 186 | w__phase__next = DRAIN; 187 | else if ((w__switch_phase) && (r__phase__pff == DRAIN)) 188 | w__phase__next = GENERATE; 189 | 190 | // Update phase count 191 | if ((r__phase__pff==DRAIN) && (w__phase__next == GENERATE)) 192 | w__phase_count__next = r__phase_count__pff + 1'b1; 193 | else w__phase_count__next = r__phase_count__pff; 194 | end 195 | 196 | always_comb 197 | begin 198 | w__total_packets__next = r__total_packets__pff; 199 | 200 | // Update packet count 201 | if (w__generate_phase && w__generate) 202 | w__total_packets__next = r__total_packets__pff + 1'b1; 203 | else if (w__receive_phase && w__dequeue) 204 | w__total_packets__next = r__total_packets__pff + 1'b1; 205 | end 206 | 207 | always_comb 208 | begin 209 | // Phase signals 210 | w__generate_phase = (r__phase__pff == GENERATE); 211 | w__receive_phase = ((r__phase__pff == DRAIN) || (r__phase__pff == REINSERT)); 212 | w__reinsert_phase = (r__phase__pff == REINSERT); 213 | end 214 | 215 | always_ff @(posedge clk) 216 | begin 217 | if (reset) 218 | begin 219 | r__phase__pff <= GENERATE; 220 | r__phase_count__pff <= '0; 221 | r__total_packets__pff 222 | <= '0; 223 | end 224 | else 225 | begin 226 | r__phase__pff <= w__phase__next; 227 | r__phase_count__pff <= w__phase_count__next; 228 | r__total_packets__pff 229 | <= w__total_packets__next; 230 | end 231 | end 232 | 233 | //------------------------------------------------------------------------------ 234 | // Traffic generator/receiver configuration 235 | //------------------------------------------------------------------------------ 236 | always_comb 237 | begin 238 | w__traffic_generator_config.flow_id_seed = PKT_FLOWID_SEED; 239 | w__traffic_generator_config.priority_seed = PRIORITY_SEED; 240 | w__traffic_generator_config.injrate_seed = PKT_INJRATE_SEED; 241 | w__traffic_generator_config.injrate = PKT_INJRATE; 242 | w__traffic_generator_config.total_packets = MAX_PACKETS; 243 | 244 | w__reinsert_generator_config.flow_id_seed = PKT_FLOWID_SEED; 245 | w__reinsert_generator_config.priority_seed = PRIORITY_SEED2; 246 | w__reinsert_generator_config.injrate_seed = PKT_RIRATE_SEED; 247 | w__reinsert_generator_config.injrate = PKT_RIRATE; 248 | w__reinsert_generator_config.total_packets = MAX_PACKETS; 249 | 250 | 251 | w__traffic_receiver_config.ejrate_seed = PKT_EJRATE_SEED; 252 | w__traffic_receiver_config.ejrate = PKT_EJRATE; 253 | end 254 | 255 | //------------------------------------------------------------------------------ 256 | // Simulation control flow 257 | //------------------------------------------------------------------------------ 258 | initial 259 | begin: simulation_control_flow 260 | reset = 1'b0; 261 | 262 | // Free run the clock 263 | #(`CYCLE*3.5) 264 | reset = 1'b1; 265 | 266 | #(`CYCLE*3) 267 | reset = 1'b0; 268 | 269 | #(`CYCLE*1.5) 270 | 271 | // Determine the specified simulation cycle 272 | if(!$value$plusargs("NUM_SIM_CYCLES=%d", num_sim_cycles)) 273 | begin 274 | num_sim_cycles = `NUM_SIM_CYCLES; 275 | end 276 | 277 | // Wait until the specified simulation time and call $finish 278 | #(`CYCLE*num_sim_cycles) 279 | 280 | // Monitor any signals you want 281 | $monitor("\n\n======= STATS =======\nTotal packets generated: %d\nTotal packets reinserted: %d\nTotal packets received: %d\n\n", tg.r__num_pkts_sent__pff, rig.r__num_pkts_sent__pff, tr.r__num_pkts_recvd__pff); 282 | 283 | #(`CYCLE) 284 | $finish(); 285 | end 286 | 287 | //------------------------------------------------------------------------------ 288 | // Dump wave 289 | //------------------------------------------------------------------------------ 290 | initial 291 | begin: dump_wave 292 | `ifdef VPD 293 | string test_dump_name = $psprintf("dumps/%s.vpd", `STRINGIFY(`TEST_DUMP_NAME)); 294 | // Dump VCD+ (VPD) 295 | $vcdplusfile(test_dump_name); 296 | $vcdpluson; 297 | $vcdplusmemon; 298 | `endif 299 | 300 | `ifdef VCD 301 | // Dump VCD 302 | string test_dump_name = $psprintf("dumps/%s.vcd", `STRINGIFY(`TEST_DUMP_NAME)); 303 | $dumpfile(test_dump_name); 304 | $dumpvars(0, `TESTBENCH_NAME); 305 | `endif 306 | end 307 | 308 | endmodule 309 | -------------------------------------------------------------------------------- /src/rtl/design/flow_pifo.v: -------------------------------------------------------------------------------- 1 | module flow_pifo ( 2 | clk, 3 | reset, 4 | 5 | i__enqueue, 6 | i__enqueue_priority, 7 | i__enqueue_flow_id, 8 | 9 | i__dequeue, 10 | o__dequeue_priority, 11 | o__dequeue_flow_id 12 | ); 13 | 14 | `include "flow_pifo_headers.vh" 15 | 16 | //------------------------------------------------------------------------------ 17 | // Global signals 18 | //------------------------------------------------------------------------------ 19 | input logic clk; 20 | input logic reset; 21 | 22 | //------------------------------------------------------------------------------ 23 | // Interface 24 | //------------------------------------------------------------------------------ 25 | input logic i__enqueue; 26 | input Priority i__enqueue_priority; 27 | input FlowId i__enqueue_flow_id; 28 | 29 | input logic i__dequeue; 30 | output Priority o__dequeue_priority; 31 | output FlowId o__dequeue_flow_id; 32 | 33 | 34 | //------------------------------------------------------------------------------ 35 | // Signals 36 | //------------------------------------------------------------------------------ 37 | logic w__pifo_set_push_valid; 38 | Priority w__pifo_set_push_priority; 39 | FlowId w__pifo_set_push_flow_id; 40 | logic w__pifo_set_push_flow_empty; 41 | logic w__pifo_set_ready; 42 | logic w__pifo_set_reinsert_valid; 43 | Priority w__pifo_set_reinsert_priority; 44 | logic w__pifo_set_pop_valid; 45 | FlowId w__pifo_set_pop_flow_id; 46 | Priority w__pifo_set_pop_priority; 47 | logic w__pifo_set_pop; 48 | 49 | logic w__prefetch_push_valid; 50 | logic w__prefetch_push_flow_not_full; 51 | logic w__prefetch_reinsert_valid; 52 | Priority w__prefetch_reinsert_priority; 53 | Priority w__prefetch_pop_priority; 54 | logic w__prefetch_pop_priority_valid; 55 | logic w__prefetch_pop; 56 | 57 | logic w__fifobank_push_valid; 58 | logic w__fifobank_reinsert_valid; 59 | Priority w__fifobank_reinsert_priority; 60 | Priority w__fifobank_pop_priority; 61 | logic w__fifobank_pop_priority_valid; 62 | logic w__fifobank_pop; 63 | 64 | logic w__bypass_prefetch; 65 | logic w__bypass_fifo; 66 | 67 | //------------------------------------------------------------------------------ 68 | // Sub-modules 69 | //------------------------------------------------------------------------------ 70 | pifo_set #( 71 | .NUM_ELEMENTS (NUM_FLOWS), 72 | .MAX_PRIORITY (MAX_PACKET_PRIORITY), 73 | .DATA_WIDTH ($bits(FlowId)) 74 | ) pifo ( 75 | .clk (clk), 76 | .reset (reset), 77 | 78 | // Input interface 79 | .i__push_valid (w__pifo_set_push_valid), 80 | .i__push_priority (i__enqueue_priority), 81 | .i__push_flow_id (w__pifo_set_push_flow_id), 82 | .o__push_flow_empty (w__pifo_set_push_flow_empty), 83 | 84 | .o__pifo_set_ready (w__pifo_set_ready), 85 | .o__pifo_set_ready__next(), 86 | 87 | .i__reinsert_priority (w__pifo_set_reinsert_priority), 88 | .i__reinsert_valid (w__pifo_set_reinsert_valid), 89 | 90 | // Output interface 91 | .o__pop_valid (w__pifo_set_pop_valid), 92 | .o__pop_priority (w__pifo_set_pop_priority), 93 | .o__pop_flow_id (w__pifo_set_pop_flow_id), 94 | .i__pop (w__pifo_set_pop), 95 | .i__clear_all ('0) // pulled to '0: OK 96 | ); 97 | 98 | prefetch_buffer #( 99 | .NUM_FLOWS (NUM_FLOWS), 100 | .DEPTH (PREFETCH_BUFFER_DEPTH), 101 | .DATA_WIDTH ($bits(Priority)) 102 | ) pre_buf ( 103 | .clk (clk), 104 | .reset (reset), 105 | 106 | // Input interface 107 | .i__push_valid (w__prefetch_push_valid), 108 | .i__push_flow_id (i__enqueue_flow_id), 109 | .i__push_data (i__enqueue_priority), 110 | .o__push_flow_not_full (w__prefetch_push_flow_not_full), 111 | 112 | .i__reinsert_valid (w__prefetch_reinsert_valid), 113 | .i__reinsert_data (w__prefetch_reinsert_priority), 114 | 115 | // Output interface 116 | .o__pop_data (w__prefetch_pop_priority), 117 | .o__pop_valid (w__prefetch_pop_priority_valid), 118 | .i__pop (w__prefetch_pop), 119 | .i__pop_flow_id (w__pifo_set_pop_flow_id) // OK 120 | ); 121 | 122 | fifo_bank #( 123 | .NUM_FLOWS (NUM_FLOWS), 124 | .DEPTH (FIFO_DEPTH), 125 | .DATA_WIDTH ($bits(Priority)) 126 | ) fifobank ( 127 | .clk (clk), 128 | .reset (reset), 129 | 130 | // Input interface 131 | .i__push_valid (w__fifobank_push_valid), 132 | .i__push_flow_id (i__enqueue_flow_id), 133 | .i__push_data (i__enqueue_priority), 134 | .o__push_flow_not_full (), // unused: OK 135 | 136 | .i__reinsert_valid (w__fifobank_reinsert_valid), // pulled to '0: OK 137 | .i__reinsert_data (w__fifobank_reinsert_priority), // pulled to '0: OK 138 | 139 | // Output interface 140 | .o__pop_data (w__fifobank_pop_priority), 141 | .o__pop_valid (w__fifobank_pop_priority_valid), 142 | .i__pop (w__fifobank_pop), 143 | .i__pop_flow_id (w__pifo_set_pop_flow_id) // OK 144 | ); 145 | 146 | 147 | //------------------------------------------------------------------------------ 148 | // Output assignments 149 | //------------------------------------------------------------------------------ 150 | assign o__dequeue_priority = w__pifo_set_pop_priority; 151 | assign o__dequeue_flow_id = w__pifo_set_pop_flow_id; 152 | 153 | //------------------------------------------------------------------------------ 154 | // Bypass signals 155 | //------------------------------------------------------------------------------ 156 | always_comb 157 | begin 158 | if (w__pifo_set_push_flow_empty) // 1. PIFO set entry for the flow being 159 | begin // enqueued is invalid 160 | w__bypass_prefetch = 1'b1; 161 | w__bypass_fifo = 1'b1; 162 | end 163 | else if (w__prefetch_push_flow_not_full) // 2. PIFO set entry exists for enqueue flow 164 | begin // But it's prefetch buffer is not full 165 | w__bypass_prefetch = 1'b0; 166 | w__bypass_fifo = 1'b1; 167 | end 168 | else // 3. PIFO set entry exists for enqueue flow 169 | begin // And it's prefetch buffer is also full 170 | w__bypass_prefetch = 1'b0; 171 | w__bypass_fifo = 1'b0; 172 | end 173 | end 174 | 175 | 176 | //------------------------------------------------------------------------------ 177 | // Pifo-set signals 178 | //------------------------------------------------------------------------------ 179 | // Reinsert logic 180 | always_comb 181 | begin 182 | if (w__prefetch_pop_priority_valid || // 1. Have a valid prefetch entry OR 183 | (~w__prefetch_pop_priority_valid && i__enqueue && // 2. Don't have a valid prefetch entry, AND 184 | (i__enqueue_flow_id == w__pifo_set_pop_flow_id)) // new enqueue flow is the same as popped 185 | ) // flow. 186 | w__pifo_set_reinsert_valid = i__dequeue; 187 | else 188 | w__pifo_set_reinsert_valid = 1'b0; 189 | 190 | // TODO Assert that if prefetch is empty, then so is the 191 | // corresponding fifo bank. 192 | end 193 | 194 | always_comb 195 | begin 196 | if (w__prefetch_pop_priority_valid) // 1. Prefetch entry is valid, get prio from there 197 | w__pifo_set_reinsert_priority = w__prefetch_pop_priority; 198 | else if (~w__prefetch_pop_priority_valid && (i__enqueue_flow_id == w__pifo_set_pop_flow_id)) 199 | w__pifo_set_reinsert_priority = i__enqueue_priority; // 2. Same as 2, above. Get the enqueue priority 200 | else 201 | w__pifo_set_reinsert_priority = '0; // 3. Neither, ignore reinsert priority 202 | // TODO Assert that w__pifo_set_reinsert_valid = false 203 | end 204 | 205 | // Push logic 206 | always_comb 207 | begin 208 | // TODO Asserts 209 | w__pifo_set_push_flow_id = i__enqueue_flow_id; 210 | if ((w__pifo_set_push_flow_empty) && i__enqueue) // 1. If no valid entry for enqueue flow, push 211 | w__pifo_set_push_valid = 1'b1; // Note that if enqueue flow == popped flow 212 | else // by defn w__pifo_set_push_flow_empty = 0 213 | w__pifo_set_push_valid = 1'b0; // and we will fall back to the reinsert mechn. 214 | end 215 | 216 | // Pop logic 217 | always_comb 218 | begin 219 | w__pifo_set_pop = i__dequeue; // Obvious 220 | end 221 | 222 | //------------------------------------------------------------------------------ 223 | // Prefetch buffer signals 224 | //------------------------------------------------------------------------------ 225 | // FIXME Documenting this concern here so it can be fixed. 226 | // Prefetch buffer might be full in this cycle, and a pop occurs. 227 | // In this case an incoming packet has to bypass fifo (if fifo is also empty). 228 | // Currently, that will not happen. 229 | // Reinsert logic 230 | always_comb 231 | begin 232 | if ( ( w__fifobank_pop_priority_valid || // 1. Fifobank has a valid entry OR 233 | (~w__fifobank_pop_priority_valid && i__enqueue && // 2. Fifobank does not have a valid entry AND 234 | (i__enqueue_flow_id == w__pifo_set_pop_flow_id)) // enqueued flow is same as popped flow. 235 | ) && 236 | ~w__bypass_prefetch // Gate the entire thing by bypass prefetch 237 | ) 238 | w__prefetch_reinsert_valid = i__dequeue; 239 | else 240 | w__prefetch_reinsert_valid = 1'b0; 241 | end 242 | 243 | always_comb 244 | begin 245 | if (w__fifobank_pop_priority_valid) // Similar reasoning to pifo-set reinsert 246 | w__prefetch_reinsert_priority = w__fifobank_pop_priority; 247 | else if ( (~w__fifobank_pop_priority_valid && (i__enqueue_flow_id == w__pifo_set_pop_flow_id)) && 248 | ~w__bypass_prefetch) 249 | w__prefetch_reinsert_priority = i__enqueue_priority; 250 | else 251 | w__prefetch_reinsert_priority = '0; 252 | end 253 | 254 | // Push logic 255 | always_comb 256 | begin 257 | // TODO Assert that corresponding fifo is empty 258 | if ((w__prefetch_push_flow_not_full) && ~w__bypass_prefetch && i__enqueue) // Similar reasoning to pifo-set 259 | w__prefetch_push_valid = 1'b1; 260 | else 261 | w__prefetch_push_valid = 1'b0; 262 | end 263 | 264 | // Pop logic 265 | always_comb 266 | begin 267 | w__prefetch_pop = i__dequeue; // Obvious 268 | end 269 | 270 | 271 | //------------------------------------------------------------------------------ 272 | // Fifobank signals 273 | //------------------------------------------------------------------------------ 274 | // [ssub] I am re-using the logic of the pre-fetch buffer for the fifo bank 275 | // The fifo bank will have atmost 1 push and 1 pop in any cycle. There is no 276 | // notion of "re-inserting". We just set reinsert signals to '0 and they should 277 | // get synthesized away. We can explicitly re-write the fifo bank module if 278 | // this does not happen, or if this organization is confusing. 279 | // Reinsert logic 280 | always_comb 281 | begin 282 | w__fifobank_reinsert_valid = 1'b0; 283 | w__fifobank_reinsert_priority = 1'b0; 284 | end 285 | 286 | // Push logic 287 | always_comb 288 | begin 289 | if (i__enqueue && ~w__bypass_fifo) w__fifobank_push_valid = 1'b1; // 1. Push to fifobank if there's valid enqueue 290 | else w__fifobank_push_valid = 1'b0; // and bypass is false. 291 | end 292 | 293 | // Pop logic 294 | always_comb 295 | begin 296 | w__fifobank_pop = i__dequeue; // Obvious 297 | end 298 | 299 | endmodule 300 | -------------------------------------------------------------------------------- /src/rtl/design/pifo.v: -------------------------------------------------------------------------------- 1 | module pifo ( 2 | clk, rst, 3 | pop_0, oprt_0, ovld_0, opri_0, odout_0, 4 | push_1, uprt_1, upri_1, udin_1, 5 | push_2, uprt_2, upri_2, udin_2 6 | ); 7 | 8 | parameter NUMPIFO = 1024; 9 | parameter BITPORT = 8; 10 | parameter BITPRIO = 16; 11 | parameter BITDATA = 32; 12 | 13 | localparam BITPIFO = $clog2(NUMPIFO); 14 | 15 | localparam FLOP_IDX = 1; 16 | 17 | input clk, rst; 18 | 19 | input pop_0; 20 | input [BITPORT-1:0] oprt_0; 21 | output ovld_0; 22 | output [BITPRIO-1:0] opri_0; 23 | output [BITDATA-1:0] odout_0; 24 | 25 | input push_1; 26 | input [BITPORT-1:0] uprt_1; 27 | input [BITPRIO-1:0] upri_1; 28 | input [BITDATA-1:0] udin_1; 29 | 30 | input push_2; 31 | input [BITPORT-1:0] uprt_2; 32 | input [BITPRIO-1:0] upri_2; 33 | input [BITDATA-1:0] udin_2; 34 | 35 | wire pop_0_del; 36 | wire [BITPORT-1:0] oprt_0_del; 37 | wire push_1_del; 38 | wire [BITPORT-1:0] uprt_1_del; 39 | wire [BITPRIO-1:0] upri_1_del; 40 | wire [BITDATA-1:0] udin_1_del; 41 | wire push_2_del; 42 | wire [BITPORT-1:0] uprt_2_del; 43 | wire [BITPRIO-1:0] upri_2_del; 44 | wire [BITDATA-1:0] udin_2_del; 45 | shift #(.BITDATA(1+BITPORT), .DELAY(FLOP_IDX)) pop_fidx_inst (.clk(clk), .din({pop_0,oprt_0}), .dout({pop_0_del,oprt_0_del})); 46 | shift #(.BITDATA(1+BITPORT+BITPRIO+BITDATA), .DELAY(FLOP_IDX)) push_1_fidx_inst (.clk(clk), .din({push_1,uprt_1,upri_1,udin_1}), .dout({push_1_del,uprt_1_del,upri_1_del,udin_1_del})); 47 | shift #(.BITDATA(1+BITPORT+BITPRIO+BITDATA), .DELAY(FLOP_IDX)) push_2_fidx_inst (.clk(clk), .din({push_2,uprt_2,upri_2,udin_2}), .dout({push_2_del,uprt_2_del,upri_2_del,udin_2_del})); 48 | 49 | reg [BITDATA-1:0] pf_data [0:NUMPIFO-1]; 50 | reg [BITPRIO-1:0] pf_prio [0:NUMPIFO-1]; 51 | reg [BITPORT-1:0] pf_port [0:NUMPIFO-1]; 52 | reg [BITPIFO :0] pf_cnt; 53 | 54 | reg pop_0_hit; 55 | reg [BITPIFO-1:0] pop_0_idx; 56 | reg [BITPIFO-1:0] push_1_idx; 57 | reg [BITPIFO-1:0] push_1_idx_raw; 58 | reg [BITPIFO-1:0] push_2_idx; 59 | reg [BITPIFO-1:0] push_2_idx_raw; 60 | reg push_hi; 61 | reg [BITPIFO-1:0] push_hi_idx; 62 | reg [BITPIFO-1:0] push_hi_idx_raw; 63 | reg [BITPRIO-1:0] push_hi_pri; 64 | reg [BITPORT-1:0] push_hi_prt; 65 | reg push_lo; 66 | reg [BITPIFO-1:0] push_lo_idx; 67 | reg [BITPIFO-1:0] push_lo_idx_raw; 68 | reg [BITPRIO-1:0] push_lo_pri; 69 | reg [BITPORT-1:0] push_lo_prt; 70 | 71 | wire pop_0_hit_del; 72 | wire [BITPIFO-1:0] pop_0_idx_del; 73 | wire [BITPIFO-1:0] push_1_idx_del; 74 | wire [BITPIFO-1:0] push_2_idx_del; 75 | wire [BITPIFO-1:0] push_1_idx_raw_del; 76 | wire [BITPIFO-1:0] push_2_idx_raw_del; 77 | wire push_hi_del; 78 | wire [BITPIFO-1:0] push_hi_idx_del; 79 | wire [BITPIFO-1:0] push_hi_idx_raw_del; 80 | wire [BITPRIO-1:0] push_hi_pri_del; 81 | wire [BITPORT-1:0] push_hi_prt_del; 82 | wire push_lo_del; 83 | wire [BITPIFO-1:0] push_lo_idx_del; 84 | wire [BITPIFO-1:0] push_lo_idx_raw_del; 85 | wire [BITPRIO-1:0] push_lo_pri_del; 86 | wire [BITPORT-1:0] push_lo_prt_del; 87 | shift #(.BITDATA(1+BITPIFO), .DELAY(FLOP_IDX)) pop_idx_del_inst (.clk(clk), .din({pop_0_hit,pop_0_idx}), .dout({pop_0_hit_del,pop_0_idx_del})); 88 | shift #(.BITDATA(2*BITPIFO), .DELAY(FLOP_IDX)) push_idx_del_inst (.clk(clk), .din({push_1_idx, push_2_idx}), .dout({push_1_idx_del,push_2_idx_del})); 89 | shift #(.BITDATA(2*BITPIFO), .DELAY(FLOP_IDX)) push_idx_raw_del_inst (.clk(clk), .din({push_1_idx_raw, push_2_idx_raw}), .dout({push_1_idx_raw_del,push_2_idx_raw_del})); 90 | shift #(.BITDATA(1+BITPIFO+BITPIFO+BITPRIO+BITPORT), .DELAY(FLOP_IDX)) push_hi_del_inst (.clk(clk), .din({push_hi, push_hi_idx, push_hi_idx_raw, push_hi_pri, push_hi_prt}), .dout({push_hi_del,push_hi_idx_del,push_hi_idx_raw_del,push_hi_pri_del, push_hi_prt_del})); 91 | shift #(.BITDATA(1+BITPIFO+BITPIFO+BITPRIO+BITPORT), .DELAY(FLOP_IDX)) push_lo_del_inst (.clk(clk), .din({push_lo, push_lo_idx, push_lo_idx_raw, push_lo_pri, push_lo_prt}), .dout({push_lo_del,push_lo_idx_del,push_lo_idx_raw_del,push_lo_pri_del, push_lo_prt_del})); 92 | 93 | 94 | 95 | reg [BITPIFO-1:0] pop_0_bmp_id; 96 | reg pop_0_bmp_hit; 97 | pop_pe_idx #(.NUMPIFO(NUMPIFO), .BITPORT(BITPORT)) pop_idx_inst (.port(oprt_0), .pf_port(pf_port), .pf_cnt(pf_cnt), .pop_idx(pop_0_bmp_id), .pop_hit(pop_0_bmp_hit)); 98 | 99 | reg [BITPIFO-1:0] push_1_bmp_id; 100 | push_pe_idx #(.NUMPIFO(NUMPIFO), .BITPRIO(BITPRIO)) push_1_idx_inst (.prio(upri_1), .pf_prio(pf_prio), .pf_cnt(pf_cnt), .push_idx(push_1_bmp_id)); 101 | 102 | reg [BITPIFO-1:0] push_2_bmp_id; 103 | push_pe_idx #(.NUMPIFO(NUMPIFO), .BITPRIO(BITPRIO)) push_2_idx_inst (.prio(upri_2), .pf_prio(pf_prio), .pf_cnt(pf_cnt), .push_idx(push_2_bmp_id)); 104 | 105 | reg pop_0_hit_tmp; 106 | reg [BITPIFO-1:0] pop_0_idx_tmp; 107 | always_comb begin 108 | pop_0_idx = pop_0_bmp_id; 109 | pop_0_hit_tmp = pop_0_bmp_hit; 110 | 111 | if(pop_0_hit_del && pop_0_idx > pop_0_idx_del) 112 | pop_0_idx = pop_0_idx -1; 113 | 114 | pop_0_idx_tmp = pop_0_idx; 115 | pop_0_idx = pop_0_idx + (push_1_del && pop_0_idx_tmp >= push_1_idx_raw_del) + (push_2_del && pop_0_idx_tmp >= push_2_idx_raw_del); 116 | 117 | if(push_hi_del && push_hi_prt_del==oprt_0) begin 118 | if(!pop_0_hit_tmp || push_hi_idx_raw_del <= pop_0_idx_tmp) begin 119 | pop_0_idx = push_hi_idx_del; 120 | pop_0_hit_tmp = 1; 121 | end 122 | end 123 | else if(push_lo_del && push_lo_prt_del==oprt_0 && (!pop_0_hit_tmp || push_lo_idx_raw_del <= pop_0_idx_tmp)) begin 124 | pop_0_idx = push_lo_idx_del; 125 | pop_0_hit_tmp = 1; 126 | end 127 | pop_0_hit = pop_0 && pop_0_hit_tmp; 128 | end 129 | 130 | always_comb begin 131 | push_1_idx = push_1_bmp_id; 132 | if(pop_0_hit_del && pop_0_idx_del < push_1_idx) 133 | push_1_idx = push_1_idx -1; 134 | push_1_idx = push_1_idx 135 | + (push_1_del && (push_1_idx_raw_del < push_1_idx || (push_1_idx_raw_del==push_1_idx && upri_1_del <= upri_1))) 136 | + (push_2_del && (push_2_idx_raw_del < push_1_idx || (push_2_idx_raw_del==push_1_idx && upri_2_del <= upri_1))); 137 | if(pop_0_hit && pop_0_idx < push_1_idx) 138 | push_1_idx = push_1_idx -1; 139 | 140 | push_1_idx_raw = push_1_idx; 141 | if(push_1 && push_2 && upri_2 < upri_1) 142 | push_1_idx = push_1_idx+1; 143 | end 144 | 145 | always_comb begin 146 | push_2_idx = push_2_bmp_id; 147 | if(pop_0_hit_del && pop_0_idx_del < push_2_idx) 148 | push_2_idx = push_2_idx -1; 149 | push_2_idx = push_2_idx 150 | + (push_1_del && (push_1_idx_raw_del < push_2_idx || (push_1_idx_raw_del==push_2_idx && upri_1_del <= upri_2))) 151 | + (push_2_del && (push_2_idx_raw_del < push_2_idx || (push_2_idx_raw_del==push_2_idx && upri_2_del <= upri_2))); 152 | if(pop_0_hit && pop_0_idx < push_2_idx) 153 | push_2_idx = push_2_idx -1; 154 | 155 | push_2_idx_raw = push_2_idx; 156 | if(push_1 && push_2 && upri_2 >= upri_1) 157 | push_2_idx = push_2_idx+1; 158 | end 159 | 160 | always_comb begin 161 | push_hi = push_1 || push_2; 162 | push_lo = push_1 && push_2; 163 | push_hi_idx = push_1_idx; 164 | push_lo_idx = push_2_idx; 165 | push_hi_idx_raw = push_1_idx_raw; 166 | push_lo_idx_raw = push_2_idx_raw; 167 | push_hi_pri = upri_1; 168 | push_lo_pri = upri_2; 169 | push_hi_prt = uprt_1; 170 | push_lo_prt = uprt_2; 171 | if((push_1 && push_2 && upri_2 < upri_1) || !push_1) begin 172 | push_hi_idx = push_2_idx; 173 | push_lo_idx = push_1_idx; 174 | push_hi_idx_raw = push_2_idx_raw; 175 | push_lo_idx_raw = push_1_idx_raw; 176 | push_hi_pri = upri_2; 177 | push_lo_pri = upri_1; 178 | push_hi_prt = uprt_2; 179 | push_lo_prt = uprt_1; 180 | end 181 | end 182 | 183 | always @(posedge clk) 184 | if(rst) 185 | pf_cnt <= 0; 186 | else 187 | pf_cnt <= pf_cnt - pop_0_hit_del + push_1_del + push_2_del; 188 | 189 | assign opri_0 = pf_prio[pop_0_idx_del]; 190 | assign odout_0 = pf_data[pop_0_idx_del]; 191 | assign ovld_0 = pop_0_hit_del; 192 | 193 | reg [NUMPIFO-1:0] pop_shift; 194 | always_comb 195 | for(integer i=0; i push_lo_idx_del && pv > 1; 206 | wire hi_move = push_hi_del && pv > push_hi_idx_del && pv > 0; 207 | wire po_move = pop_shift[pv]; 208 | wire shift_r1 = !pu1_set && !pu2_set && !lo_move && !hi_move && po_move; 209 | wire shift_l1 = !pu1_set && !pu2_set && ((pv>1 && lo_move && pop_shift[pv-2]) || (pv>0 && !lo_move && hi_move && !pop_shift[pv-1])); 210 | wire shift_l2 = !pu1_set && !pu2_set && (pv>1 && lo_move && !pop_shift[pv-2]); 211 | wire shift_no = !pu1_set && !pu2_set && !shift_r1 && !shift_l1 && !shift_l2; 212 | always_comb begin 213 | pf_data_nxt[pv] = '0; 214 | pf_prio_nxt[pv] = '0; 215 | pf_port_nxt[pv] = '0; 216 | if(pu1_set) begin 217 | pf_data_nxt[pv] = pf_data_nxt[pv] | udin_1_del; 218 | pf_prio_nxt[pv] = pf_prio_nxt[pv] | upri_1_del; 219 | pf_port_nxt[pv] = pf_port_nxt[pv] | uprt_1_del; 220 | end 221 | if(pu2_set) begin 222 | pf_data_nxt[pv] = pf_data_nxt[pv] | udin_2_del; 223 | pf_prio_nxt[pv] = pf_prio_nxt[pv] | upri_2_del; 224 | pf_port_nxt[pv] = pf_port_nxt[pv] | uprt_2_del; 225 | end 226 | if(shift_l2 && pv>1) begin 227 | pf_data_nxt[pv] = pf_data_nxt[pv] | pf_data[pv-2]; 228 | pf_prio_nxt[pv] = pf_prio_nxt[pv] | pf_prio[pv-2]; 229 | pf_port_nxt[pv] = pf_port_nxt[pv] | pf_port[pv-2]; 230 | end 231 | if(shift_l1 && pv>0) begin 232 | pf_data_nxt[pv] = pf_data_nxt[pv] | pf_data[pv-1]; 233 | pf_prio_nxt[pv] = pf_prio_nxt[pv] | pf_prio[pv-1]; 234 | pf_port_nxt[pv] = pf_port_nxt[pv] | pf_port[pv-1]; 235 | end 236 | if(shift_r1 && pv0) begin: flp_loop 275 | always @(posedge clk) 276 | din_reg[fdel_var] <= din_reg[fdel_var-1]; 277 | end else begin: nflp_loop 278 | always_comb 279 | din_reg[fdel_var] = din; 280 | end 281 | end 282 | endgenerate 283 | 284 | assign dout = din_reg[DELAY]; 285 | 286 | endmodule 287 | 288 | module priority_encode_log ( 289 | decode, 290 | encode,valid 291 | ); 292 | 293 | parameter width = 1024; 294 | parameter log_width = 10; 295 | 296 | localparam pot_width = 1 << log_width; 297 | 298 | input [width-1:0] decode; 299 | output [log_width-1:0] encode; 300 | output valid; 301 | 302 | wire [pot_width-1:0] pot_decode = {pot_width{1'b0}} | decode; 303 | 304 | reg [pot_width-1:0] part_idx [0:log_width-1]; 305 | 306 | always_comb begin 307 | part_idx[0] = 0; 308 | for(integer i=0; iprio); 363 | 364 | priority_encode_log #(.width(NUMPIFO), .log_width(BITPIFO)) push_pe (.decode(push_bmp), .encode(push_idx), .valid()); 365 | endmodule 366 | -------------------------------------------------------------------------------- /src/rtl/design/pifo_set.v: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // pifo_set maintains a sorted list of elements, 0 ... NUM_ELEMENTS 3 | // 0 --> highest priority element 4 | // It returns the highest priority element when queried 5 | // 6 | // eg: This is a valid state of the pifo_buffer 7 | // Index 0 1 2 3 4 5 6 7 8 9 8 | // Priority 237 234 37 23 22 10 x x x x 9 | // In this state, when queried, pifo_buffer[0] (ie. prio 237) will 10 | // be returned. 11 | // 12 | // A popped element may be reinserted with a different priority into 13 | // the pifo-set. i.e 237 may be popped, and re-inserted with a different 14 | // priority. 15 | // 16 | // The pifo-set effectively supports upto 2 inserts (push) and 1 dequeue (pop) 17 | // in the same cycle (you can have any combination of upto 2 inserts + 1 dequeue). 18 | //------------------------------------------------------------------------------ 19 | module pifo_set ( 20 | //-------------------------------------------------------------------------- 21 | // Global signals 22 | //-------------------------------------------------------------------------- 23 | clk, 24 | reset, 25 | 26 | //-------------------------------------------------------------------------- 27 | // Input interface 28 | //-------------------------------------------------------------------------- 29 | i__push_valid, // assert true, if you want to enqueue 30 | i__push_priority, 31 | i__push_flow_id, 32 | o__push_flow_empty, // Is the flow-id corresponding to the push flow id 33 | // empty currently? 34 | 35 | o__pifo_set_ready, // true, if pifo-set is not full: safe to enqueue 36 | o__pifo_set_ready__next, // [ssub] Remove if unnecessary, but I think it may be useful 37 | 38 | i__reinsert_valid, 39 | i__reinsert_priority, // we know the popped "index" from the output interface; no need 40 | // to pass it again 41 | 42 | //-------------------------------------------------------------------------- 43 | // Output interface 44 | //-------------------------------------------------------------------------- 45 | o__pop_valid, // true, if pifo-set is not empty ie. valid packet available for dequeue 46 | o__pop_priority, 47 | o__pop_flow_id, 48 | i__pop, // assert true, if you want to dequeue 49 | i__clear_all // clear pifo 50 | ); 51 | 52 | //------------------------------------------------------------------------------ 53 | // Parameters 54 | //------------------------------------------------------------------------------ 55 | parameter NUM_ELEMENTS = (16); 56 | parameter MAX_PRIORITY = (256); 57 | parameter DATA_WIDTH = $clog2(NUM_ELEMENTS+1); 58 | 59 | //------------------------------------------------------------------------------ 60 | // Constants 61 | //------------------------------------------------------------------------------ 62 | localparam PRIO_WIDTH = $clog2(MAX_PRIORITY); 63 | localparam IDX_WIDTH = $clog2(NUM_ELEMENTS+1); 64 | 65 | 66 | //------------------------------------------------------------------------------ 67 | // Local data structure 68 | //------------------------------------------------------------------------------ 69 | typedef struct { 70 | logic [DATA_WIDTH-1:0] data; 71 | logic [PRIO_WIDTH-1:0] prio; 72 | } PifoEntry; 73 | 74 | //------------------------------------------------------------------------------ 75 | // Global signals 76 | //------------------------------------------------------------------------------ 77 | input logic clk; 78 | input logic reset; 79 | 80 | //------------------------------------------------------------------------------ 81 | // Input interface 82 | //------------------------------------------------------------------------------ 83 | input logic i__push_valid; 84 | input logic [PRIO_WIDTH-1:0] i__push_priority; 85 | input logic [DATA_WIDTH-1:0] i__push_flow_id; 86 | output logic o__push_flow_empty; 87 | output logic o__pifo_set_ready; 88 | output logic o__pifo_set_ready__next; 89 | input logic i__reinsert_valid; 90 | input logic [PRIO_WIDTH-1:0] i__reinsert_priority; 91 | 92 | 93 | //------------------------------------------------------------------------------ 94 | // Output interface 95 | //------------------------------------------------------------------------------ 96 | output logic o__pop_valid; 97 | output logic [PRIO_WIDTH-1:0] o__pop_priority; 98 | output logic [DATA_WIDTH-1:0] o__pop_flow_id; 99 | input logic i__pop; 100 | input logic i__clear_all; 101 | 102 | //------------------------------------------------------------------------------ 103 | // Signals 104 | //------------------------------------------------------------------------------ 105 | logic w__push; 106 | logic w__pop; 107 | logic w__reinsert; 108 | logic [IDX_WIDTH-1:0] w__enq_high_idx; 109 | logic [IDX_WIDTH-1:0] w__enq_low_idx; 110 | PifoEntry w__enq_high_entry; 111 | PifoEntry w__enq_low_entry; 112 | 113 | logic w__pifo_set_ready; 114 | logic w__pifo_set_ready__next; 115 | logic w__pop_valid; 116 | logic [DATA_WIDTH-1:0] w__pop_flow_id; 117 | logic [PRIO_WIDTH-1:0] w__pop_priority; 118 | 119 | //------------------------------------------------------------------------------ 120 | // States and next signals 121 | //------------------------------------------------------------------------------ 122 | logic w__empty__next; 123 | logic r__empty__pff; 124 | logic w__full__next; 125 | logic r__full__pff; 126 | logic [IDX_WIDTH-1:0] r__pifo_count__pff; 127 | logic [IDX_WIDTH-1:0] w__pifo_count__next; 128 | 129 | logic [NUM_ELEMENTS-1:0] r__valid__pff; 130 | logic [NUM_ELEMENTS-1:0] r__valid__next; 131 | 132 | PifoEntry r__buffer__pff [NUM_ELEMENTS-1:0]; 133 | 134 | //------------------------------------------------------------------------------ 135 | // Output assignments 136 | //------------------------------------------------------------------------------ 137 | assign o__pifo_set_ready = w__pifo_set_ready; 138 | assign o__pifo_set_ready__next = w__pifo_set_ready__next; 139 | assign o__pop_valid = w__pop_valid; 140 | assign o__pop_flow_id = w__pop_flow_id; 141 | assign o__pop_priority = w__pop_priority; 142 | assign o__push_flow_empty = ~r__valid__pff[i__push_flow_id]; 143 | 144 | //------------------------------------------------------------------------------ 145 | // Output signals 146 | //------------------------------------------------------------------------------ 147 | always_comb 148 | begin 149 | w__pifo_set_ready = ~r__full__pff & (~reset); // When reset, ready should be low 150 | w__pifo_set_ready__next = ~w__full__next; 151 | w__pop_valid = ~r__empty__pff; // When reset, this _will_ be low 152 | w__pop_flow_id = r__buffer__pff[0].data; 153 | w__pop_priority = r__buffer__pff[0].prio; 154 | end 155 | 156 | //------------------------------------------------------------------------------ 157 | // Internal push and pop signals 158 | //------------------------------------------------------------------------------ 159 | always_comb 160 | begin 161 | // [ssub] All three of these signals can be high in 162 | // the same cycle. 163 | w__push = i__push_valid && o__pifo_set_ready; 164 | w__pop = o__pop_valid && i__pop; 165 | w__reinsert = i__reinsert_valid; 166 | end 167 | 168 | //------------------------------------------------------------------------------ 169 | // Pifo element count 170 | //------------------------------------------------------------------------------ 171 | always_comb 172 | begin 173 | w__pifo_count__next = r__pifo_count__pff; 174 | if (reset == 1'b1) 175 | w__pifo_count__next = '0; 176 | else if ( (w__push && w__reinsert && w__pop) || 177 | (w__push && ~w__reinsert && ~w__pop) || 178 | (~w__push && w__reinsert && ~w__pop) ) 179 | w__pifo_count__next = r__pifo_count__pff + 1'b1; 180 | else if ( (w__push && ~w__reinsert && w__pop) || 181 | (~w__push && w__reinsert && w__pop) || 182 | (~w__push && ~w__reinsert && ~w__pop) ) 183 | w__pifo_count__next = r__pifo_count__pff; 184 | else if (w__push && w__reinsert && ~w__pop) 185 | w__pifo_count__next = r__pifo_count__pff + 2'b10; // add 2 186 | else if (~w__push && ~w__reinsert && w__pop) 187 | w__pifo_count__next = r__pifo_count__pff - 1'b1; 188 | end 189 | 190 | always_ff @(posedge clk) 191 | begin 192 | if ((reset == 1'b1) || (i__clear_all == 1'b1)) 193 | r__pifo_count__pff <= '0; 194 | else 195 | r__pifo_count__pff <= w__pifo_count__next; 196 | end 197 | 198 | 199 | //------------------------------------------------------------------------------ 200 | // Internal full and empty states, signals 201 | //------------------------------------------------------------------------------ 202 | always_comb 203 | begin 204 | w__empty__next = (w__pifo_count__next == '0); 205 | w__full__next = (w__pifo_count__next == NUM_ELEMENTS); 206 | end 207 | 208 | always_ff @ (posedge clk) 209 | begin 210 | if(reset == 1'b1) 211 | begin 212 | r__empty__pff <= 1'b1; 213 | r__full__pff <= 1'b0; 214 | end 215 | else 216 | begin 217 | r__empty__pff <= w__empty__next; 218 | r__full__pff <= w__full__next; 219 | end 220 | end 221 | 222 | //------------------------------------------------------------------------------ 223 | // Internal valid signals for each flow 224 | //------------------------------------------------------------------------------ 225 | genvar flow_idx; 226 | generate for(flow_idx = 0; flow_idx < NUM_ELEMENTS; flow_idx = flow_idx + 1) 227 | begin: gen_valid_flow 228 | always_comb 229 | begin 230 | // [ssub] You cannot compute i__push_valid or i__reinsert_valid 231 | // based on r__valid__next[flow_idx] signal. It will lead to a 232 | // combinational loop. Be cognizant of this. 233 | if ( (i__push_valid && (i__push_flow_id == flow_idx)) || 234 | (i__reinsert_valid && (w__pop_flow_id == flow_idx)) ) 235 | r__valid__next[flow_idx] = 1'b1; 236 | else 237 | r__valid__next[flow_idx] = r__valid__pff[flow_idx]; 238 | end 239 | 240 | always_ff @(posedge clk) 241 | begin 242 | if (reset == 1'b1) 243 | r__valid__pff[flow_idx] <= 1'b0; 244 | else 245 | r__valid__pff[flow_idx] <= r__valid__next[flow_idx]; 246 | end 247 | end 248 | endgenerate 249 | 250 | //------------------------------------------------------------------------------ 251 | // Pifo next state : Core PIFO logic 252 | //------------------------------------------------------------------------------ 253 | // Pick higher and lower entry 254 | always_comb 255 | begin 256 | w__enq_high_entry.prio = '0; 257 | w__enq_high_entry.data = '0; 258 | w__enq_low_entry.prio = '0; 259 | w__enq_low_entry.data = '0; 260 | 261 | if (w__push && w__reinsert) 262 | begin 263 | if (i__push_priority > i__reinsert_priority) 264 | begin 265 | w__enq_high_entry.prio = i__push_priority; 266 | w__enq_high_entry.data = i__push_flow_id; 267 | w__enq_low_entry.prio = i__reinsert_priority; 268 | w__enq_low_entry.data = r__buffer__pff[0].data; // TODO Check if this needs to be refetched 269 | end 270 | else 271 | begin 272 | w__enq_low_entry.prio = i__push_priority; 273 | w__enq_low_entry.data = i__push_flow_id; 274 | w__enq_high_entry.prio = i__reinsert_priority; 275 | w__enq_high_entry.data = r__buffer__pff[0].data; // TODO Check if this needs to be refetched 276 | end 277 | end 278 | else if (w__push && ~w__reinsert) 279 | begin 280 | w__enq_high_entry.prio = i__push_priority; 281 | w__enq_high_entry.data = i__push_flow_id; 282 | end 283 | else if (~w__push && w__reinsert) 284 | begin 285 | w__enq_high_entry.prio = i__reinsert_priority; 286 | w__enq_high_entry.data = r__buffer__pff[0].data; // FIXME Check if this needs to be refetched 287 | end 288 | end 289 | 290 | // Enqueue indices computation 291 | integer idx1; 292 | always_comb 293 | begin 294 | if (w__enq_high_entry.prio > r__buffer__pff[0].prio) 295 | begin 296 | w__enq_high_idx = w__pop ? 1'b1 : '0; 297 | end 298 | else 299 | begin 300 | w__enq_high_idx = r__pifo_count__pff; 301 | for(idx1 = 0; idx1 < NUM_ELEMENTS; idx1 = idx1 + 1) 302 | if ((idx1 < r__pifo_count__pff) && (w__enq_high_entry.prio < r__buffer__pff[idx1].prio)) 303 | w__enq_high_idx = idx1; 304 | w__enq_high_idx = w__enq_high_idx + 1'b1; 305 | end 306 | end 307 | 308 | integer idx2; 309 | always_comb 310 | begin 311 | // By construction w__enq_high_idx >= w__enq_low_idx 312 | if (w__enq_low_entry.prio > r__buffer__pff[0].prio) 313 | begin 314 | w__enq_low_idx = w__pop ? 1'b1 : '0; 315 | end 316 | else 317 | begin 318 | w__enq_low_idx = r__pifo_count__pff; 319 | for(idx2 = 0; idx2 < NUM_ELEMENTS; idx2 = idx2 + 1) 320 | if ((idx2 < r__pifo_count__pff) && (w__enq_low_entry.prio < r__buffer__pff[idx2].prio)) 321 | w__enq_low_idx = idx2; 322 | w__enq_low_idx = w__enq_low_idx + 1'b1; 323 | end 324 | end 325 | 326 | 327 | // Next state 328 | genvar pifo_idx; 329 | generate for(pifo_idx = 0; pifo_idx < NUM_ELEMENTS; pifo_idx = pifo_idx + 1) 330 | begin: gen_pifo_next_state 331 | PifoEntry r__buffer__next; 332 | PifoEntry w__buffer_shift; 333 | PifoEntry w__buffer_noshift; 334 | 335 | // In event of a dequeue, we have to left shift elements. I use the 336 | // shorthand shift for denoting this. In addition to the left shift 337 | // we may have to right shift some elements. 338 | // Note that this logic works correctly, even if (w__enq_high_idx == w__enq_low_idx) 339 | // i.e. we want to insert the two items one after the other. 340 | always_comb 341 | begin 342 | w__buffer_shift = r__buffer__pff[pifo_idx]; 343 | if (pifo_idx < (w__enq_high_idx-1)) // must also be less than w__enq_low_idx 344 | w__buffer_shift = r__buffer__pff[pifo_idx+1]; 345 | else if (pifo_idx == (w__enq_high_idx-1)) 346 | w__buffer_shift = w__enq_high_entry; 347 | else if ((pifo_idx >= w__enq_high_idx) && (pifo_idx < w__enq_low_idx)) 348 | w__buffer_shift = r__buffer__pff[pifo_idx]; 349 | else if (pifo_idx == w__enq_low_idx) 350 | w__buffer_shift = w__enq_low_entry; 351 | else if (pifo_idx > w__enq_low_idx) 352 | w__buffer_shift = r__buffer__pff[pifo_idx - 1]; 353 | end 354 | 355 | // In event of no pop (dequeue), we do not have to left-shift elements (hence the shorthand 356 | // noshift). We still may have to shift elements to the right if we have a push. 357 | always_comb 358 | begin 359 | w__buffer_noshift = r__buffer__pff[pifo_idx]; 360 | // Strictly we should have atmost w__enq_high_idx 361 | // No pop => No reinsert; So only if there is a push will there 362 | // be a change in state 363 | if (pifo_idx == w__enq_high_idx) 364 | w__buffer_noshift = w__enq_high_entry; 365 | else if (pifo_idx > w__enq_high_idx) 366 | w__buffer_noshift = r__buffer__pff[pifo_idx-1]; 367 | end 368 | 369 | always_comb 370 | begin 371 | if (w__pop) 372 | r__buffer__next = w__buffer_shift; 373 | else 374 | r__buffer__next = w__buffer_noshift; 375 | end 376 | 377 | always_ff @(posedge clk) 378 | begin 379 | if (reset) 380 | begin 381 | r__buffer__pff[pifo_idx].data <= '0; 382 | r__buffer__pff[pifo_idx].prio <= '0; 383 | end 384 | else 385 | r__buffer__pff[pifo_idx] <= r__buffer__next; 386 | end 387 | end 388 | endgenerate 389 | 390 | endmodule 391 | --------------------------------------------------------------------------------