diff --git a/flow/vgen_apb_regs b/flow/vgen_apb_regs new file mode 100755 index 0000000000000000000000000000000000000000..85dfdd410eca09297c919b1fbcac0267cd46cac3 --- /dev/null +++ b/flow/vgen_apb_regs @@ -0,0 +1,16 @@ +#----------------------------------------------------------------------------- +# SoC Labs Register Generation Script +# A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license. +# +# Contributors +# +# David Mapstone (d.a.mapstone@soton.ac.uk) +# +# Copyright 2022, SoC Labs (www.soclabs.org) +#----------------------------------------------------------------------------- + +#!/usr/bin/env bash + +mkdir -p $1 +# TODO: Choose a template for verilog +python3 $CHIPKIT_DIR/tools/vgen/examples/registers/vgen_regs.py --generate $1.csv --clock pclk --reset presetn --output $1 \ No newline at end of file diff --git a/flow/vgen_regs b/flow/vgen_regs new file mode 100755 index 0000000000000000000000000000000000000000..406e0db4b09f6bd613e205db899dab8d6d08ec92 --- /dev/null +++ b/flow/vgen_regs @@ -0,0 +1,15 @@ +#----------------------------------------------------------------------------- +# SoC Labs Register Generation Script +# A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license. +# +# Contributors +# +# David Mapstone (d.a.mapstone@soton.ac.uk) +# +# Copyright 2022, SoC Labs (www.soclabs.org) +#----------------------------------------------------------------------------- + +#!/usr/bin/env bash + +mkdir -p $1 +python3 $CHIPKIT_DIR/tools/vgen/examples/registers/vgen_regs.py --generate $1.csv --clock pclk --reset presetn --output $1 \ No newline at end of file diff --git a/ip/apb/apb3_target_interface.sv b/ip/apb/apb3_target_interface.sv new file mode 100644 index 0000000000000000000000000000000000000000..b5630fe6e26b98a272961d5232d70184c1bd7fcf --- /dev/null +++ b/ip/apb/apb3_target_interface.sv @@ -0,0 +1,104 @@ +//----------------------------------------------------------------------------- +// The confidential and proprietary information contained in this file may +// only be used by a person authorised under and to the extent permitted +// by a subsisting licensing agreement from Arm Limited or its affiliates. +// +// (C) COPYRIGHT 2010-2011 Arm Limited or its affiliates. +// ALL RIGHTS RESERVED +// +// This entire notice must be reproduced on all copies of this file +// and copies of this file may only be made by a person if such person is +// permitted to do so under the terms of a subsisting license agreement +// from Arm Limited or its affiliates. +// +// SVN Information +// +// Checked In : $Date: 2017-10-10 15:55:38 +0100 (Tue, 10 Oct 2017) $ +// +// Revision : $Revision: 371321 $ +// +// Release Information : Cortex-M System Design Kit-r1p1-00rel0 +// +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// Abstract : AMBA APB3 example Target interface module. +// Convert APB BUS protocol to simple register read write protocol +//----------------------------------------------------------------------------- +module apb3_target_interface #( + // parameter for address width + parameter ADDRWIDTH = 12) + ( + // IO declaration + + input wire pclk, // pclk + input wire presetn, // reset + + // apb interface inputs + input wire psel, + input wire [ADDRWIDTH-1:0] paddr, + input wire penable, + input wire pwrite, + input wire [31:0] pwdata, + + // apb interface outputs + output wire [31:0] prdata, + output wire pready, + output wire pslverr, + + // Data register read/write interface + output wire [ADDRWIDTH-1:0] addr, + output wire read_en, + output wire write_en, + output wire [31:0] wdata, + input wire [31:0] rdata + ); + + //------------------------------------------------------------------------------ + // module logic start + //------------------------------------------------------------------------------ + +// APB interface +assign pready = 1'b1; //always ready. Can be customized to support waitstate if required. +assign pslverr = 1'b0; //always OKAY. Can be customized to support error response if required. + + +// register read and write signal +assign addr = paddr; +assign read_en = psel & (~pwrite); // assert for whole apb read transfer +assign write_en = psel & (~penable) & pwrite; // assert for 1st cycle of write transfer + // It is also possible to change the design to perform the write in the 2nd + // APB cycle. E.g. + // assign write_en = psel & penable & pwrite; + // However, if the design generate waitstate, this expression will result + // in write_en being asserted for multiple cycles. +assign wdata = pwdata; +assign prdata = rdata; + + +`ifdef ARM_APB_ASSERT_ON + + `include "std_ovl_defines.h" + // ------------------------------------------------------------ + // Assertions + // ------------------------------------------------------------ + + // Check error response should not be generated if not selected + assert_never + #(`OVL_ERROR, + `OVL_ASSERT, + "Error! Should not generate error response if not selected") + u_ovl_apb3_eg_slave_response_illegal + (.clk (pclk), + .reset_n (presetn), + .test_expr (pslverr & pready & (~psel)) + ); + +`endif + + //------------------------------------------------------------------------------ + // module logic end + //------------------------------------------------------------------------------ + +endmodule + + diff --git a/tools/vgen/examples/registers/regs_apb.tmpl.sv b/tools/vgen/examples/registers/regs_apb.tmpl.sv new file mode 100644 index 0000000000000000000000000000000000000000..22fbe3828b1f7ab8cf9d1daf2f7ff2ccaba1dd1d --- /dev/null +++ b/tools/vgen/examples/registers/regs_apb.tmpl.sv @@ -0,0 +1,103 @@ +//----------------------------------------------------------------------------- +// SoC Labs APB register Template +// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license. +// +// Contributors +// +// David Mapstone (d.a.mapstone@soton.ac.uk) +// +// Copyright 2023, SoC Labs (www.soclabs.org) +//----------------------------------------------------------------------------- +// VGEN: HEADER +// VGEN: MODULE NAME +( +// clocks and resets + input logic clk, + input logic rstn, + +// APB inteface + input logic psel, + input logic [ADDRWIDTH:0] paddr, + input logic penable, + input logic pwrite, + input logic [31:0] pwdata, + + output logic [31:0] prdata, + output logic pready, + output logic pslverr, + +// VGEN: INPUTS TO REGS + + +// VGEN: OUTPUTS FROM REGS + + +); + +//------------------------------------------------------------------------------ +// APB Interface +//------------------------------------------------------------------------------ + +logic [ADDRWIDTH-1:0] addr; +logic read_en; +logic write_en; +logic [31:0] wdata; +logic [31:0] rdata; + +// APB interface +assign pready = 1'b1; //always ready. Can be customized to support waitstate if required. +assign pslverr = 1'b0; //always OKAY. Can be customized to support error response if required. + + +// register read and write signal +assign addr = paddr; +assign read_en = psel & (~pwrite); // assert for whole apb read transfer +assign write_en = psel & (~penable) & pwrite; // assert for 1st cycle of write transfer + // It is also possible to change the design to perform the write in the 2nd + // APB cycle. E.g. + // assign write_en = psel & penable & pwrite; + // However, if the design generate waitstate, this expression will result + // in write_en being asserted for multiple cycles. +assign wdata = pwdata; +assign prdata = rdata; + +//------------------------------------------------------------------------------ +// Regsiter write +//------------------------------------------------------------------------------ + +// VGEN: REG WRITE + + +//------------------------------------------------------------------------------ +// Regsiter read +//------------------------------------------------------------------------------ + + +logic [31:0] rdata_o; + +always @* +begin + if (read_en) + begin + rdata_o[31:0] = 32'h00000000; + + // VGEN: REG READ + + end + else + begin + rdata_o[31:0] = {32'h00000000}; + end +end + +assign rdata[31:0] = rdata_o[31:0]; + + +//------------------------------------------------------------------------------ +// +//------------------------------------------------------------------------------ + + + + +endmodule diff --git a/tools/vgen/examples/registers/vgen_regs.py b/tools/vgen/examples/registers/vgen_regs.py index 3dbb65aef978c7d0b66b69fc873043b2bf405d26..06fc0b148cf9f7cca4d7dfe581369e819de13cfc 100755 --- a/tools/vgen/examples/registers/vgen_regs.py +++ b/tools/vgen/examples/registers/vgen_regs.py @@ -11,6 +11,7 @@ import shutil; import os; import sys; import argparse; +from enum import Enum from CHIPKIT.tools.vgen.bin.vgen import *; @@ -26,6 +27,43 @@ regs_keys = [ 'rval' ] +class Port_direction(Enum): + INPUT = 1 + OUTPUT = 2 + +class Port(): + def __init__(self,name,width,direction): + self.name = name + self.width = width + self.direction = direction + +class Interface(): + def __init__(self,ports): + self.ports = ports + +ADDRW = 12 + +apb_psel = Port("psel", 1, Port_direction.INPUT) +apb_paddr = Port("paddr", ADDRW, Port_direction.INPUT) +apb_penable = Port("penable", 1, Port_direction.INPUT) +apb_pwrite = Port("pwrite", 1, Port_direction.INPUT) +apb_pwdata = Port("pwdata", 32, Port_direction.INPUT) + +apb_prdata = Port("prdata", 32, Port_direction.OUTPUT) +apb_pready = Port("pready", 1, Port_direction.OUTPUT) +apb_pslverr = Port("pslverr", 1, Port_direction.OUTPUT) + +apb_inf = Interface([ + apb_psel, + apb_paddr, + apb_penable, + apb_pwrite, + apb_pwdata, + apb_prdata, + apb_pready, + apb_pslverr +]) + # TODO # Update command line arg parsing - setup the same as pads version. # Might make sense to put the command line arg parsing into vgen.py? @@ -88,7 +126,7 @@ def update_regs_csv_from_verilog(csv_file,verilog_file,match_prefix=''): ############################################################################### -def gen_regs_module(module_name,module_file,template_file,regs): +def gen_regs_module(module_name,module_file,template_file,regs,ext_inf=apb_inf): """ Generate a CSR module from a template file and a signal list """ # Check the required keys are present (others will be ignored) @@ -128,13 +166,27 @@ def gen_regs_module(module_name,module_file,template_file,regs): # Module name fo.write(read_to_tag(fi_template,"VGEN: MODULE NAME")) - fo.write(module_name+"\n") + fo.write("module "+module_name+" ") + # # Interface + # fo.write(read_to_tag(fi_template,"VGEN: EXTERNAL INTERFACE")) + # for port in ext_inf.ports: + # if port.direction == Port_direction.INPUT: + # fo.write("\tinput logic ") + # elif port.direction == Port_direction.OUTPUT: + # fo.write("\toutput logic ") + + # if port.width > 1: + # fo.write(f"[{port.width-1}:0] ") + + # fo.write(port.name + ",\n") + + # Port list inputs fo.write(read_to_tag(fi_template,"VGEN: INPUTS TO REGS")) for n, row in enumerate(regs): if (row['access'] == "r"): - l = "input logic "+reg_dims(row)+" "+row['name']+",\t" + l = "\tinput logic "+reg_dims(row)+" "+row['name']+",\t" l += "/* idx #"+str(n)+": "+row['desc']+" */" + "\n" fo.write(l) @@ -148,9 +200,11 @@ def gen_regs_module(module_name,module_file,template_file,regs): first = False else: l += ",\n" - l += "output logic " + reg_dims(row) + " " + row['name'] + "\t" + l += "\toutput logic " + reg_dims(row) + " " + row['name'] + "\t" l += " /* idx #"+str(n)+": "+row['desc']+" */" fo.write(l) + + # # Register write fo.write(read_to_tag(fi_template,"VGEN: REG WRITE")) @@ -166,8 +220,8 @@ def gen_regs_module(module_name,module_file,template_file,regs): else: # TODO really should get the correct number of digits for the reset value l += " <= " + row['nbits'] + "\'h" + row['rval'].rsplit("0x")[1] + ";\n" l += " end else begin\n" - l += " if(regbus.write_en & (regbus.addr[9:2]==8'h"+(hex(int(row['idx'])).lstrip("0x") or "0")+")) " - l += row['name'] + "_reg" + reg_dims(row) + " <= regbus.wdata" + reg_dims(row) + l += " if(write_en & (addr[9:2]==8'h"+(hex(int(row['idx'])).lstrip("0x") or "0")+")) " + l += row['name'] + "_reg" + reg_dims(row) + " <= wdata" + reg_dims(row) l += ";\n end\nend\n" l += "assign "+row['name']+reg_dims(row)+" = "+row['name']+"_reg"+reg_dims(row)+";\n\n" fo.write(l) @@ -175,7 +229,7 @@ def gen_regs_module(module_name,module_file,template_file,regs): # Register read fo.write(read_to_tag(fi_template,"VGEN: REG READ")) for n, row in enumerate(regs): - l = " if(regbus.addr[9:2]==8'h"+(hex(int(row['idx'])).lstrip("0x") or "0")+") " + l = " if(addr[9:2]==8'h"+(hex(int(row['idx'])).lstrip("0x") or "0")+") " l += l + "rdata_o"+reg_dims(row)+" = "+row['name']+reg_dims(row)+";\t" l = l +" // idx #"+str(n)+"\n" fo.write(l) @@ -537,15 +591,15 @@ def main(): if (args.generate): # Module name is derived from the CSV filename - module = args.generate.split('.')[0] - print(module) + module = os.path.basename(args.generate.split('.')[0]) + print("module is "+module) outdir = args.output # Read in the register list regs = read_csv(args.generate,debug=True) # generate verilog - gen_regs_module(module,outdir+'/'+module+'.sv',os.path.dirname(__file__)+'/regs_template.sv',regs) + gen_regs_module(module,outdir+'/'+module+'.sv',os.path.dirname(__file__)+'/regs_apb.tmpl.sv',regs) gen_regs_instance(module,outdir+'/'+module+'.inst.sv',regs,clock=args.clock,reset=args.reset) gen_regs_docs(module,outdir+'/'+module+'.md',regs) gen_regs_python(module,outdir+'/'+module+'.py',regs)