# Modeling Multiplexers

Modeling multiplexer represent a challenge in that they combine both discrete and continuous behaviors in an analog model. The discrete signals require the used of transition functions to smooth the discontinuities, whereas the continuous signals cannot pass through a transition function. There is a bit of a trick to combining these two that is demonstrated in this tutorial. The trick is not difficult, but it can be hard to come up with on your own. So if you like puzzles, you might want to stop reading now and see if you can come up with it on your own.

You should read Introduction to Verilog-A and Functional Modeling before this tutorial.

A Verilog-AMS model for a 4-channel mux can be implemented as follows:

```
module(out, in, sel);
output out; electrical out;
input [3:0] in; electrical [3:0] in;
input [3:0] sel; logic [3:0] sel;
analog begin
@(sel)
;
V(out) <+ V(in[0])*transition(sel === 0, 0, 100n);
V(out) <+ V(in[1])*transition(sel === 1, 0, 100n);
V(out) <+ V(in[2])*transition(sel === 2, 0, 100n);
V(out) <+ V(in[3])*transition(sel === 3, 0, 100n);
end
endmodule
```

Notice that the input voltages are outside the *transition* function, as
expected. Multiple contributions are made to *V(out)*, which accumulate. Each
input is multiplied by either 0 or 1 before accumulating with all inputs but one
being multiplied by 0. So if *sel=2* then the output will be ```
Vin[0]*0
+ Vin[1]*0 + Vin[2]*1 + Vin[3]*0
```

, which equals just `Vin[2]`

. The
transitions between 0 and 1 are smoothed by the *transition* filters. The event
statement is used to synchronize the kernels. Specifically, it causes the
continuous kernel to place a time point whenever there is a change to *sel*.

Unfortunately, this model is not accepted by Cadence’s simulator. For reasons
I have never understood, Cadence has severe restrictions on what can be used as
an analog event. Specifically, digital signals must be preceded by either
`posedge`

or `negedge`

in analog event expression. With Cadence’s
simulator, you can use the following:

```
module(out, in, sel);
output out; electrical out;
input [3:0] in; electrical [3:0] in;
input [3:0] sel; logic [3:0] sel;
reg sync = 0;
always @(sel) sync <= !sync;
analog begin
@(posedge sync or negedge sync)
;
V(out) <+ V(in[0])*transition(sel === 0, 0, 100n);
V(out) <+ V(in[1])*transition(sel === 1, 0, 100n);
V(out) <+ V(in[2])*transition(sel === 2, 0, 100n);
V(out) <+ V(in[3])*transition(sel === 3, 0, 100n);
end
endmodule
```

To implement a Verilog-A version of a multiplexer, it is helpful to read Modeling Digital Buses in Verilog-A:

```
module(out, in, sel);
output out; electrical out;
input [3:0] in; electrical [3:0] in;
input [3:0] sel; logic [3:0] sel;
parameter real vdd = 2.5;
integer SEL;
genvar i;
analog begin
// convert the input to an integer
SEL = 0;
for (i = 0; i < 2; i = i + 1) begin
@(cross(V(sel[i]) - vdd/2));
if (V(sel[i]) > vdd/2)
SEL = SEL + (1 << i);
end
V(out) <+ V(in[0])*transition(SEL == 0, 0, 100n);
V(out) <+ V(in[1])*transition(SEL == 1, 0, 100n);
V(out) <+ V(in[2])*transition(SEL == 2, 0, 100n);
V(out) <+ V(in[3])*transition(SEL == 3, 0, 100n);
end
endmodule
```