From ba45cfc64a9453bbdb5f36d0d2b7439f2ed25f82 Mon Sep 17 00:00:00 2001 From: Dennis Date: Thu, 4 Nov 2021 23:33:06 -0700 Subject: [PATCH] Add parameters example RDL file --- examples/parameters/Makefile | 11 + examples/parameters/parameters.rdl | 19 + examples/parameters/srdl2sv_out/paremeters.sv | 500 ++++++++++++++++++ .../srdl2sv_out/srdl2sv_amba3ahblite.sv | 312 +++++++++++ .../srdl2sv_out/srdl2sv_widget_if.sv | 30 ++ 5 files changed, 872 insertions(+) create mode 100644 examples/parameters/Makefile create mode 100644 examples/parameters/parameters.rdl create mode 100644 examples/parameters/srdl2sv_out/paremeters.sv create mode 100644 examples/parameters/srdl2sv_out/srdl2sv_amba3ahblite.sv create mode 100644 examples/parameters/srdl2sv_out/srdl2sv_widget_if.sv diff --git a/examples/parameters/Makefile b/examples/parameters/Makefile new file mode 100644 index 0000000..cd5563d --- /dev/null +++ b/examples/parameters/Makefile @@ -0,0 +1,11 @@ +RTL_TARGETS = $(subst .rdl,.sv,srdl2sv_out/$(shell ls *.rdl)) + +.PHONY: clean + +default: $(RTL_TARGETS) + +srdl2sv_out/%.sv: %.rdl $(shell which srdl2sv) + srdl2sv $< --out-dir $(shell dirname $@) --stdout-logging INFO + +clean: + rm -rf srdl2sv_out diff --git a/examples/parameters/parameters.rdl b/examples/parameters/parameters.rdl new file mode 100644 index 0000000..3e56944 --- /dev/null +++ b/examples/parameters/parameters.rdl @@ -0,0 +1,19 @@ +// This RDL file demonstrates how parameters can be used +// to make generic templates that can easily be re-used +// at different locations in the design. + +signal {activelow; async; field_reset;} rst_async_n; + +reg myReg #(longint unsigned SIZE = 32, + accesstype SW_ACCESS = rw) { + field { + sw = SW_ACCESS; + } data[SIZE-1:0] = 0; +}; + +addrmap paremeters { + myReg reg32; + myReg reg32_arr[8]; + myReg #(.SIZE(16)) reg16; + myReg #(.SIZE(8), .SW_ACCESS(r)) reg8; +}; diff --git a/examples/parameters/srdl2sv_out/paremeters.sv b/examples/parameters/srdl2sv_out/paremeters.sv new file mode 100644 index 0000000..d292e10 --- /dev/null +++ b/examples/parameters/srdl2sv_out/paremeters.sv @@ -0,0 +1,500 @@ +/***************************************************************** + * + * ███████╗██████╗ ██████╗ ██╗ ██████╗ ███████╗██╗ ██╗ + * ██╔════╝██╔══██╗██╔══██╗██║ ╚════██╗██╔════╝██║ ██║ + * ███████╗██████╔╝██║ ██║██║ █████╔╝███████╗██║ ██║ + * ╚════██║██╔══██╗██║ ██║██║ ██╔═══╝ ╚════██║╚██╗ ██╔╝ + * ███████║██║ ██║██████╔╝███████╗███████╗███████║ ╚████╔╝ + * ╚══════╝╚═╝ ╚═╝╚═════╝ ╚══════╝╚══════╝╚══════╝ ╚═══╝ + * + * 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 04 2021 23:31:13 + * - Path : /home/dpotter/srdl2sv/examples/parameters + * - RDL file : ['parameters.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 + * - Unpacked I/Os : True + * - Register Bus Type: amba3ahblite + * - Address width : 32 + * - Byte enables : True + * - Descriptions : {'AddrMap': False, 'RegFile': False, 'Memory': False, 'Register': False, 'Field': False} + * + * ===LICENSE OF PAREMETERS.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 paremeters + +( + // Resets + input rst_async_n, + + // 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 [31:0] reg32__data_in , + input [31:0] reg32_arr__data_in[8], + input [15:0] reg16__data_in , + input [7:0] reg8__data_in , + + // Outputs + output HREADYOUT , + output HRESP , + output [32-1:0] HRDATA , + output [31:0] reg32__data_r , + output [31:0] reg32_arr__data_r[8], + output [15:0] reg16__data_r , + output [7:0] reg8__data_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); + +genvar gv_a; + + +/******************************************************************* +/******************************************************************* +/* REGISTER : reg32 +/* DIMENSION : 0 +/* DEPTHS (per dimension): [] +/******************************************************************* +/*******************************************************************/ + +logic reg32_active ; +logic reg32_sw_wr ; +logic [31:0] reg32_data_mux_in; +logic reg32_rdy_mux_in ; +logic reg32_err_mux_in ; +logic [31:0] reg32__data_q ; + + +// Register-activation for 'reg32' +assign reg32_active = widget_if.addr == 0; +assign reg32_sw_wr = reg32_active && widget_if.w_vld; + +//-----------------FIELD SUMMARY----------------- +// name : data (reg32[31:0]) +// access : hw = rw +// sw = rw (precedence) +// reset : active_low / asynchronous +// flags : ['sw'] +// external : False +// storage type : StorageType.FLOPS +//----------------------------------------------- + +always_ff @(posedge clk or negedge rst_async_n) +if (!rst_async_n) +begin + reg32__data_q <= 32'd0; +end +else +begin + if (reg32_sw_wr) + begin + if (widget_if.byte_en[0]) + reg32__data_q[7:0] <= widget_if.w_data[7:0]; + if (widget_if.byte_en[1]) + reg32__data_q[15:8] <= widget_if.w_data[15:8]; + if (widget_if.byte_en[2]) + reg32__data_q[23:16] <= widget_if.w_data[23:16]; + if (widget_if.byte_en[3]) + reg32__data_q[31:24] <= widget_if.w_data[31:24]; + end + else + // we or wel property not set + reg32__data_q <= reg32__data_in; +end // of reg32__data's always_ff + +// Connect register to hardware output port +assign reg32__data_r = reg32__data_q; + + + + +/************************************** + * Assign all fields to signal to Mux * + **************************************/ +// Assign all fields. Fields that are not readable are tied to 0. +assign reg32_data_mux_in = {reg32__data_q}; + +// Internal registers are ready immediately +assign reg32_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 reg32_err_mux_in = !((widget_if.r_vld && (|widget_if.byte_en[3:0])) || (widget_if.w_vld && (|widget_if.byte_en[3:0]))); + +/******************************************************************* +/******************************************************************* +/* REGISTER : reg32_arr +/* DIMENSION : 1 +/* DEPTHS (per dimension): [8] +/******************************************************************* +/*******************************************************************/ + +logic reg32_arr_active [8]; +logic reg32_arr_sw_wr [8]; +logic [31:0] reg32_arr_data_mux_in[8]; +logic reg32_arr_rdy_mux_in [8]; +logic reg32_arr_err_mux_in [8]; +logic [31:0] reg32_arr__data_q [8]; + +generate +for (gv_a = 0; gv_a < 8; gv_a++) +begin + + // Register-activation for 'reg32_arr' + assign reg32_arr_active[gv_a] = widget_if.addr == 4+(gv_a*4); + assign reg32_arr_sw_wr[gv_a] = reg32_arr_active[gv_a] && widget_if.w_vld; + + //-----------------FIELD SUMMARY----------------- + // name : data (reg32_arr[31:0]) + // access : hw = rw + // sw = rw (precedence) + // reset : active_low / asynchronous + // flags : ['sw'] + // external : False + // storage type : StorageType.FLOPS + //----------------------------------------------- + + always_ff @(posedge clk or negedge rst_async_n) + if (!rst_async_n) + begin + reg32_arr__data_q[gv_a] <= 32'd0; + end + else + begin + if (reg32_arr_sw_wr[gv_a]) + begin + if (widget_if.byte_en[0]) + reg32_arr__data_q[gv_a][7:0] <= widget_if.w_data[7:0]; + if (widget_if.byte_en[1]) + reg32_arr__data_q[gv_a][15:8] <= widget_if.w_data[15:8]; + if (widget_if.byte_en[2]) + reg32_arr__data_q[gv_a][23:16] <= widget_if.w_data[23:16]; + if (widget_if.byte_en[3]) + reg32_arr__data_q[gv_a][31:24] <= widget_if.w_data[31:24]; + end + else + // we or wel property not set + reg32_arr__data_q[gv_a] <= reg32_arr__data_in[gv_a]; + end // of reg32_arr__data's always_ff + + // Connect register to hardware output port + assign reg32_arr__data_r[gv_a] = reg32_arr__data_q[gv_a]; + + + + + /************************************** + * Assign all fields to signal to Mux * + **************************************/ + // Assign all fields. Fields that are not readable are tied to 0. + assign reg32_arr_data_mux_in[gv_a] = {reg32_arr__data_q[gv_a]}; + + // Internal registers are ready immediately + assign reg32_arr_rdy_mux_in[gv_a] = 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 reg32_arr_err_mux_in[gv_a] = !((widget_if.r_vld && (|widget_if.byte_en[3:0])) || (widget_if.w_vld && (|widget_if.byte_en[3:0]))); +end // of for loop with iterator gv_a + +endgenerate + + +/******************************************************************* +/******************************************************************* +/* REGISTER : reg16 +/* DIMENSION : 0 +/* DEPTHS (per dimension): [] +/******************************************************************* +/*******************************************************************/ + +logic reg16_active ; +logic reg16_sw_wr ; +logic [15:0] reg16_data_mux_in; +logic reg16_rdy_mux_in ; +logic reg16_err_mux_in ; +logic [15:0] reg16__data_q ; + + +// Register-activation for 'reg16' +assign reg16_active = widget_if.addr == 36; +assign reg16_sw_wr = reg16_active && widget_if.w_vld; + +//-----------------FIELD SUMMARY----------------- +// name : data (reg16[15:0]) +// access : hw = rw +// sw = rw (precedence) +// reset : active_low / asynchronous +// flags : ['sw'] +// external : False +// storage type : StorageType.FLOPS +//----------------------------------------------- + +always_ff @(posedge clk or negedge rst_async_n) +if (!rst_async_n) +begin + reg16__data_q <= 16'd0; +end +else +begin + if (reg16_sw_wr) + begin + if (widget_if.byte_en[0]) + reg16__data_q[7:0] <= widget_if.w_data[7:0]; + if (widget_if.byte_en[1]) + reg16__data_q[15:8] <= widget_if.w_data[15:8]; + end + else + // we or wel property not set + reg16__data_q <= reg16__data_in; +end // of reg16__data's always_ff + +// Connect register to hardware output port +assign reg16__data_r = reg16__data_q; + + + + +/************************************** + * Assign all fields to signal to Mux * + **************************************/ +// Assign all fields. Fields that are not readable are tied to 0. +assign reg16_data_mux_in = {reg16__data_q}; + +// Internal registers are ready immediately +assign reg16_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 reg16_err_mux_in = !((widget_if.r_vld && (|widget_if.byte_en[1:0])) || (widget_if.w_vld && (|widget_if.byte_en[1:0]))); + +/******************************************************************* +/******************************************************************* +/* REGISTER : reg8 +/* DIMENSION : 0 +/* DEPTHS (per dimension): [] +/******************************************************************* +/*******************************************************************/ + +logic reg8_active ; +logic [7:0] reg8_data_mux_in; +logic reg8_rdy_mux_in ; +logic reg8_err_mux_in ; +logic [7:0] reg8__data_q ; + + +// Register-activation for 'reg8' +assign reg8_active = widget_if.addr == 38; + +//-----------------FIELD SUMMARY----------------- +// name : data (reg8[7:0]) +// access : hw = rw +// sw = r (precedence) +// reset : active_low / asynchronous +// flags : ['sw'] +// external : False +// storage type : StorageType.FLOPS +//----------------------------------------------- + +always_ff @(posedge clk or negedge rst_async_n) +if (!rst_async_n) +begin + reg8__data_q <= 8'd0; +end +else +begin + // we or wel property not set + reg8__data_q <= reg8__data_in; +end // of reg8__data's always_ff + +// Connect register to hardware output port +assign reg8__data_r = reg8__data_q; + + + + +/************************************** + * Assign all fields to signal to Mux * + **************************************/ +// Assign all fields. Fields that are not readable are tied to 0. +assign reg8_data_mux_in = {reg8__data_q}; + +// Internal registers are ready immediately +assign reg8_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 reg8_err_mux_in = !((widget_if.r_vld && (widget_if.byte_en[0])) || (widget_if.w_vld && (1'b0))); + +// Read multiplexer +always_comb +begin + unique case (1'b1) + reg32_active: + begin + widget_if.r_data = reg32_data_mux_in; + widget_if.err = reg32_err_mux_in; + widget_if.rdy = reg32_rdy_mux_in; + end + reg32_arr_active[0]: + begin + widget_if.r_data = reg32_arr_data_mux_in[0]; + widget_if.err = reg32_arr_err_mux_in[0]; + widget_if.rdy = reg32_arr_rdy_mux_in[0]; + end + reg32_arr_active[1]: + begin + widget_if.r_data = reg32_arr_data_mux_in[1]; + widget_if.err = reg32_arr_err_mux_in[1]; + widget_if.rdy = reg32_arr_rdy_mux_in[1]; + end + reg32_arr_active[2]: + begin + widget_if.r_data = reg32_arr_data_mux_in[2]; + widget_if.err = reg32_arr_err_mux_in[2]; + widget_if.rdy = reg32_arr_rdy_mux_in[2]; + end + reg32_arr_active[3]: + begin + widget_if.r_data = reg32_arr_data_mux_in[3]; + widget_if.err = reg32_arr_err_mux_in[3]; + widget_if.rdy = reg32_arr_rdy_mux_in[3]; + end + reg32_arr_active[4]: + begin + widget_if.r_data = reg32_arr_data_mux_in[4]; + widget_if.err = reg32_arr_err_mux_in[4]; + widget_if.rdy = reg32_arr_rdy_mux_in[4]; + end + reg32_arr_active[5]: + begin + widget_if.r_data = reg32_arr_data_mux_in[5]; + widget_if.err = reg32_arr_err_mux_in[5]; + widget_if.rdy = reg32_arr_rdy_mux_in[5]; + end + reg32_arr_active[6]: + begin + widget_if.r_data = reg32_arr_data_mux_in[6]; + widget_if.err = reg32_arr_err_mux_in[6]; + widget_if.rdy = reg32_arr_rdy_mux_in[6]; + end + reg32_arr_active[7]: + begin + widget_if.r_data = reg32_arr_data_mux_in[7]; + widget_if.err = reg32_arr_err_mux_in[7]; + widget_if.rdy = reg32_arr_rdy_mux_in[7]; + end + reg16_active: + begin + widget_if.r_data = reg16_data_mux_in; + widget_if.err = reg16_err_mux_in; + widget_if.rdy = reg16_rdy_mux_in; + end + reg8_active: + begin + widget_if.r_data = reg8_data_mux_in; + widget_if.err = reg8_err_mux_in; + widget_if.rdy = reg8_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/parameters/srdl2sv_out/srdl2sv_amba3ahblite.sv b/examples/parameters/srdl2sv_out/srdl2sv_amba3ahblite.sv new file mode 100644 index 0000000..d1598f9 --- /dev/null +++ b/examples/parameters/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/parameters/srdl2sv_out/srdl2sv_widget_if.sv b/examples/parameters/srdl2sv_out/srdl2sv_widget_if.sv new file mode 100644 index 0000000..b85afc4 --- /dev/null +++ b/examples/parameters/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 +