In NVIDIA Deep Learning Accelerator, a python script epython is used. Source code address: https://github.com/nvdla/hw/blob/master/tools/bin/epython . The full name of ephon is embedded python utility, which is simply used to preprocess python scripts embedded in verilog files. Using the simplicity of python syntax, we can automatically generate some repetitive and regular code.
Raise questions
When we write Verilog code, the state machine code is generally defined by parameter, as follows:
localparam IDLE = 3'd0; localparam START = 3'd1; ... localparam START = 3'd7;
If you need to insert a new state in the middle, you may need to modify both parts. One is that the bit width may be increased by 1, and the other is that all the States after the new insertion need to be increased by 1.
Binary, decimal and hexadecimal, which can be recoded by Vim or Emacs column editing, data filling and formatting. It would be a lot of trouble if it was gray code or single hot code.
So is there a simpler way?
An application of epython
We know that python can embed python script in verilog, so we can write a script to do this.
Suppose we have several States, which are described by python's list:
st = ['IDLE', 'START', 'NEW', 'DO_SOMETHING', 'DONE']
Can we automatically generate the definition of localparam based on this list? Our goal is to look like this:
st = ['IDLE', 'START', 'NEW', 'DO_SOMETHING', 'DONE'] stat_gen()
My method steps are as follows:
1. Calculate the list length, that is, the number of States
2. Calculate the bit width of the state code, log2(stat_num), and then round it up
3. Convert 0,..., stat_num-1 to binary, decimal, hexadecimal, gray, onehot, etc
4. Format output
Isn't it simple?
For the simplicity of embedding python in verilog, I put the main implementation process in python module, and then import it. The final handwritten verilog code is as follows:
//:| import vloglib //:| //:| st = ['IDLE', 'FULL', 'WIN', 'PROT', 'WR_FULL', 'WR_WIN'] //:| vloglib.stat_gen(st, 'bin') //:| //:) epython: generated_beg //:) epython: generated_end
After executing ephon, it is as follows:
//:| import vloglib //:| //:| st = ['IDLE', 'START', 'NEW', 'DO_SOMETHING', 'DONE'] //:| vloglib.stat_gen(st, 'bin') //:| //:) epython: generated_beg (DO NOT EDIT BELOW) localparam IDLE = 3'b000; localparam START = 3'b001; localparam NEW = 3'b010; localparam DO_SOMETHING = 3'b011; localparam DONE = 3'b100; //:) epython: generated_end (DO NOT EDIT ABOVE)
The effect of gray code is as follows:
//:| import vloglib //:| //:| st = ['IDLE', 'START', 'NEW', 'DO_SOMETHING', 'DONE'] //:| vloglib.stat_gen(st, 'gray') //:| //:) epython: generated_beg (DO NOT EDIT BELOW) localparam IDLE = 3'b000; localparam START = 3'b001; localparam NEW = 3'b011; localparam DO_SOMETHING = 3'b010; localparam DONE = 3'b110; //:) epython: generated_end (DO NOT EDIT ABOVE)
The effect of single hot code is as follows:
//:| import vloglib //:| //:| st = ['IDLE', 'START', 'NEW', 'DO_SOMETHING', 'DONE'] //:| vloglib.stat_gen(st, 'onehot') //:| //:) epython: generated_beg (DO NOT EDIT BELOW) localparam IDLE = 5'b00001; localparam START = 5'b00010; localparam NEW = 5'b00100; localparam DO_SOMETHING = 5'b01000; localparam DONE = 5'b10000; //:) epython: generated_end (DO NOT EDIT ABOVE)
Is the effect OK?
vloglib.py code analysis
The code is as follows:
import os import sys import re import math import bin2gray2bin def stat_gen(l_stat, code='dec'): #calc bit width stat_num = len(l_stat) bit_width = math.ceil(math.log2(stat_num)) #get the max lenght of strings in list l = [len(i) for i in l_stat] maxlenth = max(l) #print verilog code for i in range(len(l_stat)): n = ' localparam {}'.format(l_stat[i]).ljust(13 + maxlenth) c = '' if code == 'bin': t = '{:b}'.format(i) t = t.rjust(bit_width, '0') c = ' = {}\'b{};'.format(bit_width, t) elif code == 'dec': c = ' = {}\'d{};'.format(bit_width, i) elif code == 'hex': t = '{:x}'.format(i) t = t.rjust(math.ceil(bit_width/4), '0') c = ' = {}\'h{};'.format(bit_width, t) elif code == 'gray': t = '{:b}'.format(i) t = t.rjust(bit_width, '0') t = bin2gray2bin.bin2gray(t, bit_width) c = ' = {}\'b{};'.format(bit_width, t) elif code == 'onehot': if i == 0: t = '0' * (stat_num - 1) + '1' else: t = t[1:] + '0' c = ' = {}\'b{};'.format(stat_num, t) print(n + c)
Main points:
-
Math is a math library, which uses two functions log2() and ceil() to calculate the bit width
-
ljust(len) of string is the specified width len, which is left aligned. If it is insufficient, it is filled with spaces. Len is determined by the maximum length of the status string.
-
2, X. hexadecimal can be formatted with sting.format(), then right aligned with rjust(len), and filled with '0'
-
Gray code calls a third-party library bin2gray2bin
-
Single hot code uses string sequence splicing to achieve the effect of left shift
Source download
Download address:
https://github.com/chenfengrugao/vloglib
perhaps
git clone https://github.com/chenfengrugao/vloglib.git
ExASIC Published 6 original articles, won praise 11, visited 149 Private letter follow