I have to delay a few control signals in a pipeline I've designed by the number of stages in the pipeline. This is obviously very straight forward -- just put N flip-flops in between the the input signal and output signal. I'm wondering if there's a way to parameterize N. If I ever change the number of stages in the pipeline I have to go back and add/remove flip-flops, which is sort of annoying. I thought about just writing a script to read a define somewhere and generate the module, but that seems like overkill. Is a genvar loop the right way to go here?
You could use a parameterized shift register to do this. Something like:
module shift
(
input clk,
input data_in,
output data_out
);
parameter DEPTH = 3;
reg [DEPTH-1:0] holding_register;
always # (posedge clk) begin
holding_register <= {holding_register[DEPTH-2:0], data_in};
end
assign data_out = holding_register[DEPTH-1];
endmodule
Another alternative would be to use a generate statement to create essentially the same effect.
Here is how to created the parameterized shift register using a generate block and a DFF module. It even works with DEPTH=0 and DEPTH=1.
module shift
(
input clk,
input reset,
input data_in,
output data_out
);
parameter DEPTH = 3;
wire [DEPTH:0] connect_wire;
assign data_out = connect_wire[DEPTH];
assign connect_wire[0] = data_in;
genvar i;
generate
for (i=1; i <= DEPTH; i=i+1) begin
dff DFF(clk, reset,
connect_wire[i-1], connect_wire[i]);
end
endgenerate
endmodule
Complete working code with a test on EDA Playground: http://www.edaplayground.com/s/4/50
Related
I have 2 Modules. One is Register_File_Rf which is a file of 32 Registers I have created. I want to be able to see what every single register is storing.
Can I do this with $display or $monitor somehow?
Where these should be? In actual code or in Testbench, and how do I get the value in testbench when the stored Data is neither input or output?
module Register(
input Clk,
input [31:0] Data,
input WE,
output reg[31:0] Dout
);
reg [31:0] stored;
// With every Positive Edge of the Clock
always #(posedge Clk)begin
// If Write is Enabled we store the new Data
if (WE)begin
stored <= Data;
Dout <= stored;
end else
Dout <= stored;
end
module Register_File_RF(
input [4:0] Adr1,
input [4:0] Adr2,
input [4:0] Awr,
output reg[31:0] Dout1,
output reg[31:0] Dout2,
input [31:0] Din,
input WrEn,
input Clk
);
integer j;
genvar i;
wire [31:0]Temp_Dout[31:0];
reg W_E [31:0];
// Writing only in the first time R0 Register with 0
initial begin
W_E[0] = 1;
end
// Creating the R0 Register
Register register (.Clk(Clk),.WE(W_E[0]),.Data(0),.Dout(Temp_Dout[0]));
// Creating 30 Registers
for(i = 1; i < 32; i = i + 1)begin:loop
Register register (.Clk(Clk),.WE(W_E[i]),.Data(Din),.Dout(Temp_Dout[i]));
end:loop
// Assigning to Dout1 and Dout2 the Data from a spesific register
always #(Adr1, Adr2) begin
Dout1 = Temp_Dout[Adr1];
Dout2 = Temp_Dout[Adr2];
end
// Wrting Data to a specific register
always #(posedge Clk)begin
//Reseting Write Enable of the register to 0
for (j = 0; j < 32; j = j + 1)begin:loop2
W_E[j] = 0;
end:loop2
if(WrEn)begin
W_E[Awr] = WrEn;
end
end
endmodule
Yes, you can do this with either $display or $monitor.
Typically, $monitor would be called inside an initial block since it should only be called at one time in your simulation. It automatically displays values whenever one of its argument signals changes value.
Unlike $monitor, $display only displays values when it is called; it must be called whenever you want to display a signal value. It can be called in an initial block, but it is often called in an always block.
Regarding when to use either one, it is up to you to decide what you require.
If you are not planning to synthesize your modules, you could place monitor/display inside your design module directly. However, if you plan to synthesize, it might be better to place them in the testbench.
You can use hierarchical scoping to view internal signals from the testbench module. For example, assume you named the instance of the Register_File_RF module in the testbench as dut:
Register_File_RF dut (
// ports
);
always #(posedge Clk) begin
$display($time, " dout='h%x", dut.register.Dout);
end
initial begin
$monitor($time, " dout='h%x", dut.register.Dout);
end
$monitor will display a value every time Dout changes value, whereas $display will show the value at the posedge of the clock.
If your simulator supports SystemVerilog features, you can also use bind to magically add code to your design modules.
I'm newbie in ASIC design. I have a design with for example two inputs a ,b. I'm using the following code for initialize these two signals. But the Design compiler generating a warning that the register "a" is a constant and will be removed. When I'm trying to do post-synthesis simulation these two signals are all 'z'. So how can I apply initial signal assignment to avoid such a problem?
always #(posedge(clk) or posedge (rst)) begin
if (rst) begin
a<=4d'5;
b <=4'd10;
end
end
While describing hardware system, you need to consider that input signals to your module comes from another module/system and their values are decided by that signals. Inputs to any module can only be wire type.
You can think of a module as a box that has inputs and outputs. The values of output signals are decided by input signal + logic inside the box. However, the module cannot decide what its inputs should be. It is only possible if there is feedback, and even in that case it would depend on other signals that are outside of the module's control.
As a result, output signals can be declared as output reg but the same is not true for inputs. However there is solution to your problem, I think what you want can be designed using the following method:
module your_module(
input clk,
input rst,
//other inputs and outputs that you might need
input [3:0] a,
input [3:0] b
);
//define registers
reg [3:0] a_register;
reg [3:0] b_register;
/*
These registers are defined to make it possible to
to give any value to that logics when posedge rst
is detected, otherwise you can use them as your
input logics
*/
//use initial block if you need
always#(posedge clk or posedge rst) begin
if(rst) begin
a_register <= 4'd5;
b_register <= 4'd10;
end
else
begin
a_register <= a;
b_register <= b;
// and use a_register and b_register as you want to use a and b
end
end
endmodule
I want to create a shift register using d-flip-flop as basic structural element.
code:
dff:
module dff(d,q,clk,rst);
input d,clk,rst;
output reg q;
always #(posedge clk)
begin:dff_block
if(rst==1'b1)
q=1'b0;
else
q=d;
end
endmodule
shift register:
module shift_register(s1,d,clk,s0,q);
parameter n=3;
input s1,clk;
input [n:0] d;
output s0;
output [n:0] q;
genvar i;
assign d[3]=s1;
generate
for(i=0; i<=n; i=i+1)
dff U1(.d(d[i]),.q(q[i]),.clk(clk));
endgenerate
assign q[3]=d[2];
assign q[2]=d[1];
assign q[1]=d[0];
assign q[0]=s0;
endmodule
test bench:
module tb();
parameter n=3;
reg [n:0] d;
reg s1,clk;
wire [n:0] q;
wire s0;
shift_register UUT(.s1(s1),.d(d),.clk(clk),.q(q),.s0(s0));
initial begin
d=4'b0000;
clk=0;
end
always
begin:clok
#10 clk=~clk; s1=1;
end
endmodule
I think test bench has the problem.I have tried to give s1 values for every #10 while clk=1 but again does not work.
This code does not give me waveforms for q and s0.I cant find whats wrong.Any ideas?
you have several problems with the code.
q is an output reg of dff; q[i] is passed as q to dff. q[i] gets also assigned in within the assign statement. So, you have multiply driven wire q[i] which most likely gets resolved to x and never changes. You have your i/o swapped around somewhere.
you do not assign anything to s0, so it does not change and does not produce any waveform.
in this particular case blocking assignments within the flop will not pay any role, but in general they could cause unpredictable simulation results. Use non-blocking.
there is not much sense in the generate loop there. You can pass full vectors tot he dff and can flop full vectors as well.
It looks like you get confused int teh direction of the assign statement. It implies direction. assign q[0] = s0; means assign value of s0 to the wire q[0], not vice versa.
I am trying using infinite for loop inside generate statement. But the problem is I cannot stop it or exit it using some condition. I used "disable" and "break". Both don't work.
It shows an error :
unexpected token: 'disable'
Please help me solve this problem or suggest an alternative to it. Here is my Verilog code:
module top(a1,a3,wj,d4,d10,d2,dc,dtot);
input [11:0]a1,a3,wj;
input [3:0]d4;
input [9:0]d10;
input [1:0]d2;
input [25:0]dc;
output reg[25:0]dtot;
reg [25:0]dt,error;
reg [11:0]alpha1,alpha3;
genvar i;
generate
for (i=1;i>0;i=i+1-1)begin:test
assign a1[11:0]=alpha1[11:0];
assign a3[11:0]=alpha3[11:0];
calb_top t1(a1,a3,wj,d4,d10,d2,dc,dt,error,alpha1,alpha3);
if(error==26'b00000000000000000000000000)begin
disable test;
//break;
end
end
endgenerate
assign dtot=dt;
endmodule
Verilog generate block are used to describe physical hardware. As such, an inifinite loop in a generate block will require infinite resources.
Any for loop inside a generate statement must be of a fixed and finite size that can be determined during synthesis.
Remember that HDL is not executed sequentially, but describes connections between physical circuits. Since it appears that you only require one instance of the calb_top module, you don't require either the generate block or the for loop.
Edit:
Since you're intending to perform an iterative process, you have two options, as Greg pointed out in his comment below - you can either instantiate a fixed number of calb_top blocks (since an infinite number would require an infinite amount of space) or to re-use the same block some number of times.
Here are some samples. I've haven't sim'd or synthesized them, but they're logically correct.
N-Block solution
module top(a1,a3,wj,d4,d10,d2,dc,dtot,clock,done);
parameter NUM_BLOCKS = 10;
input [11:0]a1,a3,wj;
input [3:0]d4;
input [9:0]d10;
input [1:0]d2;
input [25:0]dc;
output [25:0]dtot;
wire [11:0] a1s [NUM_BLOCKS:0];
wire [11:0] a3s [NUM_BLOCKS:0];
wire [25:0] dt [NUM_BLOCKS-1:0];
wire [25:0] error [NUM_BLOCKS-1:0];
assign a1s[0]=a1;
assign a3s[0]=a3;
genvar i;
generate
for (i=0;i<NUM_BLOCKS;i=i+1)begin:test
calb_top t1(a1s[i],a3s[i],wj,d4,d10,d2,dc,dt[i],error[i],a1s[i+1],a3s[i+1]);
end
endgenerate
assign dtot=dt[NUM_BLOCKS-1];
endmodule
This links together a number of calb_top blocks equal to NUM_BLOCKS, then outputs the result of the final block to dtot. This doesn't do any checks on the error, so you may want to put in your own code to check error[NUM_BLOCKS-1] (the error of the final calb_top).
Single-Block solution:
module top(clock,start,a1,a3,wj,d4,d10,d2,dc,dtot);
input clock;
input start;
input [11:0]a1,a3,wj;
input [3:0]d4;
input [9:0]d10;
input [1:0]d2;
input [25:0]dc;
output reg[25:0]dtot;
wire [25:0]dt,error;
reg [11:0] a1in, a3in;
wire [11:0] alpha1,alpha3;
calb_top t1(a1in,a3in,wj,d4,d10,d2,dc,dt,error,alpha1,alpha3);
always #(posedge clock)
begin
if (start)
begin
a1in <= a1;
a3in <= a3;
end
else
begin
a1in <= alpha1;
a3in <= alpha3;
end
end
always #(posedge clock)
if (start)
dtot <= 0;
else if (error == 0)
dtot <= dt;
else
dtot <= dtot;
endmodule
Each clock cycle, we run one pass through calb_top. If start is 1, then a1 and a3 are used as inputs. Otherwise, the previous outputs alpha1 and alpha3 are used. When error is 0, then dtot is set. Note that I've added clock and start to the port list.
module save_random (clk,in,out);
parameter size=10;
parameter k=10;
input clk;
input [k-1:0] in;
output [k-1:0]out;
wire [size:0] cout;
genvar i;
generate
for(i=0;i<size;i=i+1)
begin: level1
always#(posedge clk) begin
random ins(clk,in[i],cout[i+1]);//generte 10 instances from module random to save it //in registers
end
end
endgenerate
assign cout[0]=in[0];
assign out=cout[k];
endmodule
I am just starting to learn verilog,
i have a task to write synthesis code that generate 10 random values and save each value in register or Dflipflop or sth like this.
The first(save_random) module that generate 10 instances from module random(the 2nd one) and connected ..but still have error when I am using clk input with generate i..
module random(clk,d,cout);
parameter size=8;
input [size-1:0] d;
input clk;
output [size-1:0]cout;
reg [size-1:0]cout;
integer i;
always#(posedge clk)
begin
cout<=d;
end
endmodule
You cannot instantiate modules inside an always block. As you have a module random which is a register of size size, you only need to instantiate that module inside your generate if you need more than one:
genvar i;
generate begin
for(i=0;i<size;i=i+1) begin: level1
random ins(clk,in[i],cout[i+1]);
end
end
However, note that in[i] and cout[i+1] are not an 8-bit values. So if you want to use the full 8-bit register, you need to declare them to be 10 (or 11 for cout) 8-bit vectors:
input [7:0] in [9:0];
wire [7:0] cout [10:0];
This tutorial might give you a better idea how generate blocks work: https://www.youtube.com/watch?v=5CKfP4n9ge0