diff --git a/examples/aliases/Makefile b/examples/aliases/Makefile new file mode 100644 index 0000000..e2cc62a --- /dev/null +++ b/examples/aliases/Makefile @@ -0,0 +1,14 @@ +RTL_TARGETS = $(subst .rdl,.sv,srdl2sv_out/$(shell ls *.rdl)) + +.PHONY: clean + +default: verilog_compile + +verilog_compile: $(RTL_TARGETS) + verilator -cc -sv $(shell ls srdl2sv_out/*.sv) + +srdl2sv_out/%.sv: %.rdl $(shell which srdl2sv) + srdl2sv $< --out-dir $(shell dirname $@) --stdout-logging INFO -d 31 + +clean: + rm -rf srdl2sv_out diff --git a/examples/aliases/aliases.rdl b/examples/aliases/aliases.rdl new file mode 100644 index 0000000..f0b4273 --- /dev/null +++ b/examples/aliases/aliases.rdl @@ -0,0 +1,63 @@ + +addrmap aliases { + /////////////////////////// + // Example SystemRDL LRM // + /////////////////////////// + reg some_intr_r { + desc = "This register shows the alias example from Section 10.5.2 of the + SystemRDL2.0 spec (with some slight adaptations to make it compilable)."; + field { + level intr; + hw=w; + sw=rw; + woclr; + } some_event; + }; + + some_intr_r event1; + + // Create an alias for the DV team to use and modify its properties + // so that DV can force interrupt events and allow more rigorous structural + // testing of the interrupt. + alias event1 some_intr_r event1_for_dv; + event1_for_dv.some_event->woset = true; + + ////////////////////////// + // Example field-subset // + ////////////////////////// + field field_templ { + sw = rw; + hw = rw; + wel; + }; + + reg four_field_reg { + desc = "This is a register with 4 fields."; + + field_templ f1 [7:0]; + field_templ f2 [15:8]; + field_templ f3 [23:16]; + field_templ f4 [31:24]; + + + f3->swmod = true; // swmod does work for aliased registers + f4->rclr = true; // Show rclr feature + }; + + reg two_field_alias { + desc = "It is not mandatory that aliases have all fields of the original + register. A subset of the fields can be made accessible and they + can have different names."; + + field_templ field_1 [7:0]; + // Removed f2 + // Removed f3 + field_templ field_4 [31:24]; + + field_4->woclr = true; // Different option compared to four_field_reg.f1 + }; + + four_field_reg four_field_reg; // Actual register + alias four_field_reg two_field_alias two_field_alias; // Alias with different properties + +}; diff --git a/examples/aliases/srdl2sv_out/aliases.sv b/examples/aliases/srdl2sv_out/aliases.sv new file mode 100644 index 0000000..0ebeb74 --- /dev/null +++ b/examples/aliases/srdl2sv_out/aliases.sv @@ -0,0 +1,486 @@ +/***************************************************************** + * + * ███████╗██████╗ ██████╗ ██╗ ██████╗ ███████╗██╗ ██╗ + * ██╔════╝██╔══██╗██╔══██╗██║ ╚════██╗██╔════╝██║ ██║ + * ███████╗██████╔╝██║ ██║██║ █████╔╝███████╗██║ ██║ + * ╚════██║██╔══██╗██║ ██║██║ ██╔═══╝ ╚════██║╚██╗ ██╔╝ + * ███████║██║ ██║██████╔╝███████╗███████╗███████║ ╚████╔╝ + * ╚══════╝╚═╝ ╚═╝╚═════╝ ╚══════╝╚══════╝╚══════╝ ╚═══╝ + * + * The present RTL was generated by srdl2sv v0.01. The RTL and all + * templates the RTL is derived from are licensed under the MIT + * license. The license is shown below. + * + * srdl2sv itself is licensed under GPLv3. + * + * Maintainer : Dennis Potter + * Report Bugs: https://github.com/Silicon1602/srdl2sv/issues + * + * ===GENERATION INFORMATION====================================== + * + * Generation information: + * - User: : dpotter + * - Time : November 06 2021 22:46:49 + * - Path : /home/dpotter/srdl2sv/examples/aliases + * - RDL file : ['aliases.rdl'] + * - Hostname : ArchXPS + * + * RDL include directories: + * - + * + * Commandline arguments to srdl2sv: + * - Ouput Directory : srdl2sv_out + * - Stream Log Level : INFO + * - File Log Level : NONE + * - Use Real Tabs : False + * - Tab Width : 4 + * - Enums Enabled : True + * - Address Errors : True + * - Unpacked I/Os : True + * - Register Bus Type: amba3ahblite + * - Address width : 32 + * - Byte enables : True + * - Descriptions : {'AddrMap': True, 'RegFile': True, 'Memory': True, 'Register': True, 'Field': True} + * + * ===LICENSE OF ALIASES.SV===================================== + * + * Copyright 2021 Dennis Potter + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + ****************************************************************/ +module aliases + +( + // Resets + + + // Inputs + input clk , + input HRESETn , + input [31:0] HADDR , + input HWRITE , + input [2:0] HSIZE , + input [3:0] HPROT , + input [1:0] HTRANS , + input [32-1:0] HWDATA , + input HSEL , + input [0:0] event1__some_event_in , + input four_field_reg__f1_hw_wr, + input [7:0] four_field_reg__f1_in , + input four_field_reg__f2_hw_wr, + input [7:0] four_field_reg__f2_in , + input four_field_reg__f3_hw_wr, + input [7:0] four_field_reg__f3_in , + input four_field_reg__f4_hw_wr, + input [7:0] four_field_reg__f4_in , + + // Outputs + output HREADYOUT , + output HRESP , + output [32-1:0] HRDATA , + output event1_intr , + output [7:0] four_field_reg__f1_r , + output [7:0] four_field_reg__f2_r , + output [7:0] four_field_reg__f3_r , + output reg four_field_reg__f3_swmod, + output [7:0] four_field_reg__f4_r +); + + +// Internal signals +srdl2sv_widget_if #(.ADDR_W (32), .DATA_W(32)) widget_if; + +/******************************************************************* + * AMBA 3 AHB Lite Widget + * ====================== + * Naming conventions + * - widget_if -> SystemVerilog interface to between widgets + * and the internal srdl2sv registers. + * - H* -> Signals as defined in AMBA3 AHB Lite + * specification + * - clk -> Clock that drives registers and the bus + *******************************************************************/ +srdl2sv_amba3ahblite + #(.FLOP_REGISTER_IF (0), + .BUS_BITS (32), + .NO_BYTE_ENABLE (0)) +srdl2sv_amba3ahblite_inst + (// Bus protocol + .HRESETn, + .HCLK (clk), + .HADDR, + .HWRITE, + .HSIZE, + .HPROT, + .HTRANS, + .HWDATA, + .HSEL, + + .HREADYOUT, + .HRESP, + .HRDATA, + + // Interface to internal logic + .widget_if); + +/******************************************************************* +/******************************************************************* +/* REGISTER : event1 +/* DIMENSION : 0 +/* DEPTHS (per dimension): [] +/******************************************************************* +/*******************************************************************/ + +/**REGISTER DESCRIPTION********************************************* +This register shows the alias example from Section 10.5.2 of the +SystemRDL2.0 spec (with some slight adaptations to make it compilable). +/*******************************************************************/ +logic event1_active ; +logic event1_sw_wr ; +logic event1_for_dv_active ; +logic event1_for_dv_sw_wr ; +logic [31:0] event1_data_mux_in ; +logic event1_rdy_mux_in ; +logic event1_err_mux_in ; +logic [31:0] event1_for_dv_data_mux_in ; +logic event1_for_dv_rdy_mux_in ; +logic event1_for_dv_err_mux_in ; +logic [0:0] event1__some_event_sticky_latch; +logic [0:0] event1__some_event_q ; + + +// Register-activation for 'event1' +assign event1_active = widget_if.addr == 0; +assign event1_sw_wr = event1_active && widget_if.w_vld; + +// Register-activation for 'event1_for_dv' (alias) +assign event1_for_dv_active = widget_if.addr == 4; +assign event1_for_dv_sw_wr = event1_for_dv_active && widget_if.w_vld; + +//-----------------FIELD SUMMARY----------------- +// name : some_event (event1[0:0]) +// access : hw = w +// sw = rw (precedence) +// reset : - / - +// flags : ['intr', 'intr type', 'sw', 'woclr'] +// external : False +// storage type : StorageType.FLOPS +//----------------------------------------------- + +always_ff @(posedge clk) +begin + if (event1_sw_wr) + begin + if (widget_if.byte_en[0]) // woclr property + event1__some_event_q[0:0] <= event1__some_event_q[0:0] & ~widget_if.w_data[0:0]; + end + else + if (event1_for_dv_sw_wr) + begin + if (widget_if.byte_en[0]) // woset property + event1__some_event_q[0:0] <= event1__some_event_q[0:0] | widget_if.w_data[0:0]; + end + else + begin + for (int i = 0; i < 1; i++) + begin + if (event1__some_event_sticky_latch[i]) + begin + // Stickybit. Keep value until software clears it + event1__some_event_q[i] <= 1'b1; + end + end + end +end // of event1__some_event's always_ff + +// Define signal that causes the interrupt to be set (level-type interrupt) +assign event1__some_event_sticky_latch = event1__some_event_in; + + +/************************************** + * Register contains interrupts * + **************************************/ +// Register has at least one interrupt field +assign event1_intr = |(event1__some_event_q); + + +/********************************************** + * Assign all fields to signal to Mux * + **********************************************/ +// Assign all fields. Fields that are not readable are tied to 0. +assign event1_data_mux_in = {{31{1'b0}}, event1__some_event_q}; + +// Internal registers are ready immediately +assign event1_rdy_mux_in = 1'b1; + +// Return an error if *no* read and *no* write was succesful. If some bits +// cannot be read/written but others are succesful, don't return and error +// Hence, as long as one action can be succesful, no error will be returned. +assign event1_err_mux_in = !((widget_if.r_vld && (widget_if.byte_en[0])) || (widget_if.w_vld && (widget_if.byte_en[0]))); + +/********************************************** + * Assign all fields to signal to Mux (alias) * + **********************************************/ +// Assign all fields. Fields that are not readable are tied to 0. +assign event1_for_dv_data_mux_in = {{31{1'b0}}, event1__some_event_q}; + +// Internal registers are ready immediately +assign event1_for_dv_rdy_mux_in = 1'b1; + +// Return an error if *no* read and *no* write was succesful. If some bits +// cannot be read/written but others are succesful, don't return and error +// Hence, as long as one action can be succesful, no error will be returned. +assign event1_for_dv_err_mux_in = !((widget_if.r_vld && (widget_if.byte_en[0])) || (widget_if.w_vld && (widget_if.byte_en[0]))); + +/******************************************************************* +/******************************************************************* +/* REGISTER : four_field_reg +/* DIMENSION : 0 +/* DEPTHS (per dimension): [] +/******************************************************************* +/*******************************************************************/ + +/**REGISTER DESCRIPTION********************************************* +This is a register with 4 fields. +/*******************************************************************/ +logic four_field_reg_active ; +logic four_field_reg_sw_wr ; +logic two_field_alias_active ; +logic two_field_alias_sw_wr ; +logic four_field_reg__any_alias_sw_wr; +logic [31:0] four_field_reg_data_mux_in ; +logic four_field_reg_rdy_mux_in ; +logic four_field_reg_err_mux_in ; +logic [31:0] two_field_alias_data_mux_in ; +logic two_field_alias_rdy_mux_in ; +logic two_field_alias_err_mux_in ; +logic [7:0] four_field_reg__f1_q ; +logic [7:0] four_field_reg__f2_q ; +logic [7:0] four_field_reg__f3_q ; +logic [7:0] four_field_reg__f4_q ; + + +// Register-activation for 'four_field_reg' +assign four_field_reg_active = widget_if.addr == 8; +assign four_field_reg_sw_wr = four_field_reg_active && widget_if.w_vld; + +// Register-activation for 'two_field_alias' (alias) +assign two_field_alias_active = widget_if.addr == 12; +assign two_field_alias_sw_wr = two_field_alias_active && widget_if.w_vld; + +// Combined register activation. These will become active on +// access via any of the alias registers. +assign four_field_reg__any_alias_sw_wr = four_field_reg_sw_wr || two_field_alias_sw_wr; + +//-----------------FIELD SUMMARY----------------- +// name : f1 (four_field_reg[7:0]) +// access : hw = rw +// sw = rw (precedence) +// reset : - / - +// flags : ['sw', 'wel'] +// external : False +// storage type : StorageType.FLOPS +//----------------------------------------------- + +always_ff @(posedge clk) +begin + if (four_field_reg_sw_wr) + begin + if (widget_if.byte_en[0]) + four_field_reg__f1_q[7:0] <= widget_if.w_data[7:0]; + end + else + if (two_field_alias_sw_wr) + begin + if (widget_if.byte_en[0]) + four_field_reg__f1_q[7:0] <= widget_if.w_data[7:0]; + end + else + if (!four_field_reg__f1_hw_wr) + four_field_reg__f1_q <= four_field_reg__f1_in; +end // of four_field_reg__f1's always_ff + +// Connect register to hardware output port +assign four_field_reg__f1_r = four_field_reg__f1_q; + + + +//-----------------FIELD SUMMARY----------------- +// name : f2 (four_field_reg[15:8]) +// access : hw = rw +// sw = rw (precedence) +// reset : - / - +// flags : ['sw', 'wel'] +// external : False +// storage type : StorageType.FLOPS +//----------------------------------------------- + +always_ff @(posedge clk) +begin + if (four_field_reg_sw_wr) + begin + if (widget_if.byte_en[1]) + four_field_reg__f2_q[7:0] <= widget_if.w_data[15:8]; + end + else + if (!four_field_reg__f2_hw_wr) + four_field_reg__f2_q <= four_field_reg__f2_in; +end // of four_field_reg__f2's always_ff + +// Connect register to hardware output port +assign four_field_reg__f2_r = four_field_reg__f2_q; + + + +//-----------------FIELD SUMMARY----------------- +// name : f3 (four_field_reg[23:16]) +// access : hw = rw +// sw = rw (precedence) +// reset : - / - +// flags : ['sw', 'wel', 'swmod'] +// external : False +// storage type : StorageType.FLOPS +//----------------------------------------------- + +always_ff @(posedge clk) +begin + if (four_field_reg_sw_wr) + begin + if (widget_if.byte_en[2]) + four_field_reg__f3_q[7:0] <= widget_if.w_data[23:16]; + end + else + if (!four_field_reg__f3_hw_wr) + four_field_reg__f3_q <= four_field_reg__f3_in; +end // of four_field_reg__f3's always_ff + +// Connect register to hardware output port +assign four_field_reg__f3_r = four_field_reg__f3_q; + +// Combinational block to generate swmod-output signals +always_comb +begin + four_field_reg__f3_swmod = 0; + four_field_reg__f3_swmod |= four_field_reg__any_alias_sw_wr && |widget_if.byte_en[2:2]; +end + + +//-----------------FIELD SUMMARY----------------- +// name : f4 (four_field_reg[31:24]) +// access : hw = rw +// sw = rw (precedence) +// reset : - / - +// flags : ['sw', 'wel', 'rclr'] +// external : False +// storage type : StorageType.FLOPS +//----------------------------------------------- + +always_ff @(posedge clk) +begin + if (four_field_reg_sw_wr) + begin + if (widget_if.byte_en[3]) + four_field_reg__f4_q[7:0] <= widget_if.w_data[31:24]; + end + else + if (two_field_alias_sw_wr) + begin + if (widget_if.byte_en[3]) // woclr property + four_field_reg__f4_q[7:0] <= four_field_reg__f4_q[7:0] & ~widget_if.w_data[31:24]; + end + else + if (!four_field_reg__f4_hw_wr) + four_field_reg__f4_q <= four_field_reg__f4_in; +end // of four_field_reg__f4's always_ff + +// Connect register to hardware output port +assign four_field_reg__f4_r = four_field_reg__f4_q; + + + + +/********************************************** + * Assign all fields to signal to Mux * + **********************************************/ +// Assign all fields. Fields that are not readable are tied to 0. +assign four_field_reg_data_mux_in = {four_field_reg__f4_q, four_field_reg__f3_q, four_field_reg__f2_q, four_field_reg__f1_q}; + +// Internal registers are ready immediately +assign four_field_reg_rdy_mux_in = 1'b1; + +// Return an error if *no* read and *no* write was succesful. If some bits +// cannot be read/written but others are succesful, don't return and error +// Hence, as long as one action can be succesful, no error will be returned. +assign four_field_reg_err_mux_in = !((widget_if.r_vld && (|widget_if.byte_en[3:0])) || (widget_if.w_vld && (|widget_if.byte_en[3:0]))); + +/********************************************** + * Assign all fields to signal to Mux (alias) * + **********************************************/ +// Assign all fields. Fields that are not readable are tied to 0. +assign two_field_alias_data_mux_in = {four_field_reg__f4_q, {16{1'b0}}, four_field_reg__f1_q}; + +// Internal registers are ready immediately +assign two_field_alias_rdy_mux_in = 1'b1; + +// Return an error if *no* read and *no* write was succesful. If some bits +// cannot be read/written but others are succesful, don't return and error +// Hence, as long as one action can be succesful, no error will be returned. +assign two_field_alias_err_mux_in = !((widget_if.r_vld && (widget_if.byte_en[3] || widget_if.byte_en[0])) || (widget_if.w_vld && (widget_if.byte_en[3] || widget_if.byte_en[0]))); + +// Read multiplexer +always_comb +begin + unique case (1'b1) + event1_active: + begin + widget_if.r_data = event1_data_mux_in; + widget_if.err = event1_err_mux_in; + widget_if.rdy = event1_rdy_mux_in; + end + event1_for_dv_active: + begin + widget_if.r_data = event1_for_dv_data_mux_in; + widget_if.err = event1_for_dv_err_mux_in; + widget_if.rdy = event1_for_dv_rdy_mux_in; + end + four_field_reg_active: + begin + widget_if.r_data = four_field_reg_data_mux_in; + widget_if.err = four_field_reg_err_mux_in; + widget_if.rdy = four_field_reg_rdy_mux_in; + end + two_field_alias_active: + begin + widget_if.r_data = two_field_alias_data_mux_in; + widget_if.err = two_field_alias_err_mux_in; + widget_if.rdy = two_field_alias_rdy_mux_in; + end + default: + begin + // If the address is not found, return an error + widget_if.r_data = 0; + widget_if.err = 1; + widget_if.rdy = widget_if.r_vld || widget_if.w_vld; + end + endcase +end +endmodule diff --git a/examples/aliases/srdl2sv_out/srdl2sv_amba3ahblite.sv b/examples/aliases/srdl2sv_out/srdl2sv_amba3ahblite.sv new file mode 100644 index 0000000..d1598f9 --- /dev/null +++ b/examples/aliases/srdl2sv_out/srdl2sv_amba3ahblite.sv @@ -0,0 +1,312 @@ +/* + * Copyright 2021 Dennis Potter + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +module srdl2sv_amba3ahblite #( + parameter bit FLOP_REGISTER_IF = 0, + parameter BUS_BITS = 32, + parameter NO_BYTE_ENABLE = 0 +) +( + // Bus protocol + input HCLK, + input HRESETn, + input HSEL, + input [31:0] HADDR, + input HWRITE, + input [ 2:0] HSIZE, + input [ 3:0] HPROT, // Might be used in the future together with an RDL UDP + input [ 1:0] HTRANS, + input [BUS_BITS-1:0] HWDATA, + + output logic HREADYOUT, + output logic HRESP, + output logic [BUS_BITS-1:0] HRDATA, + + // Interface to internal logic + srdl2sv_widget_if.widget widget_if +); + + localparam BUS_BYTES = BUS_BITS/8; + localparam BUS_BYTES_W = $clog2(BUS_BYTES); + + /*********************** + * Define enums + ***********************/ + typedef enum logic [2:0] { + SINGLE = 3'b000, + INCR = 3'b001, + WRAP4 = 3'b010, + INCR4 = 3'b011, + WRAP8 = 3'b100, + INCR8 = 3'b101, + WRAP16 = 3'b110, + INCR16 = 3'b111 + } HBURST_t; + + typedef enum logic [1:0] { + IDLE = 2'b00, + BUSY = 2'b01, + NONSEQ = 2'b10, + SEQ = 2'b11 + } HTRANS_t; + + typedef enum logic { + OKAY = 1'b0, + ERROR = 1'b1 + } HRESP_t; + + typedef enum logic { + READ = 1'b0, + WRITE = 1'b1 + } OP_t; + + typedef enum logic [1:0] { + FSM_IDLE = 2'b00, + FSM_TRANS = 2'b01, + FSM_ERR_0 = 2'b10, + FSM_ERR_1 = 2'b11 + } fsm_t; + + /**************************** + * Determine current address + ****************************/ + logic [31:0] HADDR_q; + logic [2:0] HSIZE_q; + OP_t operation_q; + + wire addr_err = HADDR % (32'b1 << HSIZE) != 32'b0; + + always_ff @ (posedge HCLK) + begin + case (HTRANS) + IDLE: ;// Do nothing + BUSY: ;// Do nothing + NONSEQ: + begin + // When a transfer is extended it has the side-effecxt + // of extending the address phase of the next transfer + if (HREADYOUT) + begin + HADDR_q <= HADDR; + HSIZE_q <= HSIZE; + operation_q <= HWRITE ? WRITE : READ; + end + end + SEQ: + begin + if (HREADYOUT) + begin + HADDR_q <= HADDR; + HSIZE_q <= HSIZE; + end + end + endcase + end + + /**************************** + * Statemachine + ****************************/ + logic [BUS_BITS-1:0] HRDATA_temp; + fsm_t fsm_next, fsm_q; + + always_comb + begin + // Defaults + HREADYOUT = 1'b1; + HRESP = OKAY; + + // When reading back, the data of the bit that was accessed over the bus + // should be at byte 0 of the HRDATA bus and bits that were not accessed + // should be masked with 0s. + HRDATA_temp = widget_if.r_data >> (8*HADDR_q[BUS_BYTES_W-1:0]); + + for (int i = 0; i < BUS_BYTES; i++) + if (i < (1 << HSIZE_q)) + HRDATA[8*(i+1)-1 -: 8] = HRDATA_temp[8*(i+1)-1 -: 8]; + else + HRDATA[8*(i+1)-1 -: 8] = 8'b0; + + widget_if_w_vld_next = 0; + widget_if_r_vld_next = 0; + fsm_next = fsm_q; + + case (fsm_q) + default: // FSM_IDLE + begin + if (HSEL && HTRANS > BUSY) + begin + if (addr_err) + // In case the address is illegal, switch to an error state + fsm_next = FSM_ERR_0; + else if (HTRANS == NONSEQ) + // If NONSEQ, go to NONSEQ state + fsm_next = FSM_TRANS; + else if (HTRANS == SEQ) + // If a SEQ is provided, something is wrong + fsm_next = FSM_ERR_0; + end + end + FSM_TRANS: + begin + HREADYOUT = widget_if.rdy; + widget_if_w_vld_next = operation_q == WRITE; + widget_if_r_vld_next = operation_q == READ; + + if (HTRANS == BUSY) + begin + // Wait + fsm_next = FSM_TRANS; + end + else if (widget_if.err && widget_if.rdy) + begin + HREADYOUT = 0; + HRESP = ERROR; + fsm_next = FSM_ERR_1; + end + else if (HTRANS == NONSEQ) + begin + // Another unrelated access is coming + fsm_next = FSM_TRANS; + end + else if (HTRANS == SEQ) + begin + // Another part of the burst is coming + fsm_next = FSM_TRANS; + end + else if (HTRANS == IDLE) + begin + // All done, wrapping things up! + fsm_next = widget_if.rdy ? FSM_IDLE : FSM_TRANS; + end + end + FSM_ERR_0: + begin + HREADYOUT = 0; + + if (HTRANS == BUSY) + begin + // Slaves must always provide a zero wait state OKAY response + // to BUSY transfers and the transfer must be ignored by the slave. + HRESP = OKAY; + fsm_next = FSM_ERR_0; + end + else + begin + HRESP = ERROR; + fsm_next = FSM_ERR_1; + end + end + FSM_ERR_1: + begin + if (HTRANS == BUSY) + begin + // Slaves must always provide a zero wait state OKAY response + // to BUSY transfers and the transfer must be ignored by the slave. + HREADYOUT = 0; + HRESP = OKAY; + fsm_next = FSM_ERR_0; + end + else + begin + HREADYOUT = 1; + HRESP = ERROR; + + fsm_next = FSM_IDLE; + end + end + endcase + end + + + always_ff @ (posedge HCLK or negedge HRESETn) + if (!HRESETn) + fsm_q <= FSM_IDLE; + else + fsm_q <= fsm_next; + + /*** + * Determine the number of active bytes + ***/ + logic [BUS_BYTES-1:0] HSIZE_bitfielded; + logic [BUS_BYTES-1:0] widget_if_byte_en_next; + logic widget_if_w_vld_next; + logic widget_if_r_vld_next; + + generate + if (NO_BYTE_ENABLE) + begin + assign widget_if_byte_en_next = {BUS_BYTES{1'b1}}; + end + else + begin + always_comb + begin + for (int i = 0; i < BUS_BYTES; i++) + HSIZE_bitfielded[i] = i < (1 << HSIZE_q); + + // Shift if not the full bus is accessed + widget_if_byte_en_next = HSIZE_bitfielded << (HADDR_q % BUS_BYTES); + end + end + endgenerate + + /*** + * Drive interface to registers + ***/ + generate + if (FLOP_REGISTER_IF) + begin + always_ff @ (posedge HCLK or negedge HRESETn) + if (!HRESETn) + begin + widget_if.w_vld <= 1'b0; + widget_if.r_vld <= 1'b0; + end + else + begin + widget_if.w_vld <= widget_if_w_vld_next; + widget_if.r_vld <= widget_if_r_vld_next; + end + + always_ff @ (posedge HCLK) + begin + widget_if.addr <= {HADDR_q[31:BUS_BYTES_W], {BUS_BYTES_W{1'b0}}}; + widget_if.w_data <= HWDATA << (8*HADDR_q[BUS_BYTES_W-1:0]); + widget_if.byte_en <= widget_if_byte_en_next; + end + end + else + begin + assign widget_if.w_vld = widget_if_w_vld_next; + assign widget_if.r_vld = widget_if_r_vld_next; + assign widget_if.addr = {HADDR_q[31:BUS_BYTES_W], {BUS_BYTES_W{1'b0}}}; + assign widget_if.w_data = HWDATA << (8*HADDR_q[BUS_BYTES_W-1:0]); + assign widget_if.byte_en = widget_if_byte_en_next; + end + endgenerate + +endmodule + + diff --git a/examples/aliases/srdl2sv_out/srdl2sv_widget_if.sv b/examples/aliases/srdl2sv_out/srdl2sv_widget_if.sv new file mode 100644 index 0000000..b85afc4 --- /dev/null +++ b/examples/aliases/srdl2sv_out/srdl2sv_widget_if.sv @@ -0,0 +1,30 @@ +interface srdl2sv_widget_if #( + parameter ADDR_W = 32, + parameter DATA_W = 32 +); + + localparam DATA_BYTES = DATA_W >> 3; + + logic [ADDR_W-1:0] addr; + logic [DATA_W-1:0] w_data; + logic w_vld; + logic r_vld; + logic [DATA_BYTES-1:0] byte_en; + + logic [DATA_W-1:0] r_data; + logic rdy; + logic err; + + modport widget ( + output addr, + output w_data, + output w_vld, + output r_vld, + output byte_en, + + input r_data, + input rdy, + input err + ); +endinterface +