Skip to content

Instantly share code, notes, and snippets.

@josyb
Last active October 9, 2018 09:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save josyb/afd84c9a06fdec77f2fd to your computer and use it in GitHub Desktop.
Save josyb/afd84c9a06fdec77f2fd to your computer and use it in GitHub Desktop.
Exploring improved structural design - Part 1
'''
Created on 29 Dec 2015
@author: Josy
'''
from __future__ import print_function
import random
import myhdl
from Utilities import hdlutils
class Register( object):
''' a simple class with limited functionality '''
def __init__(self, WIDTH_D, Clk, Data, Shift, Result=None):
self.width_d = WIDTH_D
self.clk = Clk
self.shift = Shift
self.data = Data # imagine that 'Data' can be any type (almost)
if Result is None:
# in this particular case the Result is of the same type of the Data
# so we resort to getting a new object of that type
# but it could be any type, except 'interface'
# unless you write a copy() attribute for every new interface
# I added this copy() attribute to the _Signal class ...
self.result = self.data.copy()
# if using the 'master' branch of MyHDL: you can replace the above line with:
# self.result = myhdl.Signal( Data._val )
else:
self.result = Result
def rtl(self):
''' the actual rtl is an elaborate way to code a 'simple' register
this is what gets converted, eventually '''
lqn = myhdl.Signal( myhdl.intbv(0)[self.width_d:])
@myhdl.always_comb
def regcomb():
''' the combinatorial part of the rtl'''
if self.shift:
lqn.next = self.data[:1]
else:
lqn.next = self.data
@myhdl.always_seq( self.clk.posedge, reset= None)
def regreg():
''' the registered part of the rtl'''
self.result.next = lqn
return regcomb, regreg
def mregister(WIDTH_D, Clk, D, Shift, Q):
''' the top level module is 'structural'
we simply concatenate four modules
'''
# instantiate the four sub-modules
reg1 = Register(WIDTH_D, Clk, D, Shift)
reg2 = Register(WIDTH_D, Clk, reg1.result, Shift)
reg3 = Register(WIDTH_D, Clk, reg2.result, Shift)
reg4 = Register(WIDTH_D, Clk, reg3.result, Shift, Q)
# but we need to collect the generators
# we could automate that, like myhdl.instances()?
if RETURN_GENERATORS_METHOD == 'Append':
# this works
# but the 'original' names reg1, ... get replaced by inst0, inst1, ...
inst = []
inst.append(reg1.rtl())
inst.append(reg2.rtl())
inst.append(reg3.rtl())
inst.append(reg4.rtl())
return inst
elif RETURN_GENERATORS_METHOD == 'IntermediateObject':
# this works too
# but here also the 'original' names reg1, ... get replaced by inst0, inst1, ...
inst = reg1.rtl(), reg2.rtl(), reg3.rtl(), reg4.rtl()
return inst
elif RETURN_GENERATORS_METHOD == 'Direct':
# this throws an 'myhdl.ExtractHierarchyError: Inconsistent hierarchy - are all instances returned ?'
return reg1.rtl(), reg2.rtl(), reg3.rtl(), reg4.rtl()
elif RETURN_GENERATORS_METHOD == 'Indirect':
# this works as 'desired'
reg1rtl = reg1.rtl()
reg2rtl = reg2.rtl()
reg3rtl = reg3.rtl()
reg4rtl = reg4.rtl()
# return reg1rtl, reg2rtl, reg3rtl, reg4rtl
return myhdl.instances()
elif RETURN_GENERATORS_METHOD == 'Named':
# this is a mixed success ...
# reg1rtl and reg3rtl are in the VHDL code,
# whereas reg2rtl and reg4rtl are replaced by inst1 and inst3 ...
inst = []
reg1rtl = reg1.rtl()
reg2rtl = reg2.rtl()
reg3rtl = reg3.rtl()
reg4rtl = reg4.rtl()
inst.append(reg1rtl)
inst.append(reg2rtl)
inst.append(reg3rtl)
inst.append(reg4rtl)
return inst
def tb_mregister():
''' test bench
not self-checking ...
'''
Clk = myhdl.Signal( bool( 0 ))
Shift = myhdl.Signal( bool( 0 ))
D = myhdl.Signal(myhdl.intbv(0)[T_WIDTH_D:])
Q = myhdl.Signal(myhdl.intbv(0)[T_WIDTH_D:])
dut = mregister(T_WIDTH_D, Clk, D, Shift, Q)
ClkCount = myhdl.Signal(myhdl.intbv(0)[8:])
tCK = 20
random.seed('We want repeatable randomness')
@myhdl.instance
def clkgen():
yield hdlutils.genClk(Clk, tCK, ClkCount)
@myhdl.instance
def stimulusin():
Shift.next = 0
yield hdlutils.delayclks(Clk, tCK, 5)
for _ in range(16):
D.next = random.randint(0,2**T_WIDTH_D)
yield hdlutils.delayclks(Clk, tCK, 1)
yield hdlutils.delayclks(Clk, tCK, 5)
Shift.next = 1
for _ in range(16):
D.next = random.randint(0,2**T_WIDTH_D)
yield hdlutils.delayclks(Clk, tCK, 1)
yield hdlutils.delayclks(Clk, tCK, 5)
raise myhdl.StopSimulation
return dut, clkgen, stimulusin
def convert():
Clk = myhdl.Signal( bool( 0 ))
Shift = myhdl.Signal( bool( 0 ))
D = myhdl.Signal(myhdl.intbv(0)[T_WIDTH_D:])
Q = myhdl.Signal(myhdl.intbv(0)[T_WIDTH_D:])
myhdl.toVHDL( mregister, T_WIDTH_D, Clk, D, Shift, Q )
myhdl.toVerilog( mregister, T_WIDTH_D, Clk, D, Shift, Q )
if __name__ == '__main__':
T_WIDTH_D = 8
RETURN_GENERATORS_METHOD = 'Indirect' # 'Append', 'Direct', 'Named', 'IntermediateObject' or 'Indirect'
hdlutils.simulate(0, tb_mregister)
convert()
// File: mregister.v
// Generated by MyHDL 1.0dev
// Date: Fri Jan 15 20:05:25 2016
`timescale 1ns/10ps
module mregister (
Clk,
D,
Shift,
Q
);
// the top level module is 'structural'
// we simply concatenate four modules
input Clk;
input [7:0] D;
input Shift;
output [7:0] Q;
reg [7:0] Q;
reg [7:0] reg4_lqn;
reg [7:0] reg4_data;
reg [7:0] reg3_lqn;
reg [7:0] reg3_data;
reg [7:0] reg2_lqn;
reg [7:0] reg2_data;
reg [7:0] reg1_lqn;
// the combinatorial part of the rtl
always @(Shift, reg3_data) begin: mregister_reg3_regcomb
if (Shift) begin
reg3_lqn = reg3_data[8-1:1];
end
else begin
reg3_lqn = reg3_data;
end
end
// the registered part of the rtl
always @(posedge Clk) begin: mregister_reg3_regreg
reg4_data <= reg3_lqn;
end
// the combinatorial part of the rtl
always @(Shift, D) begin: mregister_reg1_regcomb
if (Shift) begin
reg1_lqn = D[8-1:1];
end
else begin
reg1_lqn = D;
end
end
// the registered part of the rtl
always @(posedge Clk) begin: mregister_reg1_regreg
reg2_data <= reg1_lqn;
end
// the combinatorial part of the rtl
always @(Shift, reg2_data) begin: mregister_reg2_regcomb
if (Shift) begin
reg2_lqn = reg2_data[8-1:1];
end
else begin
reg2_lqn = reg2_data;
end
end
// the registered part of the rtl
always @(posedge Clk) begin: mregister_reg2_regreg
reg3_data <= reg2_lqn;
end
// the combinatorial part of the rtl
always @(Shift, reg4_data) begin: mregister_reg4_regcomb
if (Shift) begin
reg4_lqn = reg4_data[8-1:1];
end
else begin
reg4_lqn = reg4_data;
end
end
// the registered part of the rtl
always @(posedge Clk) begin: mregister_reg4_regreg
Q <= reg4_lqn;
end
endmodule
-- File: mregister.tmp
-- Generated by MyHDL 1.0dev
-- Date: Fri Jan 1 19:53:47 2016
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use std.textio.all;
use work.pck_myhdl_10.all;
entity mregister is
port (
Clk : in std_logic;
D : in unsigned(7 downto 0);
Shift : in std_logic;
Q : out unsigned(7 downto 0)
);
end entity mregister;
-- the top level module is 'structural'
-- we simply concatenate four modules
architecture MyHDL of mregister is
signal reg1_lqn : unsigned(7 downto 0);
signal reg2_data : unsigned(7 downto 0);
signal reg2_lqn : unsigned(7 downto 0);
signal reg3_data : unsigned(7 downto 0);
signal reg3_lqn : unsigned(7 downto 0);
signal reg4_data : unsigned(7 downto 0);
signal reg4_lqn : unsigned(7 downto 0);
begin
-- the combinatorial part of the rtl
reg3_regcomb: process (Shift, reg3_data) is
begin
if bool(Shift) then
reg3_lqn <= resize(reg3_data(8-1 downto 1), 8);
else
reg3_lqn <= reg3_data;
end if;
end process reg3_regcomb;
-- the registered part of the rtl
reg3_regreg: process (Clk) is
begin
if rising_edge(Clk) then
reg4_data <= reg3_lqn;
end if;
end process reg3_regreg;
-- the combinatorial part of the rtl
reg1_regcomb: process (Shift, D) is
begin
if bool(Shift) then
reg1_lqn <= resize(D(8-1 downto 1), 8);
else
reg1_lqn <= D;
end if;
end process reg1_regcomb;
-- the registered part of the rtl
reg1_regreg: process (Clk) is
begin
if rising_edge(Clk) then
reg2_data <= reg1_lqn;
end if;
end process reg1_regreg;
-- the combinatorial part of the rtl
reg2_regcomb: process (Shift, reg2_data) is
begin
if bool(Shift) then
reg2_lqn <= resize(reg2_data(8-1 downto 1), 8);
else
reg2_lqn <= reg2_data;
end if;
end process reg2_regcomb;
-- the registered part of the rtl
reg2_regreg: process (Clk) is
begin
if rising_edge(Clk) then
reg3_data <= reg2_lqn;
end if;
end process reg2_regreg;
-- the combinatorial part of the rtl
reg4_regcomb: process (Shift, reg4_data) is
begin
if bool(Shift) then
reg4_lqn <= resize(reg4_data(8-1 downto 1), 8);
else
reg4_lqn <= reg4_data;
end if;
end process reg4_regcomb;
-- the registered part of the rtl
reg4_regreg: process (Clk) is
begin
if rising_edge(Clk) then
Q <= reg4_lqn;
end if;
end process reg4_regreg;
end architecture MyHDL;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment