摘要:Verilog 数据选择器 参数化
1、使用场景
在有些场景下,需要用到可参数化的数据选择器。比如,将DDR设计成多通道时,地址的选通和数据的选通,需要实现多选一。实际工程当中需要把DDR划分成几个通道是不确定的,所以数据选择器是从几路里面选择一路是不确定的。常规做法是用case语句实现数据选择器,然而,Verilog的case语句不够灵活,无法做到参数化,就无法做到通用性。这个时候就引出了数据选择器的参数化设计。
2、工程实现
数据选择器的参数化设计,其核心就是二维数组,通过二维数组索引的方式实现可以做到参数化。下面是具体代码实现,仅供参考。
模块代码:
module binary_mux #(
parameter dataNum = 5,
parameter dataWidth = 8,
parameter log2N = (dataNum == 1) ? 1 : $clog2(dataNum)
) (
input wire [log2N-1:0] sel,
input wire [dataNum*dataWidth-1:0] din,
output reg [dataWidth-1:0] dout
);
wire [dataWidth-1:0] din_array [2**log2N-1:0];
generate
begin
genvar i;
for (i = 0; i < 2**log2N; i = i + 1) begin
if (i < dataNum) begin
assign din_array[i] = din[dataWidth*i +: dataWidth];
end else begin
assign din_array[i] = din[dataWidth*0 +: dataWidth];
end
end
end
endgenerate
always@(*)begin
dout = din_array[sel];
end
//
/*
binary_mux #(.dataNum (dataNum ), .dataWidth (dataWidth )) u_binary_mux(.sel (sel ), .din (din ), .dout (dout ));
*/
endmodule
RTL原理图:
仿真模块:
//~ `New testbench
`timescale 1ns / 1ps
module tb_binary_mux;
// unit_data_mux Parameters
parameter PERIOD = 10;
parameter dataNum = 5;
parameter dataWidth = 8;
parameter log2N = (dataNum == 1) ? 1 : $clog2(dataNum);
// unit_data_mux Inputs
reg clk = 1 ;
reg reset = 1 ;
reg [log2N-1:0] sel = 0 ;
reg [dataNum*dataWidth-1:0] din = 0 ;
// unit_data_mux Outputs
wire [dataWidth-1:0] dout ;
initial
begin
forever #(PERIOD/2) clk=~clk;
end
initial
begin
#(PERIOD*2) reset = 0;
end
always @(posedge clk ) begin
if (reset) begin
din[dataWidth*0 +: dataWidth] <= 'd1;
din[dataWidth*1 +: dataWidth] <= 'd2;
din[dataWidth*2 +: dataWidth] <= 'd3;
din[dataWidth*3 +: dataWidth] <= 'd4;
din[dataWidth*4 +: dataWidth] <= 'd5;
sel <= 'd0;
end else begin
din <= din;
sel <= sel + 'd1;
end
end
binary_mux #(
.dataNum ( dataNum ),
.dataWidth ( dataWidth ))
u_binary_mux (
.sel ( sel [log2N-1:0] ),
.din ( din [dataNum*dataWidth-1:0] ),
.dout ( dout [dataWidth-1:0] )
);
endmodule
仿真波形:
说明:这里的数据个数不一定需要是2^N,没有这个限制,可自行设置非2^N的整数倍时的默认输出值,这里设计的是默认输出是0路。