\title{Bitwise Behavior in myHDL: Selecting, Shifting, Concatenation, Slicing} \author{Steven K Armour} \maketitle

Table of Contents

References

@misc{myhdl_2018, title={Hardware-oriented types — MyHDL 0.10 documentation}, url={http://docs.myhdl.org/en/stable/manual/hwtypes.html}, journal={Docs.myhdl.org}, author={myHDL}, year={2018} },

@misc{vandenbout_2018, title={pygmyhdl 0.0.3 documentation}, url={https://xesscorp.github.io/pygmyhdl/docs/_build/singlehtml/index.html}, journal={Xesscorp.github.io}, author={Vandenbout, Dave}, year={2018} }

Libraries and Helper functions


In [1]:
#This notebook also uses the `(some) LaTeX environments for Jupyter`
#https://github.com/ProfFan/latex_envs wich is part of the
#jupyter_contrib_nbextensions package

from myhdl import *
from myhdlpeek import Peeker
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

from sympy import *
init_printing()

import random

#https://github.com/jrjohansson/version_information
%load_ext version_information
%version_information myhdl, myhdlpeek, numpy, pandas, matplotlib, sympy, random


Out[1]:
SoftwareVersion
Python3.6.2 64bit [GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]
IPython6.2.1
OSLinux 4.15.0 30 generic x86_64 with debian stretch sid
myhdl0.10
myhdlpeek0.0.6
numpy1.13.3
pandas0.23.3
matplotlib2.1.0
sympy1.1.2.dev
randomThe 'random' distribution was not found and is required by the application
Wed Aug 29 16:10:23 2018 MDT

In [2]:
#helper  functions to read in the .v and .vhd generated files into python
def VerilogTextReader(loc, printresult=True):
    with open(f'{loc}.v', 'r') as vText:
        VerilogText=vText.read()
    if printresult:
        print(f'***Verilog modual from {loc}.v***\n\n', VerilogText)
    return VerilogText

def VHDLTextReader(loc, printresult=True):
    with open(f'{loc}.vhd', 'r') as vText:
        VerilogText=vText.read()
    if printresult:
        print(f'***VHDL modual from {loc}.vhd***\n\n', VerilogText)
    return VerilogText

In [3]:
CountVal=17
BitSize=int(np.log2(CountVal))+1; BitSize


Out[3]:
$$5$$

myHDL Bit Indexing

Bit Indexing is the act of selecting or assigning one of the bits in a Bit Vector

Expected Indexing Selection Behavior


In [4]:
TV=intbv(-93)[8:].signed()
print(f'Value:{int(TV)}, Binary {bin(TV)}')


Value:-93, Binary 10100011

In [5]:
for i in range(len(TV)):
    print(f'Bit from LSB: {i}, Selected Bit: {int(TV[i])}')


Bit from LSB: 0, Selected Bit: 1
Bit from LSB: 1, Selected Bit: 1
Bit from LSB: 2, Selected Bit: 0
Bit from LSB: 3, Selected Bit: 0
Bit from LSB: 4, Selected Bit: 0
Bit from LSB: 5, Selected Bit: 1
Bit from LSB: 6, Selected Bit: 0
Bit from LSB: 7, Selected Bit: 1

which shows that when selecting a single bit from a BitVector that selection [0] is the Least Significant Bit (LSB) (inclusive behavior) while for the Most Significant Bit (MSB) will be the index of the BitVector length -1 (noninclusive behavior)

Attempted Selection with Python Negative Warping


In [6]:
try:
    TV[-1]
except ValueError:
    print("ValueError: negative shift count")


ValueError: negative shift count

This means that negative indexing using python's list selection wrap around is NOT implemented in a myHDL intbv


In [7]:
TV=modbv(-93)[8:].signed()
print(f'Value:{int(TV)}, Binary {bin(TV)}')
try:
    TV[-1]
except ValueError:
    print("ValueError: negative shift count")


Value:-93, Binary 10100011
ValueError: negative shift count

nor is the negative wrapping supported by the use of the modbv

Selecting above the MSB


In [8]:
TV=intbv(93)[8:]
TV_S=intbv(-93)[8:].signed()
TV_M=modbv(-93)[8:].signed()
print(f'`intbv`:Value:{int(TV)}, Binary {bin(TV)}, [8]:{int(TV[8])}, [9]:{int(TV[9])}')
print(f'`intbv signed`:Value:{int(TV_S)}, Binary {bin(TV_S)}, [8]:{int(TV_S[8])}, [9]:{int(TV_S[9])}')
print(f'`modbv`:Value:{int(TV_M)}, Binary {bin(TV_M)}, [8]:{int(TV_M[8])}, [9]:{int(TV_M[9])}')


`intbv`:Value:93, Binary 1011101, [8]:0, [9]:0
`intbv signed`:Value:-93, Binary 10100011, [8]:1, [9]:1
`modbv`:Value:-93, Binary 10100011, [8]:1, [9]:1

Thus selecting above the MSB will generate a 0 if the Bit Vector is not signed where as selecting above the MSB for a signed bit will produce a 1.

Bit Selection of Signal


In [9]:
TV=Signal(intbv(93)[8:])

In [10]:
TV[0], TV(0), TV[9], TV(9)


Out[10]:
(True, Signal(True), False, Signal(False))

The difference is that outside of a generator, bit selection of a signal using [] only returns a value and not a signal that is only returned using (). This is important to know since only a Signal can be converted to registers/wires in the conversion from myHDL to Verilog/VHDL

myHDL Bit Selection Demo


In [11]:
@block
def BitSelectDemo(Index, Res, SignRes):
    """
    Bit Selection Demo
    
    Input:
        Index(4BitVec): value for selection from internal refrances 
    Output:
        Res(8BitVec): BitVector with Bit Location set from `Index` from 
            refrance internal 8Bit `intbv` with value 93
        SignRes(8BitVec Signed): signed BitVector with Bit Location set from `Index` from 
            refrance internal signed 8Bit `intbv` with value -93
    """
    Ref=Signal(intbv(93)[8:])
    RefS=Signal(intbv(-93)[8:].signed())
    @always_comb
    def logic():
        Res.next[Index]=Ref[Index]
        SignRes.next[Index]=RefS[Index]

    return instances()

Bit Assignment

Note: that in the above the module also shows how to perform bit selection assignment. The output signal Res or SignRes is assigned a value from the References at position Index but then the bit from the references is set to position Index in the outputs. Notice that the syntax is

Variable.next[index]=

The same structure is also used in setting bit slices so that for a big slice assignment is

Variable.next[MSB:LSB]=

myHDL Testing


In [12]:
Peeker.clear()
Index=Signal(intbv(0)[4:]); Peeker(Index, 'Index')
Res=Signal(intbv(0)[8:]); Peeker(Res, 'Res')
SignRes=Signal(intbv(0)[8:].signed()); Peeker(SignRes, 'SignRes')

DUT=BitSelectDemo(Index, Res, SignRes)

def BitSelectDemo_TB():
    """
    myHDL only Testbench
    """
    @instance
    def stimules():
        for i in range(7):
            Index.next=i
            yield delay(1)
        
        raise StopSimulation()
    
    return instances()
sim=Simulation(DUT, BitSelectDemo_TB(), *Peeker.instances()).run()

Note that if the for loop range was increased beyond 7 an error would be triggered.


In [13]:
Peeker.to_wavedrom('Index', 'Res', 'SignRes')



In [14]:
BitSelectDemoData=Peeker.to_dataframe() 
BitSelectDemoData['Res Bin']=BitSelectDemoData['Res'].apply(lambda Row: bin(Row, 8), 1)
BitSelectDemoData['SignRes Bin']=BitSelectDemoData['SignRes'].apply(lambda Row: bin(Row, 8), 1)
BitSelectDemoData=BitSelectDemoData[['Index', 'Res', 'Res Bin', 'SignRes', 'SignRes Bin']]
BitSelectDemoData


Out[14]:
Index Res Res Bin SignRes SignRes Bin
0 0 1 00000001 1 00000001
1 1 1 00000001 3 00000011
2 2 5 00000101 3 00000011
3 3 13 00001101 3 00000011
4 4 29 00011101 3 00000011
5 5 29 00011101 35 00100011
6 6 93 01011101 35 00100011

Verilog Conversion

Verilog Conversion Error

Line 24 in the conversion of BitSelectDemo to BitSelectDemo.v is incorrect. The myHDL source line is

RefS=Signal(intbv(-93)[8:].signed())

but the converted line becomes

assign RefS = 8'd-93;

but this needs to instead become

assign RefS = -8'd93;

in BitSelectDemo.v


In [15]:
DUT.convert()
VerilogTextReader('BitSelectDemo');


***Verilog modual from BitSelectDemo.v***

 // File: BitSelectDemo.v
// Generated by MyHDL 0.10
// Date: Wed Aug 29 14:27:57 2018


`timescale 1ns/10ps

module BitSelectDemo (
    Index,
    Res,
    SignRes
);
// Bit Selection Demo
// 
// Input:
//     Index(4BitVec): value for selection from internal refrances 
// Output:
//     Res(8BitVec): BitVector with Bit Location set from `Index` from 
//         refrance internal 8Bit `intbv` with value 93
//     SignRes(8BitVec Signed): signed BitVector with Bit Location set from `Index` from 
//         refrance internal signed 8Bit `intbv` with value -93

input [3:0] Index;
output [7:0] Res;
reg [7:0] Res;
output signed [7:0] SignRes;
reg signed [7:0] SignRes;

wire [7:0] RefS;
wire [7:0] Ref;

assign RefS = 8'd-93;
assign Ref = 8'd93;


always @(Index, RefS, Ref) begin: BITSELECTDEMO_LOGIC
    Res[Index] = Ref[Index];
    SignRes[Index] = RefS[Index];
end

endmodule

/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: RefS
  category=ToVerilogWarning
/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: Ref
  category=ToVerilogWarning
\begin{figure} \centerline{\includegraphics[width=10cm]{BitSelectDemo_v_RTL.png}} \caption{\label{fig:BSDVRTL} BitSelectDemo Verilog RTL schematic with corrected errors; Xilinx Vivado 2017.4} \end{figure}
\begin{figure} \centerline{\includegraphics[width=10cm]{BitSelectDemo_v_SYN.png}} \caption{\label{fig:BSDVHDSYN} BitSelectDemo Verilog Synthesized Schematic with corrected errors; Xilinx Vivado 2017.4} \end{figure}

VHDL Conversion

VHDL Conversion Issue

The resulting BitSelectDemo.vhd from BitSelectDemo contains a line that calls from a libary work.pck_myhdl_010.all that is created when this file is ran. Make sure to import this file along with BitSelectDemo.vhd.


In [16]:
DUT.convert('VHDL')
VHDLTextReader('BitSelectDemo');


***VHDL modual from BitSelectDemo.vhd***

 -- File: BitSelectDemo.vhd
-- Generated by MyHDL 0.10
-- Date: Wed Aug 29 14:27:57 2018


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use std.textio.all;

use work.pck_myhdl_010.all;

entity BitSelectDemo is
    port (
        Index: in unsigned(3 downto 0);
        Res: out unsigned(7 downto 0);
        SignRes: out signed (7 downto 0)
    );
end entity BitSelectDemo;
-- Bit Selection Demo
-- 
-- Input:
--     Index(4BitVec): value for selection from internal refrances 
-- Output:
--     Res(8BitVec): BitVector with Bit Location set from `Index` from 
--         refrance internal 8Bit `intbv` with value 93
--     SignRes(8BitVec Signed): signed BitVector with Bit Location set from `Index` from 
--         refrance internal signed 8Bit `intbv` with value -93

architecture MyHDL of BitSelectDemo is


signal RefS: signed (7 downto 0);
signal Ref: unsigned(7 downto 0);

begin


RefS <= to_signed(-93, 8);
Ref <= to_unsigned(93, 8);


BITSELECTDEMO_LOGIC: process (Index, RefS, Ref) is
begin
    Res(to_integer(Index)) <= Ref(to_integer(Index));
    SignRes(to_integer(Index)) <= RefS(to_integer(Index));
end process BITSELECTDEMO_LOGIC;

end architecture MyHDL;

/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVHDL.py:453: ToVHDLWarning: Signal is not driven: RefS
  category=ToVHDLWarning
/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVHDL.py:453: ToVHDLWarning: Signal is not driven: Ref
  category=ToVHDLWarning
\begin{figure} \centerline{\includegraphics[width=10cm]{BitSelectDemo_vhd_RTL.png}} \caption{\label{fig:BSDVHDRTL} BitSelectDemo VHDL RTL schematic with corrected errors; Xilinx Vivado 2017.4} \end{figure}
\begin{figure} \centerline{\includegraphics[width=10cm]{BitSelectDemo_vhd_SYN.png}} \caption{\label{fig:BSDVHDSYN} BitSelectDemo VHDL Synthesized Schematic with corrected errrors; Xilinx Vivado 2017.4} \end{figure}

myHDL to Verilog/VHDL Testbench


In [17]:
@block
def BitSelectDemo_TB_V_VHDL():
    """
    myHDL -> Verilog/VHDL Testbench for `BitSelectDemo`
    """

    Index=Signal(intbv(0)[4:])
    Res=Signal(intbv(0)[8:])
    SignRes=Signal(intbv(0)[8:].signed())

    @always_comb
    def print_data():
        print(Index, Res, SignRes)

    DUT=BitSelectDemo(Index, Res, SignRes)

    @instance
    def stimules():
        for i in range(7):
            Index.next=i
            yield delay(1)
        
        raise StopSimulation()
    
    return instances()
TB=BitSelectDemo_TB_V_VHDL()

Verilog Testbench

Verilog Testbench Conversion Issue

This testbench will work after

assign RefS = 8'd-93;

is changed to

assign RefS = -8'd93;

In [18]:
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('BitSelectDemo_TB_V_VHDL');


<class 'myhdl._Signal._Signal'> <class '_ast.Name'>
<class 'myhdl._Signal._Signal'> <class '_ast.Name'>
<class 'myhdl._Signal._Signal'> <class '_ast.Name'>
***Verilog modual from BitSelectDemo_TB_V_VHDL.v***

 // File: BitSelectDemo_TB_V_VHDL.v
// Generated by MyHDL 0.10
// Date: Wed Aug 29 14:27:58 2018


`timescale 1ns/10ps

module BitSelectDemo_TB_V_VHDL (

);
// myHDL -> Verilog/VHDL Testbench


reg [3:0] Index = 0;
reg [7:0] Res = 0;
reg signed [7:0] SignRes = 0;
wire [7:0] BitSelectDemo0_0_RefS;
wire [7:0] BitSelectDemo0_0_Ref;

assign BitSelectDemo0_0_RefS = 8'd-93;
assign BitSelectDemo0_0_Ref = 8'd93;


always @(SignRes, Index, Res) begin: BITSELECTDEMO_TB_V_VHDL_PRINT_DATA
    $write("%h", Index);
    $write(" ");
    $write("%h", Res);
    $write(" ");
    $write("%h", SignRes);
    $write("\n");
end


always @(Index, BitSelectDemo0_0_RefS, BitSelectDemo0_0_Ref) begin: BITSELECTDEMO_TB_V_VHDL_BITSELECTDEMO0_0_LOGIC
    Res[Index] = BitSelectDemo0_0_Ref[Index];
    SignRes[Index] = BitSelectDemo0_0_RefS[Index];
end


initial begin: BITSELECTDEMO_TB_V_VHDL_STIMULES
    integer i;
    for (i=0; i<7; i=i+1) begin
        Index <= i;
        # 1;
    end
    $finish;
end

endmodule

/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: BitSelectDemo0_0_RefS
  category=ToVerilogWarning
/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: BitSelectDemo0_0_Ref
  category=ToVerilogWarning

VHDL Testbench

VHDL Testbench Conversion Issue

This Testbench is not working in Vivado


In [19]:
TB.convert(hdl="VHDL", initial_values=True)
VHDLTextReader('BitSelectDemo_TB_V_VHDL');


***VHDL modual from BitSelectDemo_TB_V_VHDL.vhd***

 -- File: BitSelectDemo_TB_V_VHDL.vhd
-- Generated by MyHDL 0.10
-- Date: Wed Aug 29 14:27:58 2018


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use std.textio.all;

use work.pck_myhdl_010.all;

entity BitSelectDemo_TB_V_VHDL is
end entity BitSelectDemo_TB_V_VHDL;
-- myHDL -> Verilog/VHDL Testbench

architecture MyHDL of BitSelectDemo_TB_V_VHDL is


signal Index: unsigned(3 downto 0) := 4X"0";
signal Res: unsigned(7 downto 0) := 8X"00";
signal SignRes: signed (7 downto 0) := 8X"00";
signal BitSelectDemo0_0_RefS: signed (7 downto 0);
signal BitSelectDemo0_0_Ref: unsigned(7 downto 0);

begin


BitSelectDemo0_0_RefS <= to_signed(-93, 8);
BitSelectDemo0_0_Ref <= to_unsigned(93, 8);


BITSELECTDEMO_TB_V_VHDL_PRINT_DATA: process (SignRes, Index, Res) is
    variable L: line;
begin
    write(L, to_hstring(Index));
    write(L, string'(" "));
    write(L, to_hstring(Res));
    write(L, string'(" "));
    write(L, to_hstring(unsigned(SignRes)));
    writeline(output, L);
end process BITSELECTDEMO_TB_V_VHDL_PRINT_DATA;

BITSELECTDEMO_TB_V_VHDL_BITSELECTDEMO0_0_LOGIC: process (Index, BitSelectDemo0_0_RefS, BitSelectDemo0_0_Ref) is
begin
    Res(to_integer(Index)) <= BitSelectDemo0_0_Ref(to_integer(Index));
    SignRes(to_integer(Index)) <= BitSelectDemo0_0_RefS(to_integer(Index));
end process BITSELECTDEMO_TB_V_VHDL_BITSELECTDEMO0_0_LOGIC;

BITSELECTDEMO_TB_V_VHDL_STIMULES: process is
begin
    for i in 0 to 7-1 loop
        Index <= to_unsigned(i, 4);
        wait for 1 * 1 ns;
    end loop;
    assert False report "End of Simulation" severity Failure;
    wait;
end process BITSELECTDEMO_TB_V_VHDL_STIMULES;

end architecture MyHDL;

/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVHDL.py:453: ToVHDLWarning: Signal is not driven: BitSelectDemo0_0_RefS
  category=ToVHDLWarning
/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVHDL.py:453: ToVHDLWarning: Signal is not driven: BitSelectDemo0_0_Ref
  category=ToVHDLWarning

myHDL shift (<</>>) behavior

Left Shift (<<)

Left Shifting with intbv


In [20]:
#Left Shift test with intbv
#intialize 
TV=intbv(52)[8:]
print(TV, bin(TV, 8))
#demenstrate left shifting with intbv
for i in range(8):
    LSRes=TV<<i
    print(f'Left Shift<<{i}; Binary: {bin(LSRes)}, BitLen: {len(bin(LSRes))}, Value:{LSRes}')


34 00110100
Left Shift<<0; Binary: 110100, BitLen: 6, Value:34
Left Shift<<1; Binary: 1101000, BitLen: 7, Value:68
Left Shift<<2; Binary: 11010000, BitLen: 8, Value:d0
Left Shift<<3; Binary: 110100000, BitLen: 9, Value:1a0
Left Shift<<4; Binary: 1101000000, BitLen: 10, Value:340
Left Shift<<5; Binary: 11010000000, BitLen: 11, Value:680
Left Shift<<6; Binary: 110100000000, BitLen: 12, Value:d00
Left Shift<<7; Binary: 1101000000000, BitLen: 13, Value:1a00

Left Shifting with signed intbv


In [21]:
#Left Shift test with intbv signed
#intialize 
TV=intbv(-52)[8:].signed()
print(TV, bin(TV, 8))
#demenstrate left shifting with intbv signed
for i in range(8):
    LSRes=(TV<<i).signed()
    print(f'Left Shift<<{i}; Binary: {bin(LSRes)}, BitLen: {len(bin(LSRes))}, Value:{LSRes}')


cc 11001100
Left Shift<<0; Binary: 1001100, BitLen: 7, Value:-34
Left Shift<<1; Binary: 10011000, BitLen: 8, Value:-68
Left Shift<<2; Binary: 100110000, BitLen: 9, Value:-d0
Left Shift<<3; Binary: 1001100000, BitLen: 10, Value:-1a0
Left Shift<<4; Binary: 10011000000, BitLen: 11, Value:-340
Left Shift<<5; Binary: 100110000000, BitLen: 12, Value:-680
Left Shift<<6; Binary: 1001100000000, BitLen: 13, Value:-d00
Left Shift<<7; Binary: 10011000000000, BitLen: 14, Value:-1a00

Left Shifting with modbv


In [22]:
#Left Shift test with modbv
#intialize 
TV=modbv(52)[8:]
print(TV, bin(TV, 8))
#demenstrate left shifting with modbv
for i in range(8):
    LSRes=(TV<<i).signed()
    print(f'Left Shift<<{i}; Binary: {bin(LSRes)}, BitLen: {len(bin(LSRes))}, Value:{LSRes}')


34 00110100
Left Shift<<0; Binary: 110100, BitLen: 6, Value:34
Left Shift<<1; Binary: 1101000, BitLen: 7, Value:68
Left Shift<<2; Binary: 11010000, BitLen: 8, Value:d0
Left Shift<<3; Binary: 110100000, BitLen: 9, Value:1a0
Left Shift<<4; Binary: 1101000000, BitLen: 10, Value:340
Left Shift<<5; Binary: 11010000000, BitLen: 11, Value:680
Left Shift<<6; Binary: 110100000000, BitLen: 12, Value:d00
Left Shift<<7; Binary: 1101000000000, BitLen: 13, Value:1a00

As can be seen, Left shifting tacks on a number of zeros equivalent to the shift increment to the end of the binary expression for the value. This then increases the size of the needed register that the resulting value needs to set into for each left shift that does not undergo right bit cutoff

Right Shift (>>)

Right Shifting with intbv


In [23]:
#Right Shift test with intbv
#intialize 
TV=intbv(52)[8:]
print(TV, bin(TV, 8))
#demenstrate left shifting with intbv
for i in range(8):
    LSRes=TV>>i
    print(f'Right Shift>>{i}; Binary: {bin(LSRes)}, BitLen: {len(bin(LSRes))}, Value:{LSRes}')


34 00110100
Right Shift>>0; Binary: 110100, BitLen: 6, Value:34
Right Shift>>1; Binary: 11010, BitLen: 5, Value:1a
Right Shift>>2; Binary: 1101, BitLen: 4, Value:d
Right Shift>>3; Binary: 110, BitLen: 3, Value:6
Right Shift>>4; Binary: 11, BitLen: 2, Value:3
Right Shift>>5; Binary: 1, BitLen: 1, Value:1
Right Shift>>6; Binary: 0, BitLen: 1, Value:0
Right Shift>>7; Binary: 0, BitLen: 1, Value:0

Right Shifting with signed intbv


In [24]:
#Right Shift test with intbv signed
#intialize 
TV=intbv(-52)[8:].signed()
print(TV, bin(TV, 8))
#demenstrate left shifting with intbv signed
for i in range(8):
    LSRes=(TV>>i)
    print(f'Right Shift>>{i}; Binary: {bin(LSRes)}, BitLen: {len(bin(LSRes))}, Value:{LSRes}')


cc 11001100
Right Shift>>0; Binary: 1001100, BitLen: 7, Value:-34
Right Shift>>1; Binary: 100110, BitLen: 6, Value:-1a
Right Shift>>2; Binary: 10011, BitLen: 5, Value:-d
Right Shift>>3; Binary: 1001, BitLen: 4, Value:-7
Right Shift>>4; Binary: 100, BitLen: 3, Value:-4
Right Shift>>5; Binary: 10, BitLen: 2, Value:-2
Right Shift>>6; Binary: 1, BitLen: 1, Value:-1
Right Shift>>7; Binary: 1, BitLen: 1, Value:-1

Right Shifting with modbv


In [25]:
#Right Shift test with modbv
#intialize 
TV=modbv(52)[8:]
print(TV, bin(TV, 8))
#demenstrate left shifting with modbv
for i in range(8):
    LSRes=(TV>>i)
    print(f'Right Shift>>{i}; Binary: {bin(LSRes)}, BitLen: {len(bin(LSRes))}, Value:{LSRes}')


34 00110100
Right Shift>>0; Binary: 110100, BitLen: 6, Value:34
Right Shift>>1; Binary: 11010, BitLen: 5, Value:1a
Right Shift>>2; Binary: 1101, BitLen: 4, Value:d
Right Shift>>3; Binary: 110, BitLen: 3, Value:6
Right Shift>>4; Binary: 11, BitLen: 2, Value:3
Right Shift>>5; Binary: 1, BitLen: 1, Value:1
Right Shift>>6; Binary: 0, BitLen: 1, Value:0
Right Shift>>7; Binary: 0, BitLen: 1, Value:0

As can be seen, the right shift moves values (shifts) to the right by the shift increment while preserving the length of the register that is being shifted. While this means that overflow is not going to be in encountered. Right shifting trades that vulnerability for information loss as any information carried in the leftmost bits gets lost as it is shifted right beyond of the length of the register

myHDL Shifting Demo Module


In [26]:
@block
def ShiftingDemo(ShiftVal, RSRes, LSRes):
    """
    Module to Demo Shifting Behavior in myHDL refrance value
    -55 8Bit
    
    Input:
        ShiftVal(4BitVec): shift amount, for this demo to not
            use values greater then 7
    Output:
        RSRes(8BitVec Signed): output of Right Shifting 
        LSRes (15BitVec Signed): output of Left Shifting
    """
    RefVal=Signal(intbv(-55)[8:].signed())
    @always_comb
    def logic():
        RSRes.next=RefVal>>ShiftVal
        LSRes.next=RefVal<<ShiftVal
    return instances()

myHDL Testing


In [27]:
Peeker.clear()
ShiftVal=Signal(intbv()[4:]); Peeker(ShiftVal, 'ShiftVal')
RSRes=Signal(intbv()[8:].signed()); Peeker(RSRes, 'RSRes')
LSRes=Signal(intbv()[15:].signed()); Peeker(LSRes, 'LSRes')

DUT=ShiftingDemo(ShiftVal, RSRes, LSRes)

def ShiftingDemo_TB():
    """
    myHDL only Testbench for `ShiftingDemo`
    """
    
    @instance
    def stimules():
        for i in range(8):
            ShiftVal.next=i
            yield delay(1)
        
        raise StopSimulation()
    
    return instances()

sim=Simulation(DUT, ShiftingDemo_TB(), *Peeker.instances()).run()

In [28]:
Peeker.to_wavedrom('ShiftVal', 'LSRes', 'RSRes');



In [29]:
Peeker.to_dataframe()[['ShiftVal', 'LSRes', 'RSRes']]


Out[29]:
ShiftVal LSRes RSRes
0 0 -55 -55
1 1 -110 -28
2 2 -220 -14
3 3 -440 -7
4 4 -880 -4
5 5 -1760 -2
6 6 -3520 -1
7 7 -7040 -1

Verilog Conversion

Unfortunately this is an unsynthesizable module as is due

assign RefVal = 8'd-55;

needing to be changed to

assign RefVal = -8'd55;

after wich the module is synthesizable


In [30]:
DUT.convert()
VerilogTextReader('ShiftingDemo');


***Verilog modual from ShiftingDemo.v***

 // File: ShiftingDemo.v
// Generated by MyHDL 0.10
// Date: Wed Aug 29 14:28:01 2018


`timescale 1ns/10ps

module ShiftingDemo (
    ShiftVal,
    RSRes,
    LSRes
);
// Module to Demo Shifting Behavior in myHDL refrance value
// -55 8Bit
// 
// Input:
//     ShiftVal(4BitVec): shift amount, for this demo to not
//         use values greater then 7
// Output:
//     RSRes(8BitVec Signed): output of Right Shifting 
//     LSRes (15BitVec Signed): output of Left Shifting

input [3:0] ShiftVal;
output signed [7:0] RSRes;
wire signed [7:0] RSRes;
output signed [14:0] LSRes;
wire signed [14:0] LSRes;

wire [7:0] RefVal;

assign RefVal = 8'd-55;



assign RSRes = $signed(RefVal >>> $signed({1'b0, ShiftVal}));
assign LSRes = (RefVal << $signed({1'b0, ShiftVal}));

endmodule

/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: RefVal
  category=ToVerilogWarning
\begin{figure} \centerline{\includegraphics[width=10cm]{ShiftingDemo_v_RTL.png}} \caption{\label{fig:SDVRTL} ShiftingDemo Verilog RTL schematic with corrected errors; Xilinx Vivado 2017.4} \end{figure}
\begin{figure} \centerline{\includegraphics[width=10cm]{ShiftingDemo_v_SYN.png}} \caption{\label{fig:SDVSYN} ShiftingDemo Verilog Synthesized Schematic with corrected errors; Xilinx Vivado 2017.4} \end{figure}

VHDL Conversion


In [31]:
DUT.convert(hdl='VHDL')
VHDLTextReader('ShiftingDemo');


***VHDL modual from ShiftingDemo.vhd***

 -- File: ShiftingDemo.vhd
-- Generated by MyHDL 0.10
-- Date: Wed Aug 29 14:28:01 2018


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use std.textio.all;

use work.pck_myhdl_010.all;

entity ShiftingDemo is
    port (
        ShiftVal: in unsigned(3 downto 0);
        RSRes: out signed (7 downto 0);
        LSRes: out signed (14 downto 0)
    );
end entity ShiftingDemo;
-- Module to Demo Shifting Behavior in myHDL refrance value
-- -55 8Bit
-- 
-- Input:
--     ShiftVal(4BitVec): shift amount, for this demo to not
--         use values greater then 7
-- Output:
--     RSRes(8BitVec Signed): output of Right Shifting 
--     LSRes (15BitVec Signed): output of Left Shifting

architecture MyHDL of ShiftingDemo is


signal RefVal: signed (7 downto 0);

begin


RefVal <= to_signed(-55, 8);



RSRes <= shift_right(RefVal, to_integer(ShiftVal));
LSRes <= shift_left(resize(RefVal, 15), to_integer(ShiftVal));

end architecture MyHDL;

/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVHDL.py:453: ToVHDLWarning: Signal is not driven: RefVal
  category=ToVHDLWarning
\begin{figure} \centerline{\includegraphics[width=10cm]{ShiftingDemo_vhd_RTL.png}} \caption{\label{fig:SDVHDRTL} ShiftingDemo VHDL RTL schematic with corrected errors; Xilinx Vivado 2017.4} \end{figure}
\begin{figure} \centerline{\includegraphics[width=10cm]{ShiftingDemo_vhd_SYN.png}} \caption{\label{fig:SDVHDSYN} ShiftingDemo VHDL Synthesized Schematic with corrected errors; Xilinx Vivado 2017.4} \end{figure}

myHDL to Verilog/VHDL Testbench


In [61]:
@block
def ShiftingDemo_TB_V_VHDL():
    """
    myHDL -> verilog/VHDL testbench for `ShiftingDemo`
    """
    
    ShiftVal=Signal(intbv()[4:])
    RSRes=Signal(intbv()[8:].signed())
    LSRes=Signal(intbv()[15:].signed())
    
    @always_comb
    def print_data():
        print(ShiftVal, RSRes, LSRes)

    DUT=ShiftingDemo(ShiftVal, RSRes, LSRes)

    
    @instance
    def stimules():
        for i in range(8):
            ShiftVal.next=i
            yield delay(1)
        
        raise StopSimulation()
    
    return instances()

TB=ShiftingDemo_TB_V_VHDL()

Verilog Testbench

Verilog Testbench Conversion Issue

This Testbench will work after

assign RefVal = 8'd-55;

is changed to

assign RefVal = -8'd55;

In [33]:
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('ShiftingDemo_TB_V_VHDL');


<class 'myhdl._Signal._Signal'> <class '_ast.Name'>
<class 'myhdl._Signal._Signal'> <class '_ast.Name'>
<class 'myhdl._Signal._Signal'> <class '_ast.Name'>
***Verilog modual from ShiftingDemo_TB_V_VHDL.v***

 // File: ShiftingDemo_TB_V_VHDL.v
// Generated by MyHDL 0.10
// Date: Wed Aug 29 14:28:02 2018


`timescale 1ns/10ps

module ShiftingDemo_TB_V_VHDL (

);
// myHDL -> verilog/VHDL testbench for `ShiftingDemo`


wire signed [14:0] LSRes;
reg [3:0] ShiftVal = 0;
wire signed [7:0] RSRes;
wire [7:0] ShiftingDemo0_0_RefVal;

assign ShiftingDemo0_0_RefVal = 8'd-55;


always @(ShiftVal, RSRes, LSRes) begin: SHIFTINGDEMO_TB_V_VHDL_PRINT_DATA
    $write("%h", ShiftVal);
    $write(" ");
    $write("%h", RSRes);
    $write(" ");
    $write("%h", LSRes);
    $write("\n");
end



assign RSRes = $signed(ShiftingDemo0_0_RefVal >>> $signed({1'b0, ShiftVal}));
assign LSRes = (ShiftingDemo0_0_RefVal << $signed({1'b0, ShiftVal}));


initial begin: SHIFTINGDEMO_TB_V_VHDL_STIMULES
    integer i;
    for (i=0; i<8; i=i+1) begin
        ShiftVal <= i;
        # 1;
    end
    $finish;
end

endmodule

/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: ShiftingDemo0_0_RefVal
  category=ToVerilogWarning

VHDL Testbench

VHDL Testbench Conversion Issue

This Testbench is not working in Vivado


In [34]:
TB.convert(hdl="VHDL", initial_values=True)
VHDLTextReader('ShiftingDemo_TB_V_VHDL');


***VHDL modual from ShiftingDemo_TB_V_VHDL.vhd***

 -- File: ShiftingDemo_TB_V_VHDL.vhd
-- Generated by MyHDL 0.10
-- Date: Wed Aug 29 14:28:02 2018


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use std.textio.all;

use work.pck_myhdl_010.all;

entity ShiftingDemo_TB_V_VHDL is
end entity ShiftingDemo_TB_V_VHDL;
-- myHDL -> verilog/VHDL testbench for `ShiftingDemo`

architecture MyHDL of ShiftingDemo_TB_V_VHDL is


signal LSRes: signed (14 downto 0) := 15X"0000";
signal ShiftVal: unsigned(3 downto 0) := 4X"0";
signal RSRes: signed (7 downto 0) := 8X"00";
signal ShiftingDemo0_0_RefVal: signed (7 downto 0);

begin


ShiftingDemo0_0_RefVal <= to_signed(-55, 8);


SHIFTINGDEMO_TB_V_VHDL_PRINT_DATA: process (ShiftVal, RSRes, LSRes) is
    variable L: line;
begin
    write(L, to_hstring(ShiftVal));
    write(L, string'(" "));
    write(L, to_hstring(unsigned(RSRes)));
    write(L, string'(" "));
    write(L, to_hstring(unsigned(LSRes)));
    writeline(output, L);
end process SHIFTINGDEMO_TB_V_VHDL_PRINT_DATA;


RSRes <= shift_right(ShiftingDemo0_0_RefVal, to_integer(ShiftVal));
LSRes <= shift_left(resize(ShiftingDemo0_0_RefVal, 15), to_integer(ShiftVal));

SHIFTINGDEMO_TB_V_VHDL_STIMULES: process is
begin
    for i in 0 to 8-1 loop
        ShiftVal <= to_unsigned(i, 4);
        wait for 1 * 1 ns;
    end loop;
    assert False report "End of Simulation" severity Failure;
    wait;
end process SHIFTINGDEMO_TB_V_VHDL_STIMULES;

end architecture MyHDL;

/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVHDL.py:453: ToVHDLWarning: Signal is not driven: ShiftingDemo0_0_RefVal
  category=ToVHDLWarning

myHDL concat behavior

The concat function is an abbreviated name for the full name of concatenation which is that action that this operator performs by joining the bits of all the signals that are arguments to it into a new concatenated single binary


In [35]:
RefVal=intbv(25)[6:]; RefVal, bin(RefVal, 6)


Out[35]:
(intbv(25), '011001')

In [36]:
Result=concat(True, RefVal); Result, bin(Result)


Out[36]:
(intbv(89), '1011001')

In [37]:
ResultSigned=concat(True, RefVal).signed(); ResultSigned, bin(ResultSigned)


Out[37]:
(intbv(-39), '1011001')

myHDL concat Demo


In [38]:
@block
def ConcatDemo(Res, ResS):
    """
    `concat` demo 
    Input:
        None
    Ouput:
        Res(7BitVec): concat result
        Res(7BitVec Signed): concat result that is signed
    """
    RefVal=Signal(intbv(25)[6:])
    @always_comb
    def logic():
        Res.next=concat(True, RefVal)
        ResS.next=concat(True, RefVal).signed()
    return instances()

myHDL Testing


In [39]:
Peeker.clear()
Res=Signal(intbv(0)[7:]); Peeker(Res, 'Res')
ResS=Signal(intbv(0)[7:].signed()); Peeker(ResS, ResS)

DUT=ConcatDemo(Res, ResS)

def ConcatDemo_TB():
    """
    myHDL only Testbench for `ConcatDemo`
    """
    @instance
    def stimules():
        for i in range(2):
            yield delay(1)
        
        raise StopSimulation()
    
    return instances()
sim=Simulation(DUT, ConcatDemo_TB(), *Peeker.instances()).run()

In [40]:
Peeker.to_wavedrom()


Verilog Conversion


In [41]:
DUT.convert()
VerilogTextReader('ConcatDemo');


***Verilog modual from ConcatDemo.v***

 // File: ConcatDemo.v
// Generated by MyHDL 0.10
// Date: Wed Aug 29 14:28:03 2018


`timescale 1ns/10ps

module ConcatDemo (
    Res,
    ResS
);
// `concat` demo 
// Input:
//     None
// Ouput:
//     Res(7BitVec): concat result
//     Res(7BitVec Signed): concat result that is signed

output [6:0] Res;
wire [6:0] Res;
output signed [6:0] ResS;
wire signed [6:0] ResS;

wire [5:0] RefVal;

assign RefVal = 6'd25;



assign Res = {1'b1, RefVal};
assign ResS = $signed({1'b1, RefVal});

endmodule

/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: RefVal
  category=ToVerilogWarning
\begin{figure} \centerline{\includegraphics[width=10cm]{ConcatDemo_v_RTL.png}} \caption{\label{fig:CDVRTL} ConcatDemo Verilog RTL schematic; Xilinx Vivado 2017.4} \end{figure}
\begin{figure} \centerline{\includegraphics[width=10cm]{ConcatDemo_v_SYN.png}} \caption{\label{fig:CDVSYN} ConcatDemo Verilog Synthesized Schematic; Xilinx Vivado 2017.4} \end{figure}

VHDL Conversion


In [42]:
DUT.convert('VHDL')
VHDLTextReader('ConcatDemo');


***VHDL modual from ConcatDemo.vhd***

 -- File: ConcatDemo.vhd
-- Generated by MyHDL 0.10
-- Date: Wed Aug 29 14:28:03 2018


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use std.textio.all;

use work.pck_myhdl_010.all;

entity ConcatDemo is
    port (
        Res: out unsigned(6 downto 0);
        ResS: out signed (6 downto 0)
    );
end entity ConcatDemo;
-- `concat` demo 
-- Input:
--     None
-- Ouput:
--     Res(7BitVec): concat result
--     Res(7BitVec Signed): concat result that is signed

architecture MyHDL of ConcatDemo is


signal RefVal: unsigned(5 downto 0);

begin


RefVal <= to_unsigned(25, 6);



Res <= unsigned'('1' & RefVal);
ResS <= signed(unsigned'('1' & RefVal));

end architecture MyHDL;

/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_VHDLNameValidation.py:39: ToVHDLWarning: Previously used name being reused: Res
  warnings.warn("Previously used name being reused: %s" % (name), category=ToVHDLWarning)
/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_VHDLNameValidation.py:39: ToVHDLWarning: Previously used name being reused: RefVal
  warnings.warn("Previously used name being reused: %s" % (name), category=ToVHDLWarning)
/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVHDL.py:453: ToVHDLWarning: Signal is not driven: RefVal
  category=ToVHDLWarning
\begin{figure} \centerline{\includegraphics[width=10cm]{ConcatDemo_vhd_RTL.png}} \caption{\label{fig:CDVHDRTL} {ConcatDemo VHDL RTL schematic; Xilinx Vivado 2017.4} \end{figure}
\begin{figure} \centerline{\includegraphics[width=10cm]{ConcatDemo_vhd_SYN.png}} \caption{\label{fig:CDVHDSYN} ConcatDemo VHDL Synthesized Schematic; Xilinx Vivado 2017.4} \end{figure}

myHDL to Verilog/VHDL Testbench


In [63]:
@block
def ConcatDemo_TB_V_VHDL():
    """
    myHDL-> Verilog/VHDL Testbench
    """

    Res=Signal(intbv(0)[7:])
    ResS=Signal(intbv(0)[7:].signed())

    @always_comb
    def print_data():
        print(Res, ResS)


    DUT=ConcatDemo(Res, ResS)

    @instance
    def stimules():
        for i in range(2):
            yield delay(1)
        
        raise StopSimulation()
    
    return instances()


TB=ConcatDemo_TB_V_VHDL()

Verilog Testbench


In [44]:
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('ConcatDemo_TB_V_VHDL');


<class 'myhdl._Signal._Signal'> <class '_ast.Name'>
<class 'myhdl._Signal._Signal'> <class '_ast.Name'>
***Verilog modual from ConcatDemo_TB_V_VHDL.v***

 // File: ConcatDemo_TB_V_VHDL.v
// Generated by MyHDL 0.10
// Date: Wed Aug 29 14:28:04 2018


`timescale 1ns/10ps

module ConcatDemo_TB_V_VHDL (

);



wire [6:0] Res;
wire signed [6:0] ResS;
wire [5:0] ConcatDemo0_0_RefVal;

assign ConcatDemo0_0_RefVal = 6'd25;


always @(ResS, Res) begin: CONCATDEMO_TB_V_VHDL_PRINT_DATA
    $write("%h", Res);
    $write(" ");
    $write("%h", ResS);
    $write("\n");
end



assign Res = {1'b1, ConcatDemo0_0_RefVal};
assign ResS = $signed({1'b1, ConcatDemo0_0_RefVal});


initial begin: CONCATDEMO_TB_V_VHDL_STIMULES
    integer i;
    for (i=0; i<2; i=i+1) begin
        # 1;
    end
    $finish;
end

endmodule

/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: ConcatDemo0_0_RefVal
  category=ToVerilogWarning

VHDL Testbench

VHDL Testbench Conversion Issue

This Testbench is not working in Vivado


In [45]:
TB.convert(hdl="VHDL", initial_values=True)
VHDLTextReader('ConcatDemo_TB_V_VHDL');


***VHDL modual from ConcatDemo_TB_V_VHDL.vhd***

 -- File: ConcatDemo_TB_V_VHDL.vhd
-- Generated by MyHDL 0.10
-- Date: Wed Aug 29 14:28:04 2018


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use std.textio.all;

use work.pck_myhdl_010.all;

entity ConcatDemo_TB_V_VHDL is
end entity ConcatDemo_TB_V_VHDL;


architecture MyHDL of ConcatDemo_TB_V_VHDL is


signal Res: unsigned(6 downto 0) := 7X"00";
signal ResS: signed (6 downto 0) := 7X"00";
signal ConcatDemo0_0_RefVal: unsigned(5 downto 0);

begin


ConcatDemo0_0_RefVal <= to_unsigned(25, 6);


CONCATDEMO_TB_V_VHDL_PRINT_DATA: process (ResS, Res) is
    variable L: line;
begin
    write(L, to_hstring(Res));
    write(L, string'(" "));
    write(L, to_hstring(unsigned(ResS)));
    writeline(output, L);
end process CONCATDEMO_TB_V_VHDL_PRINT_DATA;


Res <= unsigned'('1' & ConcatDemo0_0_RefVal);
ResS <= signed(unsigned'('1' & ConcatDemo0_0_RefVal));

CONCATDEMO_TB_V_VHDL_STIMULES: process is
begin
    for i in 0 to 2-1 loop
        wait for 1 * 1 ns;
    end loop;
    assert False report "End of Simulation" severity Failure;
    wait;
end process CONCATDEMO_TB_V_VHDL_STIMULES;

end architecture MyHDL;

/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVHDL.py:453: ToVHDLWarning: Signal is not driven: ConcatDemo0_0_RefVal
  category=ToVHDLWarning

myHDL Bitslicing Behavior

These example values come from the future work with floating point implemented in fixed point architecture which is incredibly important for Digital Signal Processing as will be shown. For now, just understand that the example are based on multiplying two Q4.4 (8bit fixed point) number resulting in Q8.8 (16bit fixed point) product

Slicing intbv

the following is an example of truncation from 16bit to 8bit rounding that shows how bit slicing works in myHDL. The truncation bit slicing keeps values from the far left (Most Significant Bit (MSB) ) to the rightmost specified bit (Least Significant Bit (LSB))


In [46]:
TV=intbv(1749)[16:]
print(f'int 1749 in bit is {bin(TV, len(TV))}')
for j in range(16):
    try:
        Trunc=TV[16:j]
        print(f'Binary: {bin(Trunc, len(Trunc))}, Bits: {len(Trunc)}, rep: {int(Trunc)}, MSB:15, LSB: {j}')
    except ValueError:
        print ('MSB {15} is <= LSB {j}')


int 1749 in bit is 0000011011010101
Binary: 0000011011010101, Bits: 16, rep: 1749, MSB:15, LSB: 0
Binary: 000001101101010, Bits: 15, rep: 874, MSB:15, LSB: 1
Binary: 00000110110101, Bits: 14, rep: 437, MSB:15, LSB: 2
Binary: 0000011011010, Bits: 13, rep: 218, MSB:15, LSB: 3
Binary: 000001101101, Bits: 12, rep: 109, MSB:15, LSB: 4
Binary: 00000110110, Bits: 11, rep: 54, MSB:15, LSB: 5
Binary: 0000011011, Bits: 10, rep: 27, MSB:15, LSB: 6
Binary: 000001101, Bits: 9, rep: 13, MSB:15, LSB: 7
Binary: 00000110, Bits: 8, rep: 6, MSB:15, LSB: 8
Binary: 0000011, Bits: 7, rep: 3, MSB:15, LSB: 9
Binary: 000001, Bits: 6, rep: 1, MSB:15, LSB: 10
Binary: 00000, Bits: 5, rep: 0, MSB:15, LSB: 11
Binary: 0000, Bits: 4, rep: 0, MSB:15, LSB: 12
Binary: 000, Bits: 3, rep: 0, MSB:15, LSB: 13
Binary: 00, Bits: 2, rep: 0, MSB:15, LSB: 14
Binary: 0, Bits: 1, rep: 0, MSB:15, LSB: 15

In [47]:
TV=intbv(1749)[16:]
print(f'int 1749 in bit is {bin(TV, len(TV))}')
for i in reversed(range(16+1)):
    try:
        Trunc=TV[i:0]
        print(f'Binary: {bin(Trunc, len(Trunc))}, Bits: {len(Trunc)}, rep: {int(Trunc)}, MSB:{i}, LSB: {0}')
    except ValueError:
        print ('MSB is <= LSB index')


int 1749 in bit is 0000011011010101
Binary: 0000011011010101, Bits: 16, rep: 1749, MSB:16, LSB: 0
Binary: 000011011010101, Bits: 15, rep: 1749, MSB:15, LSB: 0
Binary: 00011011010101, Bits: 14, rep: 1749, MSB:14, LSB: 0
Binary: 0011011010101, Bits: 13, rep: 1749, MSB:13, LSB: 0
Binary: 011011010101, Bits: 12, rep: 1749, MSB:12, LSB: 0
Binary: 11011010101, Bits: 11, rep: 1749, MSB:11, LSB: 0
Binary: 1011010101, Bits: 10, rep: 725, MSB:10, LSB: 0
Binary: 011010101, Bits: 9, rep: 213, MSB:9, LSB: 0
Binary: 11010101, Bits: 8, rep: 213, MSB:8, LSB: 0
Binary: 1010101, Bits: 7, rep: 85, MSB:7, LSB: 0
Binary: 010101, Bits: 6, rep: 21, MSB:6, LSB: 0
Binary: 10101, Bits: 5, rep: 21, MSB:5, LSB: 0
Binary: 0101, Bits: 4, rep: 5, MSB:4, LSB: 0
Binary: 101, Bits: 3, rep: 5, MSB:3, LSB: 0
Binary: 01, Bits: 2, rep: 1, MSB:2, LSB: 0
Binary: 1, Bits: 1, rep: 1, MSB:1, LSB: 0
MSB is <= LSB index

Slicing Signed intbv


In [48]:
TV=intbv(-1749)[16:].signed()
print(f'int -1749 in bit is {bin(TV, len(TV))}')
for j in range(16):
    try:
        Trunc=TV[16:j].signed()
        print(f'Binary: {bin(Trunc, len(Trunc))}, Bits: {len(Trunc)}, rep: {int(Trunc)}, MSB:15, LSB: {j}')
    except ValueError:
        print ('MSB {15} is <= LSB {j}')


int -1749 in bit is 1111100100101011
Binary: 1111100100101011, Bits: 16, rep: -1749, MSB:15, LSB: 0
Binary: 111110010010101, Bits: 15, rep: -875, MSB:15, LSB: 1
Binary: 11111001001010, Bits: 14, rep: -438, MSB:15, LSB: 2
Binary: 1111100100101, Bits: 13, rep: -219, MSB:15, LSB: 3
Binary: 111110010010, Bits: 12, rep: -110, MSB:15, LSB: 4
Binary: 11111001001, Bits: 11, rep: -55, MSB:15, LSB: 5
Binary: 1111100100, Bits: 10, rep: -28, MSB:15, LSB: 6
Binary: 111110010, Bits: 9, rep: -14, MSB:15, LSB: 7
Binary: 11111001, Bits: 8, rep: -7, MSB:15, LSB: 8
Binary: 1111100, Bits: 7, rep: -4, MSB:15, LSB: 9
Binary: 111110, Bits: 6, rep: -2, MSB:15, LSB: 10
Binary: 11111, Bits: 5, rep: -1, MSB:15, LSB: 11
Binary: 1111, Bits: 4, rep: -1, MSB:15, LSB: 12
Binary: 111, Bits: 3, rep: -1, MSB:15, LSB: 13
Binary: 11, Bits: 2, rep: -1, MSB:15, LSB: 14
Binary: 1, Bits: 1, rep: -1, MSB:15, LSB: 15

In [49]:
TV=intbv(-1749)[16:].signed()
print(f'int -1749 in bit is {bin(TV, len(TV))}')
for i in reversed(range(16+1)):
    try:
        Trunc=TV[i:0].signed()
        print(f'Binary: {bin(Trunc, len(Trunc))}, Bits: {len(Trunc)}, rep: {int(Trunc)}, MSB:{i}, LSB: {0}')
    except ValueError:
        print ('MSB is <= LSB index')


int -1749 in bit is 1111100100101011
Binary: 1111100100101011, Bits: 16, rep: -1749, MSB:16, LSB: 0
Binary: 111100100101011, Bits: 15, rep: -1749, MSB:15, LSB: 0
Binary: 11100100101011, Bits: 14, rep: -1749, MSB:14, LSB: 0
Binary: 1100100101011, Bits: 13, rep: -1749, MSB:13, LSB: 0
Binary: 100100101011, Bits: 12, rep: -1749, MSB:12, LSB: 0
Binary: 00100101011, Bits: 11, rep: 299, MSB:11, LSB: 0
Binary: 0100101011, Bits: 10, rep: 299, MSB:10, LSB: 0
Binary: 100101011, Bits: 9, rep: -213, MSB:9, LSB: 0
Binary: 00101011, Bits: 8, rep: 43, MSB:8, LSB: 0
Binary: 0101011, Bits: 7, rep: 43, MSB:7, LSB: 0
Binary: 101011, Bits: 6, rep: -21, MSB:6, LSB: 0
Binary: 01011, Bits: 5, rep: 11, MSB:5, LSB: 0
Binary: 1011, Bits: 4, rep: -5, MSB:4, LSB: 0
Binary: 011, Bits: 3, rep: 3, MSB:3, LSB: 0
Binary: 11, Bits: 2, rep: -1, MSB:2, LSB: 0
Binary: 1, Bits: 1, rep: -1, MSB:1, LSB: 0
MSB is <= LSB index

Slicing modbv


In [50]:
TV=modbv(1749)[16:]
print(f'int 1749 in bit is {bin(TV, len(TV))}')
for j in range(16):
    try:
        Trunc=TV[16:j]
        print(f'Binary: {bin(Trunc, len(Trunc))}, Bits: {len(Trunc)}, rep: {int(Trunc)}, MSB:15, LSB: {j}')
    except ValueError:
        print ('MSB {15} is <= LSB {j}')


int 1749 in bit is 0000011011010101
Binary: 0000011011010101, Bits: 16, rep: 1749, MSB:15, LSB: 0
Binary: 000001101101010, Bits: 15, rep: 874, MSB:15, LSB: 1
Binary: 00000110110101, Bits: 14, rep: 437, MSB:15, LSB: 2
Binary: 0000011011010, Bits: 13, rep: 218, MSB:15, LSB: 3
Binary: 000001101101, Bits: 12, rep: 109, MSB:15, LSB: 4
Binary: 00000110110, Bits: 11, rep: 54, MSB:15, LSB: 5
Binary: 0000011011, Bits: 10, rep: 27, MSB:15, LSB: 6
Binary: 000001101, Bits: 9, rep: 13, MSB:15, LSB: 7
Binary: 00000110, Bits: 8, rep: 6, MSB:15, LSB: 8
Binary: 0000011, Bits: 7, rep: 3, MSB:15, LSB: 9
Binary: 000001, Bits: 6, rep: 1, MSB:15, LSB: 10
Binary: 00000, Bits: 5, rep: 0, MSB:15, LSB: 11
Binary: 0000, Bits: 4, rep: 0, MSB:15, LSB: 12
Binary: 000, Bits: 3, rep: 0, MSB:15, LSB: 13
Binary: 00, Bits: 2, rep: 0, MSB:15, LSB: 14
Binary: 0, Bits: 1, rep: 0, MSB:15, LSB: 15

In [51]:
TV=modbv(1749)[16:]
print(f'int 1749 in bit is {bin(TV, len(TV))}')

for i in reversed(range(16+1)):
    try:
        Trunc=TV[i:0]
        print(f'Binary: {bin(Trunc, len(Trunc))}, Bits: {len(Trunc)}, rep: {int(Trunc)}, MSB:{i}, LSB: {0}')
    except ValueError:
        print ('MSB is <= LSB index')


int 1749 in bit is 0000011011010101
Binary: 0000011011010101, Bits: 16, rep: 1749, MSB:16, LSB: 0
Binary: 000011011010101, Bits: 15, rep: 1749, MSB:15, LSB: 0
Binary: 00011011010101, Bits: 14, rep: 1749, MSB:14, LSB: 0
Binary: 0011011010101, Bits: 13, rep: 1749, MSB:13, LSB: 0
Binary: 011011010101, Bits: 12, rep: 1749, MSB:12, LSB: 0
Binary: 11011010101, Bits: 11, rep: 1749, MSB:11, LSB: 0
Binary: 1011010101, Bits: 10, rep: 725, MSB:10, LSB: 0
Binary: 011010101, Bits: 9, rep: 213, MSB:9, LSB: 0
Binary: 11010101, Bits: 8, rep: 213, MSB:8, LSB: 0
Binary: 1010101, Bits: 7, rep: 85, MSB:7, LSB: 0
Binary: 010101, Bits: 6, rep: 21, MSB:6, LSB: 0
Binary: 10101, Bits: 5, rep: 21, MSB:5, LSB: 0
Binary: 0101, Bits: 4, rep: 5, MSB:4, LSB: 0
Binary: 101, Bits: 3, rep: 5, MSB:3, LSB: 0
Binary: 01, Bits: 2, rep: 1, MSB:2, LSB: 0
Binary: 1, Bits: 1, rep: 1, MSB:1, LSB: 0
MSB is <= LSB index

myHDL BitSlicing Demo Module


In [52]:
@block
def BitSlicingDemo(MSB, LSB, Res):
    """
    Demenstration Module for Bit Slicing in myHDL
    
    Inputs:
        MSB (5BitVec): Most Signficant Bit Index Must be > LSB, 
            ex: if LSB==0 MSB must range between 1 and 15
        LSB (5BitVec): Lest Signficant Bit Index Must be < MSB
            ex: if MSB==15 LSB must range beteen 0 and 15
    
    Outputs:
        Res(16BitVec Signed): Result of the slicing operation from
        Refrance Vales (hard coded in module) -1749 (16BitVec Signed)
        
    
    """
    RefVal=Signal(intbv(-1749)[16:].signed())
    @always_comb
    def logic():
        Res.next=RefVal[MSB:LSB].signed()
    return instances()

myHDL Testing


In [53]:
Peeker.clear()
MSB=Signal(intbv(16)[5:]); Peeker(MSB, 'MSB')
LSB=Signal(intbv(0)[5:]); Peeker(LSB, 'LSB')
Res=Signal(intbv(0)[16:].signed()); Peeker(Res, 'Res')

DUT=BitSlicingDemo(MSB, LSB, Res)

def BitslicingDemo_TB():
    """
    myHDL only Testbench for `BitSlicingDemo`
    """
    @instance
    def stimules():
        
        for j in range(15):
            MSB.next=16
            LSB.next=j
            yield delay(1)
        
        for i in reversed(range(1, 16)):
            MSB.next=i
            LSB.next=0
            yield delay(1)
        
        raise StopSimulation()
    return instances()
            
        
sim=Simulation(DUT, BitslicingDemo_TB(), *Peeker.instances()).run()

In [54]:
Peeker.to_wavedrom('MSB', 'LSB', 'Res')



In [55]:
Peeker.to_dataframe()[['MSB', 'LSB', 'Res']]


Out[55]:
MSB LSB Res
0 16 0 -1749
1 16 1 -875
2 16 2 -438
3 16 3 -219
4 16 4 -110
5 16 5 -55
6 16 6 -28
7 16 7 -14
8 16 8 -7
9 16 9 -4
10 16 10 -2
11 16 11 -1
12 16 12 -1
13 16 13 -1
14 16 14 -1
15 15 0 -1749
16 14 0 -1749
17 13 0 -1749
18 12 0 -1749
19 11 0 299
20 10 0 299
21 9 0 -213
22 8 0 43
23 7 0 43
24 6 0 -21
25 5 0 11
26 4 0 -5
27 3 0 3
28 2 0 -1
29 1 0 -1

Verilog Conversion

Verilog Conversion Issue

The following is unsynthesizable since Verilog requires that the indexes in bit slicing (aka Part-selects) be constant values. Along with the error in assign RefVal = 16'd-1749;

However, the generated Verilog code from BitSlicingDemo does hold merit in showing how the index values are mapped from myHDL to Verilog


In [56]:
DUT.convert()
VerilogTextReader('BitSlicingDemo');


***Verilog modual from BitSlicingDemo.v***

 // File: BitSlicingDemo.v
// Generated by MyHDL 0.10
// Date: Wed Aug 29 14:28:06 2018


`timescale 1ns/10ps

module BitSlicingDemo (
    MSB,
    LSB,
    Res
);
// Demenstration Module for Bit Slicing in myHDL
// 
// Inputs:
//     MSB (5BitVec): Most Signficant Bit Index Must be > LSB, 
//         ex: if LSB==0 MSB must range between 1 and 15
//     LSB (5BitVec): Lest Signficant Bit Index Must be < MSB
//         ex: if MSB==15 LSB must range beteen 0 and 15
// 
// Outputs:
//     Res(16BitVec Signed): Result of the slicing operation from
//     Refrance Vales (hard coded in module) -1749 (16BitVec Signed)
//     

input [4:0] MSB;
input [4:0] LSB;
output signed [15:0] Res;
wire signed [15:0] Res;

wire [15:0] RefVal;

assign RefVal = 16'd-1749;



assign Res = $signed(RefVal[MSB-1:LSB]);

endmodule

/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: RefVal
  category=ToVerilogWarning

VHDL Conversion

VHDL Conversion Issue

The following is unsynthesizable since VHDL requires that the indexes in bit slicing (aka Part-selects) be constant values.

However, the generated VHDL code from BitSlicingDemo does hold merit in showing how the index values are mapped from myHDL to VHDL


In [57]:
DUT.convert(hdl='VHDL')
VHDLTextReader('BitSlicingDemo');


***VHDL modual from BitSlicingDemo.vhd***

 -- File: BitSlicingDemo.vhd
-- Generated by MyHDL 0.10
-- Date: Wed Aug 29 14:28:06 2018


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use std.textio.all;

use work.pck_myhdl_010.all;

entity BitSlicingDemo is
    port (
        MSB: in unsigned(4 downto 0);
        LSB: in unsigned(4 downto 0);
        Res: out signed (15 downto 0)
    );
end entity BitSlicingDemo;
-- Demenstration Module for Bit Slicing in myHDL
-- 
-- Inputs:
--     MSB (5BitVec): Most Signficant Bit Index Must be > LSB, 
--         ex: if LSB==0 MSB must range between 1 and 15
--     LSB (5BitVec): Lest Signficant Bit Index Must be < MSB
--         ex: if MSB==15 LSB must range beteen 0 and 15
-- 
-- Outputs:
--     Res(16BitVec Signed): Result of the slicing operation from
--     Refrance Vales (hard coded in module) -1749 (16BitVec Signed)
--     

architecture MyHDL of BitSlicingDemo is


signal RefVal: signed (15 downto 0);

begin


RefVal <= to_signed(-1749, 16);



Res <= signed(unsigned(RefVal(to_integer(MSB)-1 downto to_integer(LSB))));

end architecture MyHDL;

/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_VHDLNameValidation.py:39: ToVHDLWarning: Previously used name being reused: Res
  warnings.warn("Previously used name being reused: %s" % (name), category=ToVHDLWarning)
/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_VHDLNameValidation.py:39: ToVHDLWarning: Previously used name being reused: RefVal
  warnings.warn("Previously used name being reused: %s" % (name), category=ToVHDLWarning)
/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVHDL.py:453: ToVHDLWarning: Signal is not driven: RefVal
  category=ToVHDLWarning

myHDL to Verilog/VHDL Testbench


In [58]:
@block
def BitslicingDemo_TB_V_VHDL():
    """
    myHDL -> Verilog/VHDL Testbench for `BitSlicingDemo`
    """

    MSB=Signal(intbv(16)[5:])
    LSB=Signal(intbv(0)[5:])
    Res=Signal(intbv(0)[16:].signed())
    
    @always_comb
    def print_data():
        print(MSB, LSB, Res)

    DUT=BitSlicingDemo(MSB, LSB, Res)

    @instance
    def stimules():
        
        for j in range(15):
            MSB.next=16
            LSB.next=j
            yield delay(1)
        
        #!!! reversed is not being converted
        #for i in reversed(range(1, 16)):
        #    MSB.next=i
        #    LSB.next=0
        #    yield delay(1)
        
        raise StopSimulation()
    return instances()
            
        
TB=BitslicingDemo_TB_V_VHDL()

Verilog Testbench


In [59]:
TB.convert(hdl="Verilog", initial_values=True)
VerilogTextReader('BitslicingDemo_TB_V_VHDL');


<class 'myhdl._Signal._Signal'> <class '_ast.Name'>
<class 'myhdl._Signal._Signal'> <class '_ast.Name'>
<class 'myhdl._Signal._Signal'> <class '_ast.Name'>
***Verilog modual from BitslicingDemo_TB_V_VHDL.v***

 // File: BitslicingDemo_TB_V_VHDL.v
// Generated by MyHDL 0.10
// Date: Wed Aug 29 14:28:07 2018


`timescale 1ns/10ps

module BitslicingDemo_TB_V_VHDL (

);
// myHDL -> Verilog/VHDL Testbench for `BitSlicingDemo`


wire signed [15:0] Res;
reg [4:0] MSB = 16;
reg [4:0] LSB = 0;
wire [15:0] BitSlicingDemo0_0_RefVal;

assign BitSlicingDemo0_0_RefVal = 16'd-1749;


always @(LSB, MSB, Res) begin: BITSLICINGDEMO_TB_V_VHDL_PRINT_DATA
    $write("%h", MSB);
    $write(" ");
    $write("%h", LSB);
    $write(" ");
    $write("%h", Res);
    $write("\n");
end



assign Res = $signed(BitSlicingDemo0_0_RefVal[MSB-1:LSB]);


initial begin: BITSLICINGDEMO_TB_V_VHDL_STIMULES
    integer j;
    for (j=0; j<15; j=j+1) begin
        MSB <= 16;
        LSB <= j;
        # 1;
    end
    $finish;
end

endmodule

/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVerilog.py:349: ToVerilogWarning: Signal is not driven: BitSlicingDemo0_0_RefVal
  category=ToVerilogWarning

VHDL Testbench


In [60]:
TB.convert(hdl="VHDL", initial_values=True)
VHDLTextReader('BitslicingDemo_TB_V_VHDL');


***VHDL modual from BitslicingDemo_TB_V_VHDL.vhd***

 -- File: BitslicingDemo_TB_V_VHDL.vhd
-- Generated by MyHDL 0.10
-- Date: Wed Aug 29 14:28:07 2018


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use std.textio.all;

use work.pck_myhdl_010.all;

entity BitslicingDemo_TB_V_VHDL is
end entity BitslicingDemo_TB_V_VHDL;
-- myHDL -> Verilog/VHDL Testbench for `BitSlicingDemo`

architecture MyHDL of BitslicingDemo_TB_V_VHDL is


signal Res: signed (15 downto 0) := 16X"0000";
signal MSB: unsigned(4 downto 0) := 5X"10";
signal LSB: unsigned(4 downto 0) := 5X"00";
signal BitSlicingDemo0_0_RefVal: signed (15 downto 0);

begin


BitSlicingDemo0_0_RefVal <= to_signed(-1749, 16);


BITSLICINGDEMO_TB_V_VHDL_PRINT_DATA: process (LSB, MSB, Res) is
    variable L: line;
begin
    write(L, to_hstring(MSB));
    write(L, string'(" "));
    write(L, to_hstring(LSB));
    write(L, string'(" "));
    write(L, to_hstring(unsigned(Res)));
    writeline(output, L);
end process BITSLICINGDEMO_TB_V_VHDL_PRINT_DATA;


Res <= signed(unsigned(BitSlicingDemo0_0_RefVal(to_integer(MSB)-1 downto to_integer(LSB))));

BITSLICINGDEMO_TB_V_VHDL_STIMULES: process is
begin
    for j in 0 to 15-1 loop
        MSB <= to_unsigned(16, 5);
        LSB <= to_unsigned(j, 5);
        wait for 1 * 1 ns;
    end loop;
    assert False report "End of Simulation" severity Failure;
    wait;
end process BITSLICINGDEMO_TB_V_VHDL_STIMULES;

end architecture MyHDL;

/home/iridium/anaconda3/lib/python3.6/site-packages/myhdl/conversion/_toVHDL.py:453: ToVHDLWarning: Signal is not driven: BitSlicingDemo0_0_RefVal
  category=ToVHDLWarning

In [ ]: