## basic parameterized multiplex and demultiplex

core
Posts: 9
Joined: April 5th, 2013, 3:00 pm

### basic parameterized multiplex and demultiplex

In my web searching I found it painful to find a basic parameterized mux and demux module. The web is like the wild west full of partial examples. Here is what I finally came up with merging multiple suggestions and I think using names that make it more self documenting. I did not figure out the main code myself. I basically wanted to apply the software engineering Don't Repeat Yourself principle. Any time you repeat code or magic numbers where you should have defined a constant (e.g. a bit width or special value) it is more error prone. You may get bitten later when you fix a bug in one place but not others or your design changes slightly.
• first you want to start a place for utility functions... even if it is only this one. "util.v"

Code: Select all

``````//////////////////////////////////////////////////////////////////////////////////
// utility functions
//////////////////////////////////////////////////////////////////////////////////

// ceiling of log2.
// (e.g. useful for calculating how many select lines are needed both internal to
// a mux or demux and for any module interfacing to that mux)
function integer clog2 (input integer n);
integer j;
begin
n = n - 1;
for (j = 0; n > 0; j = j + 1)
n = n >> 1;
clog2 = j;
end
endfunction
``````
• next here are demux and mux whcih I have in "common.v"

Code: Select all

``````module demux (in, select, out);
`include "util.v"
parameter W_DATA = 1;
parameter N_SELECT = 2;
localparam W_SELECT = clog2(N_SELECT);
input [W_DATA-1:0] in;
input [W_SELECT-1:0] select;
output [N_SELECT*W_DATA-1:0] out;

genvar i;
generate
for (i = 0; i < N_SELECT; i = i + 1) begin : demux_out
assign out[(i*W_DATA)+:W_DATA] = (select == i) ? in : {W_DATA{1'b0}};
end
endgenerate

endmodule

module mux (in, select, out);
`include "util.v"
parameter W_DATA = 1;
parameter N_SELECT = 2;
localparam W_SELECT = clog2(N_SELECT);
input [N_SELECT*W_DATA-1:0] in;
input [W_SELECT-1:0] select;
output [W_DATA-1:0] out;

wire [W_DATA-1:0] channels[0:N_SELECT-1];

assign out = channels[select];

genvar i;
generate
for (i = 0; i < N_SELECT; i = i + 1) begin : mux_out
assign channels[i] = in[(i*W_DATA)+:W_DATA];
end
endgenerate

endmodule
``````
• finally here is a top level test usage which just does demux and connects it back to a mux. It won't do anything on your Mojo, but you can play around with it in the simulator. "test_mux_demux.v"

Code: Select all

``````//////////////////////////////////////////////////////////////////////////////////
// just a text for demux / mux
//////////////////////////////////////////////////////////////////////////////////
module test_mux(clk, rst, in, out);
`include "util.v"
parameter W_DATA = 2;
localparam N_SELECT = 6;
localparam W_SELECT = clog2(N_SELECT);
input clk, rst;
input [W_DATA-1:0] in;
output [W_DATA-1:0] out;

wire [N_SELECT*W_DATA-1:0] bus1;
wire [W_DATA-1:0] bus2;

reg [W_DATA-1:0] in_h, out_h;
reg [W_SELECT-1:0] select_d, select_q;

assign out = out_h;

demux #(.W_DATA(W_DATA), .N_SELECT(N_SELECT)) demux1 (.in(in_h), .select(select_q), .out(bus1));
mux #(.W_DATA(W_DATA), .N_SELECT(N_SELECT)) mux1 (.in(bus1), .select(select_q), .out(bus2));

always @(select_q) begin
assign select_d = (select_q < N_SELECT -1) ? select_q + 1 : {W_SELECT{1'b0}};
end

always @(posedge clk) begin
if (rst) begin
select_q <= {W_SELECT{1'b0}};
end else begin
select_q <= select_d;
end
in_h <= in;
out_h <= bus2;
end

endmodule
``````
DISCLAIMER: I've tested this in the simulator with my limited beginner skill, not with a good representative test set. Understanding how to use the simulator better is on my to do list. PLEASE test it yourself also.