HDLBits——Multiplexers
Problem 60 : 2-to-1 multiplexer (Mux2to1)
Requirement:
multiplexer:多路选择器。
本题中需要实现一个 2 选 1 选择器,sel 信号作为选择信号,当 sel = 1 时选择 b,反之选择 a。
Solution:
module top_module(
input a, b, sel,
output out );
assign out = sel ? b : a;
endmodule
PS:三元运算符(Ternary operator),cond ? if true : if false
嵌套的用法也十分常用,比如求 a,b,c 中的最大值,可以在一个三元运算符中嵌套两个三元运算符。
assign max = (a > b) ?
(a > c)?a:c
:
(b > c)?b:c
;
在嵌套使用时,为了防止混乱,最好将 cond iftrue iffalse 分三行书写。
Timing Diagram:
Problem 61 : 2-to-1 bus multiplexer (Mux2to1v)
Requirement:
创建一个 100 位宽的 2 选 1 多路复用器。当sel=0时,选择a。当sel=1时,选择b。
Solution:
module top_module(
input [99:0] a, b,
input sel,
output [99:0] out );
assign out = sel ? b : a;
endmodule
PS:本题与上一题的区别在于信号从单比特宽度变成总线信号,但选择器的原理以及对应的代码与前一题相同。
Timing Diagram:
Problem 62 : 9-to-1 multiplexer (Mux9to1v)
Requirement:
本题中需要实现一个 16 位宽的 9 选 1 选择器,sel 信号作为选择信号,当 sel = 0 时选择 a,sel = 1 时选择 b,以此类推。对于未使用的情况,将所有 output 位设置为’1’。
Solution:
module top_module(
input reg [15:0] a, b, c, d, e, f, g, h, i,
input [3:0] sel,
output reg [15:0] out );
always @(*) begin
case(sel)
0:out = a;
1:out = b;
2:out = c;
3:out = d;
4:out = e;
5:out = f;
6:out = g;
7:out = h;
8:out = i;
default:out = 16'hffff;
endcase
end
endmodule
PS:case 语句只能在 always 块中使用。
Timing Diagram:
Problem 63 : 256-to-1 multiplexer (Mux256to1)
Requirement:
本题中需要实现一个 256 选 1 选择器,sel 信号作为选择信号,当 sel = 0 时选择 in[0],sel = 1 时选择 in[1],以此类推。
Solution:
module top_module(
input [255:0] in,
input [7:0] sel,
output reg out );
always @(*) begin
out = in[sel];
end
endmodule
选择运算符的 index 可以为变量,只要变量的位宽和向量的长度匹配即可。所以直接将 sel 这个变量,作为片选向量 in 的 index。
方法二:利用截断,将输入向量 in 右移 sel 位,高位被截去,输出最低位上的 in[sel],移位的长度也可以使用变量。
module top_module(
input [255:0] in,
input [7:0] sel,
output out );
assign out = in>>sel;
endmodule
Problem 64 : 256-to-1 4-bit multiplexer (Mux256to1v)
Requirement:
本题中需要实现一个 256 选 1 选择器,sel 信号作为选择信号,当 sel = 0 时选择 in[3:0],sel = 1 时选择 in[7:4],以此类推。同上一题的区别在于,位宽从 1 位变到了 4 位。(多位宽:使用位选择符或者位连接符)
Solution:
错过: assign out = in[ sel*4+3 : sel*4 ]; 但这个表达式不符合 Verilog 片选操作符的语法。
片选多个比特的正确语法有两种:
-
assign out = in[sel*4 +: 4];
从 sel*4 开始,选择比特序号大于sel*4 的 4 位比特(包含 sel*4),相当于[sel*4+3 : sel*4]
-
assign out = in[sel*4+3 -: 4];
从 sel*4+3 开始,选择比特序号小于 sel*4+3 的 4 位比特,相当于[sel*4+3 : sel*4]
方法一:用片选的方法
module top_module(
input [1023:0] in,
input [7:0] sel,
output [3:0] out );
assign out = in[sel*4+:4];
endmodule
方法二:用位连接符
module top_module(
input [1023:0] in,
input [7:0] sel,
output [3:0] out );
assign out = {in[sel*4+3],in[sel*4+2],in[sel*4+1],in[sel*4]};
endmodule
方法三:移位
module top_module(
input [1023:0] in,
input [7:0] sel,
output [3:0] out );
assign out = in>>sel*4;
endmodule
注意:虽然移位操作符可以使用变量,但不能嵌套移位,也就是在移位操作符中对变量进行操作:
比如若需要 assign out = in >> (sel << 2); 的效果,只能通过使用一次中间变量来将 sel 移位。
wire [9:0] sel_shift = sel << 2;
assign out = in >> sel_shift;
PS:2021 年的最后一个月以懒惰的一天开始和结束。