Verilog width expansion and reduction operator equivalence?


I’m using MyHDL on some of my small projects, and I want to implement some simple functions using width expansion and reduced unary operator, like following snippets as in verilog:

// svalid: 1-bit; en, dready: 4-bit
// width expansion
assign dvalid = {NUM_W{svalid}} & en;

//  reduced or
assign sready = | (dready & en)

But i dont have a clue how to code them using MyHDL.
Could somebody give me a hint on that ?



There will a few different opinions on your question.
IMHO you are swapping the cart and the horse. Obviously you know Verilog quite well (I don’t …) and you are asking whether there is an equivalent way to write this in MyHDL. The idea behind MyHDL is that we write standard Python to simulate (first) and convert (second) to an intermediate representation, at the time VHDL or Verilog.
The question becomes: do we have a Python construct that later in conversion can come out in the desired format(s)?
The way I would (currently do) write this:

from myhdl import Signal, intbv, block, always_comb

def vwe(svalid, en, dready, sready, dvalid):

    def assign():
        for i in range(len(en)):
  [i] = svalid and en[i] = 1 if (dready & en) else 0

    return assign

if __name__ == '__main__':

    def convert():
        en, dready, dvalid = [Signal(intbv(0)[4:]) for _ in range(3)]
        sready, svalid = [Signal(bool(0)) for _ in range(2)]

        dfc = vwe(svalid, en, dready, sready, dvalid)


produces this Verilog:

// File: vwe.v
// Generated by MyHDL 0.10
// Date: Sat Oct  6 11:50:18 2018

`timescale 1ns/10ps

module vwe (

	input svalid;
	input [3:0] en;
	input [3:0] dready;
	output sready;
	reg sready;
	output [3:0] dvalid;
	reg [3:0] dvalid;

	always @(en, svalid, dready) begin: VWE_ASSIGN
		integer i;
		for (i=0; i<4; i=i+1) begin
			dvalid[i] = (svalid && en[i]);
		sready = (dready & en) ? 1 : 0;


Which will work fine, but alas doesn’t have the conciseness of the Verilog code you presented.

Ideally you want to write something like:

def vwe(svalid, en, dready, sready, dvalid):

    def assign():[i] = bitextend(svalid, NUM_W) and en[i] = 1 if (dready & en) else 0

    return assign

Assuming we have the function bitextend defined (as a built-in?) to do what it needs to do, this code will simulate fine. It does convert fine too, but instead of the targeted Verilog construct it will include a function.

function [4-1:0] MYHDL2_bitextend;
    input [1-1:0] b;
    input w;
    integer w;
    reg [4-1:0] r;
    integer i;
    r = 4'h0;
    for (i=0; i<w; i=i+1) begin
        r[i] = b;
    MYHDL2_bitextend = r;
    disable MYHDL5_RETURN;

assign dvalid = (MYHDL2_bitextend(svalid, 4) & en);
assign sready = (dready & en) ? 1 : 0;


Now we could make the converter(s?) smarter and if we define a number of functions as built-in we could have the converter recognise them and implement the appropriate construct.
But I am sure that there are other priorities to extend MyHDL.
@cfelton, @hgomersall, and others … Your ideas?


@josyb captured the gist. Furthermore, since the reduction is only combinatorial logic you can write a function for this operation: reduce_and(bitvector: intbv), reduce_or(bitvector: intbv). If you do this the Python gods will be quite pleased as your code readability has improved immensely :smile:.

This is the scenario us VHDL’ers (although it has been years since I have done serious VHDL) have always been in. In my opinion the functions gives you more options, example you can add a warning if you are reducing too many bits.