Last active
October 9, 2018 09:23
-
-
Save josyb/afd84c9a06fdec77f2fd to your computer and use it in GitHub Desktop.
Exploring improved structural design - Part 1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- 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