本设计包含一个位宽转换单元(如:将输入的4位的数据转换为8位数据输出),一个向上计数器模块,一个top层,一个testbench。全部采用参数化设计。
位宽转换单元converter.v代码如下:
本文引用自:https://blog.csdn.net/llxxyy507/article/details/82790808
module converter #(parameter WIDTH = 4, PAD_NUM = 1) // parameter defaults.
(output[WIDTH-1+PAD_NUM:0] out_bus, // default variable type: wire
input [WIDTH-1:0] in_bus, // header port IEEE1364-2001
input enable
);
reg[WIDTH-1+PAD_NUM:0] bus_reg; // internal variables; Retains current count value.
reg[WIDTH-1+PAD_NUM:0] out_bus_gate; // Retains three-state.
// --------------main code --------------------------------------------------------
// Keep bus_reg always updated (combinational circuit): assign, always@(level_list)
always@(in_bus) // list sensitivity
begin
// This could be done by concatenation, a later topic:
// bus_reg[WIDTH-1:0] = in_bus;
if (PAD_NUM!=1'b0) begin
bus_reg[(WIDTH-1+PAD_NUM):WIDTH] = 'b0; // PAD with 0.
bus_reg[WIDTH-1:0] = in_bus;
end
else // syn-RTL coding style, if not => latch
bus_reg[WIDTH-1:0] = in_bus;
end
// Next block controls the state of the output drivers:
always@(enable, bus_reg) // IEEE-1364 1995 "," => "or'
begin
if (enable==1'b1)
#2 out_bus_gate = bus_reg;
else #1 out_bus_gate = 'bz; // Set high-impedance.
end
converter.v将输入的 input [WIDTH-1:0] in_bus,转换为 output[WIDTH-1+PAD_NUM:0] out_bus,多余的位直接补零。
计数器counter.v模块代码如下:
module counter #(parameter WIDTH = 4) // default parameter
(output[WIDTH-1:0] count,
input clk, count_enable, count_reset
);
// ------------ internal variables --------------------------
reg[WIDTH-1:0] count_reg; // Store the count. Outputs are always registed.
wire clock_wire; // To gate the clock during disable.
//-------------- main code -----------------------------------
// Keep the count wired to the output:
assign #1 count = count_reg;
// Don't count while disabled: clock gating
assign clock_wire = (count_enable==1'b1)? clk : 1'b0;
// Do the counter: sequential circuit, async-reset
always@(posedge clock_wire, posedge count_reset)
begin
if (count_reset==1'b1)
count_reg <= 'b0; // Ignore width.
else count_reg <= count_reg + 1'b1;
end
endmodule // counter
计数器counter.v实现 2^WIDTH 向上计数。
设计的top层param_counter_top.v代码如下:
`define PADWIDTH 3 // Global width; controls parameter values.
// No reference to PADWIDTH except at top.
module param_counter_top // Top-level params in ANSI format:
#(parameter WIDTH = `PADWIDTH, // Saves repeated "-1".
PAD_NUM = 5 // The Count width control.
)
( output[WIDTH-1+PAD_NUM:0] count,
input clk, count_enable, count_reset, out_enable);
wire[WIDTH-1:0] Xfer; // Local bus to connect module instances.
// instance - hirarchy (XMR)
// Pass parameter values by name (position):
counter #(.WIDTH(WIDTH))
u_counter( .count (Xfer ),
.clk (clk ),
.count_enable (count_enable),
.count_reset (count_reset )
);
converter #(.WIDTH(WIDTH), .PAD_NUM(PAD_NUM))
u_converter01( .out_bus (count),
.in_bus (Xfer),
.enable (out_enable)
);
endmodule // param_counter_top.
top层中例化了上面两个模块,且定义了一个宏 `define PADWIDTH 3 ,但在接下来的tb.v中又重新定义了 `PADWIDTH ,使用synopsys公司 vcs仿真时,会显示后面定义的 PADWIDTH 会把前面的覆盖,即 最终仿真的时候 PADWIDTH 为5。
本设计的tb.v模块代码如下:
`define PADWIDTH 5 // Global width; controls parameter values.
// No reference to PADWIDTH except at top.
module tb;
// The parameter definitions in TestBench are redundant,
// because testbench will not be synthesized.
// Changing testbench param values will override the
// values in the design, which become defaults when
// the design is instantiated in the testbench module:
//
parameter WIDTH = `PADWIDTH , PAD_NUM = 3;
//
wire[WIDTH-1+PAD_NUM:0] CountTest;
reg count_enableTest,
clockTest,
CountResetTest,
OutEnableTest;
// Design instance:
param_counter_top
#(.WIDTH(WIDTH), .PAD_NUM(PAD_NUM)) // Pass testbench size to design.
u_param_counter_top (
.count (CountTest ),
.count_enable (count_enableTest ),
.clk (clockTest ),
.count_reset (CountResetTest ),
.out_enable (OutEnableTest )
);
initial
begin
#01 clockTest = 1'b0;
count_enableTest = 1'b0;
CountResetTest = 1'b0;
OutEnableTest = 1'b0;
#02 CountResetTest = 1'b1;
#02 CountResetTest = 1'b0;
//
#01 count_enableTest = 1'b1;
#02 OutEnableTest = 1'b1;
// Later, we shall see better ways to
// define a clock:
#05 clockTest = 1'b1;
#05 clockTest = 1'b0;
#05 clockTest = 1'b1;
#05 clockTest = 1'b0;
#01 OutEnableTest = 1'b0;
#02 OutEnableTest = 1'b1;
#05 clockTest = 1'b1; // clock skips #3 here.
#05 clockTest = 1'b0;
#05 clockTest = 1'b1;
#05 clockTest = 1'b0;
#05 clockTest = 1'b1;
#05 clockTest = 1'b0;
#05 clockTest = 1'b1;
#05 clockTest = 1'b0;
#05 clockTest = 1'b1;
#05 clockTest = 1'b0;
#05 clockTest = 1'b1;
#05 clockTest = 1'b0;
#05 clockTest = 1'b1;
#05 clockTest = 1'b0;
#05 clockTest = 1'b1;
#05 clockTest = 1'b0;
#05 clockTest = 1'b1;
#10 $finish;
end
initial begin
$vcdpluson();
end
endmodule // tb
本设计的testbench与top连接的时候,将参数也传递过去了,所以整个设计的参数值全来自testbench,
`define PADWIDTH 5
parameter WIDTH = `PADWIDTH , PAD_NUM = 3;
尽管在前面的模块中有定义,但最终仿真中的数据WIDTH 为5,PAD_NUM为3。