Skip to content
Snippets Groups Projects
Commit 2435cd9d authored by David Mapstone's avatar David Mapstone
Browse files

SOC1-159: Started modifying vgen_regs script to generate registers with APB interface

parent 8c11cd64
Branches feat_apb_regs
No related tags found
No related merge requests found
#-----------------------------------------------------------------------------
# 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
#-----------------------------------------------------------------------------
# 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
//-----------------------------------------------------------------------------
// 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
//-----------------------------------------------------------------------------
// 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
...@@ -11,6 +11,7 @@ import shutil; ...@@ -11,6 +11,7 @@ import shutil;
import os; import os;
import sys; import sys;
import argparse; import argparse;
from enum import Enum
from CHIPKIT.tools.vgen.bin.vgen import *; from CHIPKIT.tools.vgen.bin.vgen import *;
...@@ -26,6 +27,43 @@ regs_keys = [ ...@@ -26,6 +27,43 @@ regs_keys = [
'rval' '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 # TODO
# Update command line arg parsing - setup the same as pads version. # Update command line arg parsing - setup the same as pads version.
# Might make sense to put the command line arg parsing into vgen.py? # 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=''): ...@@ -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 """ """ Generate a CSR module from a template file and a signal list """
# Check the required keys are present (others will be ignored) # 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): ...@@ -128,13 +166,27 @@ def gen_regs_module(module_name,module_file,template_file,regs):
# Module name # Module name
fo.write(read_to_tag(fi_template,"VGEN: 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 # Port list inputs
fo.write(read_to_tag(fi_template,"VGEN: INPUTS TO REGS")) fo.write(read_to_tag(fi_template,"VGEN: INPUTS TO REGS"))
for n, row in enumerate(regs): for n, row in enumerate(regs):
if (row['access'] == "r"): 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" l += "/* idx #"+str(n)+": "+row['desc']+" */" + "\n"
fo.write(l) fo.write(l)
...@@ -148,9 +200,11 @@ def gen_regs_module(module_name,module_file,template_file,regs): ...@@ -148,9 +200,11 @@ def gen_regs_module(module_name,module_file,template_file,regs):
first = False first = False
else: else:
l += ",\n" 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']+" */" l += " /* idx #"+str(n)+": "+row['desc']+" */"
fo.write(l) fo.write(l)
#
# Register write # Register write
fo.write(read_to_tag(fi_template,"VGEN: REG 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): ...@@ -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 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 += " <= " + row['nbits'] + "\'h" + row['rval'].rsplit("0x")[1] + ";\n"
l += " end else begin\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 += " if(write_en & (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 += row['name'] + "_reg" + reg_dims(row) + " <= wdata" + reg_dims(row)
l += ";\n end\nend\n" l += ";\n end\nend\n"
l += "assign "+row['name']+reg_dims(row)+" = "+row['name']+"_reg"+reg_dims(row)+";\n\n" l += "assign "+row['name']+reg_dims(row)+" = "+row['name']+"_reg"+reg_dims(row)+";\n\n"
fo.write(l) fo.write(l)
...@@ -175,7 +229,7 @@ def gen_regs_module(module_name,module_file,template_file,regs): ...@@ -175,7 +229,7 @@ def gen_regs_module(module_name,module_file,template_file,regs):
# Register read # Register read
fo.write(read_to_tag(fi_template,"VGEN: REG READ")) fo.write(read_to_tag(fi_template,"VGEN: REG READ"))
for n, row in enumerate(regs): 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 + "rdata_o"+reg_dims(row)+" = "+row['name']+reg_dims(row)+";\t"
l = l +" // idx #"+str(n)+"\n" l = l +" // idx #"+str(n)+"\n"
fo.write(l) fo.write(l)
...@@ -537,15 +591,15 @@ def main(): ...@@ -537,15 +591,15 @@ def main():
if (args.generate): if (args.generate):
# Module name is derived from the CSV filename # Module name is derived from the CSV filename
module = args.generate.split('.')[0] module = os.path.basename(args.generate.split('.')[0])
print(module) print("module is "+module)
outdir = args.output outdir = args.output
# Read in the register list # Read in the register list
regs = read_csv(args.generate,debug=True) regs = read_csv(args.generate,debug=True)
# generate verilog # 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_instance(module,outdir+'/'+module+'.inst.sv',regs,clock=args.clock,reset=args.reset)
gen_regs_docs(module,outdir+'/'+module+'.md',regs) gen_regs_docs(module,outdir+'/'+module+'.md',regs)
gen_regs_python(module,outdir+'/'+module+'.py',regs) gen_regs_python(module,outdir+'/'+module+'.py',regs)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment