mirror of
https://github.com/Silicon1602/srdl2sv.git
synced 2024-11-14 03:03:35 +00:00
Add _very incomplete_ AMBA 3 AHB Lite widget
This is just a start on the first widget. It is still very limited and not yet functional in any way.
This commit is contained in:
parent
145ac70123
commit
5e4a954a0c
@ -130,7 +130,14 @@ class AddrMap(Component):
|
||||
# Remove comma from last port entry
|
||||
output_ports_rtl[-1] = output_ports_rtl[-1].rstrip(',')
|
||||
|
||||
import_package_list = []
|
||||
# Define packages to be included. Always include the
|
||||
# b2w and w2b defines.
|
||||
import_package_list = [
|
||||
AddrMap.templ_dict['import_package']['rtl'].format(
|
||||
name = 'srdl2sv_widget'),
|
||||
'\n'
|
||||
]
|
||||
|
||||
try:
|
||||
for x in self.get_package_names():
|
||||
import_package_list.append(
|
||||
@ -139,10 +146,11 @@ class AddrMap(Component):
|
||||
|
||||
import_package_list.append('\n')
|
||||
|
||||
import_package_list.pop()
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
import_package_list.pop()
|
||||
|
||||
import getpass
|
||||
import socket
|
||||
import time
|
||||
|
@ -69,8 +69,6 @@ module_declaration:
|
||||
<<INDENT>>
|
||||
// Clock & Resets
|
||||
input reg_clk,
|
||||
input bus_clk,
|
||||
input bus_rst_n,
|
||||
{resets}
|
||||
|
||||
// Inputs
|
||||
@ -115,13 +113,13 @@ read_mux:
|
||||
// Read multiplexer
|
||||
always_comb
|
||||
begin
|
||||
case(addr)
|
||||
case(b2r.addr)
|
||||
{list_of_cases}
|
||||
endcase
|
||||
end
|
||||
default_mux_case:
|
||||
rtl: |-
|
||||
default: sw_rd_bus = 0;
|
||||
default: r2b.data = 0;
|
||||
list_of_mux_cases:
|
||||
rtl: |-
|
||||
32'd{}: sw_rd_bus = {};
|
||||
32'd{}: r2b.data = {};
|
||||
|
@ -29,9 +29,9 @@ sw_access_field_swwel:
|
||||
begin
|
||||
sw_access_byte:
|
||||
rtl: |-
|
||||
if (byte_enable[{i}])
|
||||
if (b2r.byte_en[{i}])
|
||||
<<INDENT>>
|
||||
{path}_q{genvars}[{msb_field}:{lsb_field}] <= sw_wr_bus[{msb_bus}:{lsb_bus}];
|
||||
{path}_q{genvars}[{msb_field}:{lsb_field}] <= b2r.data[{msb_bus}:{lsb_bus}];
|
||||
<<UNINDENT>>
|
||||
signals:
|
||||
- name: '{path}_q'
|
||||
@ -114,33 +114,33 @@ end_field_ff:
|
||||
end // of {path}'s always_ff
|
||||
OnWriteType.woset:
|
||||
rtl: |-
|
||||
if (byte_enable[{i}]) // woset property
|
||||
if (b2r.byte_en[{i}]) // woset property
|
||||
begin
|
||||
{path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] | sw_wr_bus[{msb_bus}:{lsb_bus}];
|
||||
{path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] | b2r.data[{msb_bus}:{lsb_bus}];
|
||||
end
|
||||
OnWriteType.woclr:
|
||||
rtl: |-
|
||||
if (byte_enable[{i}]) // woclr property
|
||||
if (b2r.byte_en[{i}]) // woclr property
|
||||
begin
|
||||
{path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] & ~sw_wr_bus[{msb_bus}:{lsb_bus}];
|
||||
{path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] & ~b2r.data[{msb_bus}:{lsb_bus}];
|
||||
end
|
||||
OnWriteType.wot:
|
||||
rtl: |-
|
||||
if (byte_enable[{i}]) // wot property
|
||||
if (b2r.byte_en[{i}]) // wot property
|
||||
begin
|
||||
{path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] ^ sw_wr_bus[{msb_bus}:{lsb_bus}];
|
||||
{path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] ^ b2r.data[{msb_bus}:{lsb_bus}];
|
||||
end
|
||||
OnWriteType.wzs:
|
||||
rtl: |-
|
||||
if (byte_enable[{i}]) // wzs property
|
||||
if (b2r.byte_en[{i}]) // wzs property
|
||||
begin
|
||||
{path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] & sw_wr_bus[{msb_bus}:{lsb_bus}];
|
||||
{path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] & b2r.data[{msb_bus}:{lsb_bus}];
|
||||
end
|
||||
OnWriteType.wzt:
|
||||
rtl: |-
|
||||
if (byte_enable[{i}]) // wzt property
|
||||
if (b2r.byte_en[{i}]) // wzt property
|
||||
begin
|
||||
{path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] ~^ sw_wr_bus[{msb_bus}:{lsb_bus}];
|
||||
{path}_q{genvars}[{msb_field}:{lsb_field}] <= {path}_q{genvars}[{msb_field}:{lsb_field}] ~^ b2r.data[{msb_bus}:{lsb_bus}];
|
||||
end
|
||||
OnWriteType.wclr:
|
||||
rtl: |-
|
||||
@ -210,7 +210,7 @@ swacc_assign:
|
||||
rtl: |-
|
||||
|
||||
// Combinational block to generate swacc-output signals
|
||||
assign {path}_swacc{genvars} = ({path_wo_field}__any_alias_sw_wr{genvars} || {path_wo_field}__any_alias_sw_rd{genvars}) && |byte_enable[{msbyte}:{lsbyte}];
|
||||
assign {path}_swacc{genvars} = ({path_wo_field}__any_alias_sw_wr{genvars} || {path_wo_field}__any_alias_sw_rd{genvars}) && |b2r.byte_en[{msbyte}:{lsbyte}];
|
||||
output_ports:
|
||||
- name: '{path}_swacc'
|
||||
signal_type: 'logic'
|
||||
@ -228,7 +228,7 @@ swmod_always_comb:
|
||||
signal_type: 'logic'
|
||||
swmod_assign:
|
||||
rtl: |-
|
||||
{path}_swmod{genvars} |= {path_wo_field}__any_alias_sw_{rd_wr}{genvars} && |byte_enable[{msbyte}:{lsbyte}];
|
||||
{path}_swmod{genvars} |= {path_wo_field}__any_alias_sw_{rd_wr}{genvars} && |b2r.byte_en[{msbyte}:{lsbyte}];
|
||||
output_ports:
|
||||
- name: '{path}_swmod'
|
||||
signal_type: 'logic'
|
||||
|
@ -3,9 +3,9 @@ rw_wire_assign_1_dim:
|
||||
rtl: |
|
||||
|
||||
// Register-activation for '{path}' {alias}
|
||||
assign {path}_accss = addr == {addr};
|
||||
assign {path}_sw_wr = {path}_accss && r_vld;
|
||||
assign {path}_sw_rd = {path}_accss && w_vld;
|
||||
assign {path}_accss = b2r.addr == {addr};
|
||||
assign {path}_sw_wr = {path}_accss && b2r.r_vld;
|
||||
assign {path}_sw_rd = {path}_accss && b2r.w_vld;
|
||||
signals:
|
||||
- name: '{path}_sw_wr'
|
||||
signal_type: 'logic'
|
||||
@ -17,9 +17,9 @@ rw_wire_assign_multi_dim:
|
||||
rtl: |-
|
||||
|
||||
// Register-activation for '{path}' {alias}
|
||||
assign {path}_accss{genvars} = addr == {addr}+({genvars_sum});
|
||||
assign {path}_sw_wr{genvars} = {path}_accss{genvars} && r_vld;
|
||||
assign {path}_sw_rd{genvars} = {path}_accss{genvars} && w_vld;
|
||||
assign {path}_accss{genvars} = b2r.addr == {addr}+({genvars_sum});
|
||||
assign {path}_sw_wr{genvars} = {path}_accss{genvars} && b2r.r_vld;
|
||||
assign {path}_sw_rd{genvars} = {path}_accss{genvars} && b2r.w_vld;
|
||||
signals:
|
||||
- name: '{path}_sw_wr'
|
||||
signal_type: 'logic'
|
||||
|
@ -1,35 +1,174 @@
|
||||
/*
|
||||
* Copyright 2021 Dennis Potter <dennis@dennispotter.eu>
|
||||
*
|
||||
* 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 amba3ahblite_widget
|
||||
import srdl2sv_widget_pkg::*;
|
||||
#(
|
||||
parameter FLOP_IN = 0, // Set to '1' to flop input from the AHB bus. This is meant
|
||||
// to help meet timing. Don't use this to synchronize the input.
|
||||
parameter SYNC_IO = 0 // Set to '1' to in case HCLK and bus_clk are asynchronous
|
||||
// By default, mainly for it to directly work in simulations,
|
||||
// it will double-flops based on always_ff-blocks. To replace
|
||||
// this module with a proper MTBF-optimized double flop cell,
|
||||
// the contents of the synchronizer module `srdl2sv_sync.sv`
|
||||
// shall be updated
|
||||
)
|
||||
(
|
||||
// Register clock
|
||||
input bus_clk,
|
||||
input bus_rst_n,
|
||||
input reg_clk,
|
||||
|
||||
// Outputs to internal logic
|
||||
output [31:0] addr,
|
||||
output w_vld,
|
||||
output r_vld,
|
||||
output [ 3:0] byte_enable,
|
||||
output [31:0] sw_wr_bus,
|
||||
output b2r_t b2r,
|
||||
|
||||
// Inputs from internal logic
|
||||
input [31:0] sw_rd_bus,
|
||||
input r2b_t r2b,
|
||||
|
||||
// Bus protocol
|
||||
input HRESETn,
|
||||
input HCLK,
|
||||
input [31:0] HADDR,
|
||||
input HWRITE,
|
||||
input [ 2:0] HSIZE,
|
||||
input [ 2:0] HBURST,
|
||||
input [ 3:0] HPROT,
|
||||
input [ 1:0] HTRANS,
|
||||
input HMASTLOCK,
|
||||
input HREADY,
|
||||
input HRESETn,
|
||||
input HCLK,
|
||||
input HSEL,
|
||||
input [31:0] HADDR,
|
||||
input HWRITE,
|
||||
input [ 2:0] HSIZE,
|
||||
input [ 2:0] HBURST,
|
||||
input [ 3:0] HPROT,
|
||||
input [ 1:0] HTRANS,
|
||||
input [31:0] HWDATA,
|
||||
input HREADY,
|
||||
|
||||
output HREADYOUT,
|
||||
output HRESP,
|
||||
output [31:0] HRDATA
|
||||
output logic HREADYOUT,
|
||||
output logic HRESP,
|
||||
output logic [31:0] HRDATA
|
||||
);
|
||||
|
||||
// TODO: Add synchronizer logic
|
||||
|
||||
/***
|
||||
* Translate HWRITE & HSEL into a write/read operation for the register logic
|
||||
***/
|
||||
logic r_vld_next;
|
||||
logic w_vld_next;
|
||||
|
||||
always_comb
|
||||
begin
|
||||
w_vld_next = 1'b0;
|
||||
r_vld_next = 1'b0;
|
||||
|
||||
if (HWRITE)
|
||||
w_vld_next = HSEL;
|
||||
else
|
||||
r_vld_next = HSEL;
|
||||
end
|
||||
|
||||
/***
|
||||
* Determine the number of active bytes
|
||||
***/
|
||||
logic [3:0] b2r_byte_en_next;
|
||||
|
||||
always_comb
|
||||
begin
|
||||
case (HTRANS)
|
||||
3'b000 : b2r_byte_en_next = 4'b0001;
|
||||
3'b001 : b2r_byte_en_next = 4'b0011;
|
||||
3'b010 : b2r_byte_en_next = 4'b1111;
|
||||
// TODO: Implement larger sizes
|
||||
default: b2r_byte_en_next = 4'b1111;
|
||||
endcase
|
||||
end
|
||||
|
||||
/***
|
||||
* Flop or sync input if required
|
||||
***/
|
||||
generate
|
||||
if (FLOP_IN)
|
||||
begin
|
||||
always_ff @(posedge HCLK or negedge HRESETn)
|
||||
if (!HRESETn)
|
||||
begin
|
||||
b2r.r_vld <= 1'b0;
|
||||
b2r.w_vld <= 1'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
b2r.r_vld <= r_vld_next;
|
||||
b2r.w_vld <= w_vld_next;
|
||||
end
|
||||
|
||||
always_ff @(posedge HCLK)
|
||||
if (HWRITE)
|
||||
begin
|
||||
b2r.data <= HWDATA;
|
||||
b2r.byte_en <= b2r_byte_en_next;
|
||||
end
|
||||
end
|
||||
else
|
||||
begin
|
||||
assign b2r.r_vld = r_vld_next;
|
||||
assign b2r.w_vld = w_vld_next;
|
||||
assign b2r.data = HWDATA;
|
||||
end
|
||||
endgenerate
|
||||
|
||||
/***
|
||||
* Keep track of an ungoing transaction
|
||||
***/
|
||||
logic reg_busy_q;
|
||||
|
||||
always_ff @(posedge HCLK or negedge HRESETn)
|
||||
if (!HRESETn)
|
||||
reg_busy_q <= 1'b0;
|
||||
else if ((b2r.r_vld || b2r.w_vld) && !r2b.rdy)
|
||||
reg_busy_q <= 1'b1;
|
||||
else if (r2b.rdy)
|
||||
reg_busy_q <= 1'b0;
|
||||
|
||||
assign HREADYOUT = !reg_busy_q;
|
||||
|
||||
/***
|
||||
* Return to AHB bus once the register block is ready
|
||||
***/
|
||||
// Return actual data
|
||||
logic ongoing_read_q;
|
||||
|
||||
always_ff @(posedge HCLK or negedge HRESETn)
|
||||
if (!HRESETn)
|
||||
ongoing_read_q <= 1'b0;
|
||||
else if (b2r.r_vld && !r2b.rdy)
|
||||
ongoing_read_q <= 1'b1;
|
||||
else if (r2b.rdy)
|
||||
ongoing_read_q <= 1'b0;
|
||||
|
||||
always_ff @(posedge HCLK)
|
||||
if ((b2r.r_vld || ongoing_read_q) && r2b.rdy)
|
||||
HRDATA <= r2b.data;
|
||||
|
||||
// Did an error occur while reading?
|
||||
always_ff @(posedge HCLK or negedge HRESETn)
|
||||
if (!HRESETn)
|
||||
HRESP <= 1'b0;
|
||||
else
|
||||
HRESP <= r2b.err;
|
||||
|
||||
endmodule
|
||||
|
@ -1,24 +1,30 @@
|
||||
# This file only contains the instantiation of the module
|
||||
module_instantiation:
|
||||
rtl: |-
|
||||
/****************************
|
||||
/*******************************************************************
|
||||
* AMBA 3 AHB Lite Widget
|
||||
****************************/
|
||||
* ======================
|
||||
* Naming conventions
|
||||
* - r2b.* -> Signals from registers to bus
|
||||
* - b2r.* -> Signals from bus to registers
|
||||
* - H* -> Signals as defined in AMBA3 AHB Lite
|
||||
* specification
|
||||
* - bus_clk -> Clock that that drives signals on bus
|
||||
* - reg_clk -> Clock that drives register flops
|
||||
* - bus_rst_n -> Asynchronous reset that resets only the bus (but
|
||||
* (not the registers). The deassertion of this
|
||||
* reset shall be synchronized to bus_clk
|
||||
*******************************************************************/
|
||||
amba3ahblite_widget
|
||||
amba3ahblite_widget_inst
|
||||
(// Clocks & Resets
|
||||
.bus_clk,
|
||||
.bus_rst_n,
|
||||
(// Register clock
|
||||
.reg_clk,
|
||||
|
||||
// Outputs to internal logic
|
||||
.addr,
|
||||
.w_vld,
|
||||
.r_vld,
|
||||
.byte_enable,
|
||||
.sw_wr_bus,
|
||||
.b2r,
|
||||
|
||||
// Inputs from internal logic
|
||||
.sw_rd_bus,
|
||||
.r2b,
|
||||
|
||||
// Bus protocol
|
||||
.HRESETn,
|
||||
@ -29,25 +35,18 @@ module_instantiation:
|
||||
.HBURST,
|
||||
.HPROT,
|
||||
.HTRANS,
|
||||
.HMASTLOCK,
|
||||
.HWDATA,
|
||||
.HREADY,
|
||||
.HSEL,
|
||||
|
||||
.HREADYOUT,
|
||||
.HRESP,
|
||||
.HRDATA);
|
||||
signals:
|
||||
- name: 'addr'
|
||||
signal_type: 'logic [31:0]'
|
||||
- name: 'w_vld'
|
||||
signal_type: 'logic'
|
||||
- name: 'r_vld'
|
||||
signal_type: 'logic'
|
||||
- name: 'byte_enable'
|
||||
signal_type: 'logic [ 3:0]'
|
||||
- name: 'sw_wr_bus'
|
||||
signal_type: 'logic [31:0]'
|
||||
- name: 'sw_rd_bus'
|
||||
signal_type: 'logic [31:0]'
|
||||
- name: 'b2r'
|
||||
signal_type: 'b2r_t'
|
||||
- name: 'r2b'
|
||||
signal_type: 'r2b_t'
|
||||
input_ports:
|
||||
- name: 'HRESETn'
|
||||
signal_type: ''
|
||||
@ -65,10 +64,12 @@ module_instantiation:
|
||||
signal_type: '[3:0]'
|
||||
- name: 'HTRANS'
|
||||
signal_type: '[1:0]'
|
||||
- name: 'HMASTLOCK'
|
||||
signal_type: ''
|
||||
- name: 'HWDATA'
|
||||
signal_type: '[31:0]'
|
||||
- name: 'HREADY'
|
||||
signal_type: ''
|
||||
- name: 'HSEL'
|
||||
signal_type: ''
|
||||
output_ports:
|
||||
- name: 'HREADYOUT'
|
||||
signal_type: ''
|
||||
|
17
srdl2sv/components/widgets/srdl2sv_widget_pkg.sv
Normal file
17
srdl2sv/components/widgets/srdl2sv_widget_pkg.sv
Normal file
@ -0,0 +1,17 @@
|
||||
package srdl2sv_widget_pkg;
|
||||
|
||||
typedef struct {
|
||||
logic [31:0] addr;
|
||||
logic [31:0] data;
|
||||
logic w_vld;
|
||||
logic r_vld;
|
||||
logic [ 3:0] byte_en;
|
||||
} b2r_t;
|
||||
|
||||
typedef struct {
|
||||
logic [31:0] data;
|
||||
logic rdy;
|
||||
logic err;
|
||||
} r2b_t;
|
||||
|
||||
endpackage
|
@ -58,11 +58,12 @@ if __name__ == "__main__":
|
||||
out_addrmap_file = "{}/{}.sv".format(config['output_dir'], addrmap.name)
|
||||
|
||||
with open(out_addrmap_file, 'w') as file:
|
||||
file.write(
|
||||
print(
|
||||
addrmap.get_rtl(
|
||||
tab_width=config['tab_width'],
|
||||
real_tabs=config['real_tabs']
|
||||
)
|
||||
),
|
||||
file=file
|
||||
)
|
||||
|
||||
logger.info('Succesfully created "{}"'.format(out_addrmap_file))
|
||||
@ -75,7 +76,7 @@ if __name__ == "__main__":
|
||||
).items():
|
||||
if value:
|
||||
with open('{}/{}_pkg.sv'.format(config['output_dir'], key), 'w') as file:
|
||||
file.write(value)
|
||||
print(value, file=file)
|
||||
|
||||
# Copy over widget RTL from widget directory
|
||||
widget_rtl = pkg_resources.read_text(widgets, '{}.sv'.format(config['bus']))
|
||||
@ -83,9 +84,19 @@ if __name__ == "__main__":
|
||||
out_widget_file = "{}/{}.sv".format(config['output_dir'], config['bus'])
|
||||
|
||||
with open(out_widget_file, 'w') as file:
|
||||
file.write(widget_rtl)
|
||||
print(widget_rtl, file=file)
|
||||
|
||||
logger.info("Selected, implemented, and copied '{}' widget".format(config['bus']))
|
||||
|
||||
# Copy over generic srdl2sv_widget_pkg
|
||||
widget_if_rtl = pkg_resources.read_text(widgets, 'srdl2sv_widget_pkg.sv')
|
||||
|
||||
out_widget_if_file = "{}/srdl2sv_widget_pkg.sv".format(config['output_dir'])
|
||||
|
||||
with open(out_widget_if_file, 'w') as file:
|
||||
print(widget_if_rtl,file=file)
|
||||
|
||||
logger.info("Copied 'srdl2sv_widget_pkg.sv")
|
||||
|
||||
# Print elapsed time
|
||||
logger.info("Elapsed time: %f seconds", time.time() - start)
|
||||
|
Loading…
Reference in New Issue
Block a user