Problem: want a clean way to assign a mux (ie without process syntax overhead). One consequence for example is that process requires things to be marked as “reg” that are conceptually a wire.

This page lists a bunch of different styles to write a mux to explore the synatic advantages of each. I would like an explicit and an implicit syntax depending on what mood I'm in

Based on experiments, use one of the following two based on your preferences:

What I want (explicit)

Something like:

wire o;         //Output
wire d0;        //Data to mux
wire d1;        //Data to mux
wire d2;        //Data to mux
wire d3;        //Data to mux
wire [1:0] sel; //Mux selector

assign o = case (sel)
    2'h0:       d0;
    2'h1:       d1;
    2'h2:       d2;
    2'h3:       d3;
    default:    1'bx;
    endcase

VHDL has an equivilent syntax IIRC. Key things:

  • Mux selector is only specified once
  • Values are explicit
  • Syntax is compact
  • Does not create any extra nets

What I want (implicit)

Something like:

wire o;         //Output
wire d0;        //Data to mux
wire d1;        //Data to mux
wire d2;        //Data to mux
wire d3;        //Data to mux
wire [1:0] sel; //Mux selector

assign o = {d3, d2, d1, d0}[sel];

but xst doesn't like this:

ERROR:HDLCompiler:745 - "/home/johnm/document/external/xtest/mux/src/project_top.v" Line 12: Range index value is not constant

and iSim was even less happy:

Compiling module mux_tb
FATAL_ERROR:Simulator:CompilerAssert.h:40:1.51 - Internal Compiler Error in file ../src/VlogExpr.cpp at line 3735   For technical support on this issue, please visit http://www.xilinx.com/support.
FATAL_ERROR:Simulator:CompilerAssert.h:40:1.51 - Internal Compiler Error in file ../src/VlogExpr.cpp at line 3735   For technical support on this issue, please visit http://www.xilinx.com/support.

Even if it did, works for single bit values but not multibit. Bit slice?

Anyway, assuming it did…

Advantages

  • Very compact syntax
  • Mux selector var is only written once
  • Will not create priority logic

Disadvantages

  • Only works if your input is already indexable
  • Only works for linear key to value relationship (ie mux value 0 corresponds to index 0)

A slight variation, however, does seem to work (xst 14.5):

wire o;         //Output
wire d0;        //Data to mux
wire d1;        //Data to mux
wire d2;        //Data to mux
wire d3;        //Data to mux
wire [1:0] sel; //Mux selector

assign o = |({d3, d2, d1, d0} & 1 << sel);

That is, concatenate a bit array and mask one of the bits, checking if its set. I'm unclear if this would result in an efficiency hit.

Process case

reg o;          //Output
wire d0;        //Data to mux
wire d1;        //Data to mux
wire d2;        //Data to mux
wire d3;        //Data to mux
wire [1:0] sel; //Mux selector

always @(*) begin
    case (sel)
    2'h0:       o = d0;
    2'h1:       o = d1;
    2'h2:       o = d2;
    2'h3:       o = d3;
    default:    o = 1'bx;
    endcase
end

Advantages

  • Very explicit
  • Mux selector var is only written once
  • Arbitrary index to value
  • Possible but unlikely to create priority logic

Disadvantages

  • High syntax overhead
  • May require changing output to reg instead of natural wire

Intermediate array

XXX: this won't work because of non-constant index

The first was nice but it requires an array. Why not make a temporary intermediate array and index into it?

reg o;          //Output
wire d0;        //Data to mux
wire d1;        //Data to mux
wire d2;        //Data to mux
wire d3;        //Data to mux
wire [1:0] sel; //Mux selector

wire [3:0] o_mux = {
        d0,     //0
        d1,     //1
        d2,     //2
        d3};    //3
assign o = o_mux[sel];

Advantages

  • Mux selector var is only written once
  • Arbitrary index to value
  • No chance of creating priority logic

Disadvantages

  • Requires creating intermediate net

Chained ternary

wire o;         //Output
wire d0;        //Data to mux
wire d1;        //Data to mux
wire d2;        //Data to mux
wire d3;        //Data to mux
wire [1:0] sel; //Mux selector

assign o =  sel == 0 ?   d0:
            sel == 1 ?   d1: 
            sel == 2 ?   d2:
                         d3;

Advantages

  • No intermediate nets
  • Explicit
  • Arbitrary index to value

Disadvantages

  • Mux selector var is written for each case
  • Can lead to priority logic (ex: mixing variable to compare against)
 
verlog/mux.txt · Last modified: 2015/03/31 19:10 by mcmaster-guest
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution 4.0 International
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki