Skip to content

Instantly share code, notes, and snippets.

@josyb
Last active November 20, 2022 10:07
Show Gist options
  • Save josyb/2e43c9ad7ffa772d52dfd66cb660dc4a to your computer and use it in GitHub Desktop.
Save josyb/2e43c9ad7ffa772d52dfd66cb660dc4a to your computer and use it in GitHub Desktop.
Object Oriented Design in MyHDL

There is a web-page where Adam Taylor lists 10 alternative FPGA development languages: http://www.eetimes.com/document.asp?doc_id=1329857 On some languages the OO-word was used ... I commented that the only thing I have seen so far from these languages is that they are (truly) class based but that I haven't seen any real example. Yet, as I did not study them to their deepest extent, having not enough time and too much other work ...

I already use class-based design for my MyHDL work, see my gist https://gist.github.com/josyb/afd84c9a06fdec77f2fd, but this is not OO as none of these classes have been subclassed.

In stead of doing some real work today (Sat Oct 22nd 2016), I decided to give OO in MyHDL a try. You can see the results in the two next files.

Fedback welcome!

'''
Created on 22 Oct 2016
@author: Josy
# Copyright (c) 2016 Josy Boelen
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
'''
from myhdl import Signal, intbv, ResetSignal, always_seq, always_comb, instances, toVHDL
from Utilities import hdlutils
class BasicUpCounter(object):
''' a basic up-counter '''
def __init__(self, LEN_COUNT, Clk, Reset, SClr=None, CntEn=None, Q=None):
'''
LEN_COUNT: == MAX_COUNT + 1
'''
self._maxcount = LEN_COUNT - 1
self.clk = Clk
self.reset = Reset
self.sclr = SClr if SClr is not None else False
self.bccnten = CntEn if CntEn is not None else True
self.Q = Q if Q is not None else Signal(intbv(0)[hdlutils.widthu(LEN_COUNT):])
def rtl(self):
''' the counter '''
@always_seq(self.clk.posedge, self.reset)
def synch():
''' counting ... '''
if self.bccnten or self.sclr:
if self.sclr:
self.Q.next = 0
else:
if self.Q < self._maxcount:
self.Q.next = self.Q + 1
else:
self.Q.next = 0
return synch
class UpCounter(BasicUpCounter):
''' a counter with some extras '''
def __init__(self, LEN_COUNT, Clk, Reset, SClr=None, CntEn=None, Q=None,
IsZero=None):
# must call base class first
super(UpCounter, self).__init__(LEN_COUNT, Clk, Reset, SClr, CntEn, Q)
self.IsZero = IsZero if IsZero is not None else Signal(bool())
def rtl(self):
''' augmenting the basic counter '''
# first instantiate the rtl of the basic counter
bcrtl = super(UpCounter, self).rtl()
if self.IsZero != 'Open':
@always_comb
def aiz():
''' isZero? '''
if self.Q == 0:
self.IsZero.next = 1
else:
self.IsZero.next = 0
return instances()
class OneShotCounter(UpCounter):
''' making the UpCounter stop at a given maximum '''
def __init__(self, LEN_COUNT, Clk, Reset, MaxCount, SClr=None, CntEn=None, Q=None,
IsZero=None):
super(OneShotCounter, self).__init__(LEN_COUNT, Clk, Reset, SClr, None, Q, IsZero=IsZero)
# make sure that _cnten is now a signal (under our control)
self.osccnten = CntEn if CntEn is not None else True
self.bccnten = Signal(bool(0))
self.maxcount = MaxCount
def rtl(self):
# first instantiate the rtl of the up-counter
uc = super(OneShotCounter, self).rtl()
@always_comb
def osc():
''' making it a one-shot-counter '''
self.bccnten.next = 0
if self.Q < self.maxcount:
self.bccnten.next = self.osccnten
return instances()
if __name__ == '__main__':
def top_oo(LEN_COUNT, Clk, Reset, MaxCount, SClr, CntEn, Q, IsZero):
return OneShotCounter(LEN_COUNT, Clk, Reset, MaxCount, SClr=SClr, CntEn=CntEn, Q=Q, IsZero=IsZero).rtl()
def convert():
C_LEN_COUNT = 256
Clk = Signal(bool(0))
Reset = ResetSignal(0, 1, True)
SClr = Signal(bool(0))
CntEn = Signal(bool(0))
Q = Signal(intbv(0)[hdlutils.widthu(C_LEN_COUNT):])
MaxCount = Signal(intbv(0)[hdlutils.widthu(C_LEN_COUNT):])
IsZero = Signal(bool(0))
toVHDL.no_initial_values = True
toVHDL.std_logic_ports = True
toVHDL( top_oo, C_LEN_COUNT, Clk, Reset, MaxCount, SClr, CntEn, Q, IsZero)
convert()
-- File: top_oo.vhd
-- Generated by MyHDL 1.0dev
-- Date: Sat Oct 22 14:32:10 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 top_oo is
port(
Clk : in std_logic;
Reset : in std_logic;
MaxCount : in std_logic_vector(7 downto 0);
SClr : in std_logic;
CntEn : in std_logic;
Q : out std_logic_vector(7 downto 0);
IsZero : out std_logic
);
end entity top_oo;
architecture MyHDL of top_oo is
signal MaxCount_num : unsigned(7 downto 0);
signal Q_num : unsigned(7 downto 0);
signal bccnten : std_logic;
begin
MaxCount_num <= unsigned(MaxCount);
Q <= std_logic_vector(Q_num);
-- making it a one-shot-counter
osc : process(Q_num, CntEn, MaxCount_num) is
begin
bccnten <= '0';
if (Q_num < MaxCount_num) then
bccnten <= CntEn;
end if;
end process osc;
-- counting ...
uc_bc_synch : process(Clk, Reset) is
begin
if (Reset = '1') then
Q_num <= to_unsigned(0, 8);
elsif rising_edge(Clk) then
if (bool(bccnten) or bool(SClr)) then
if bool(SClr) then
Q_num <= to_unsigned(0, 8);
else
if (Q_num < 255) then
Q_num <= (Q_num + 1);
else
Q_num <= to_unsigned(0, 8);
end if;
end if;
end if;
end if;
end process uc_bc_synch;
-- isZero?
uc_aiz : process(Q_num) is
begin
if (Q_num = 0) then
IsZero <= '1';
else
IsZero <= '0';
end if;
end process uc_aiz;
end architecture MyHDL;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment