- 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
basic parameterized multiplex and demultiplex
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.