Вы находитесь на странице: 1из 6

Pipelines

Pipelines, queues, and FIFOs are common logic structures which are all related, in the
sense that data moves from one storage location to another synchronously, based on a
strobe signal, usually a clock.
For this discussion, we will talk about a simple pipeline, but the issues covered apply
equally to the other types of structures.

module pipeline (out, in, clock);


output out;
input in, clock;
reg
out, pipe[1:2];
always @(posedge clock) begin
out = pipe[2];
pipe[2] = pipe[1];
pipe[1] = in;
end
endmodule

This code works fine. The only potential problem is that out changes value on the clock
edge, so whatever takes it as an input may get the wrong value. A better version would be
to use a non-blocking assign:
always @(posedge clock) begin
out <= pipe[2];
pipe[2] <= pipe[1];
pipe[1] <= in;
end

Note that with the non-blocking assign, the order of the assignment statements is
irrelevent.
An interesting variation is the following:
module pipeline (out, in, clock);
output out;
input in;
reg pipe[1:2];
always @(posedge clock)
{out, pipe[2], pipe[1]} = #d {pipe[2], pipe[1], in};
endmodule

Use of the intra-assignment delay is possible here because there is only one statement in
the always block.

Pipelines: Independent Pipeline Stages


It is more common for the different pipe stages to be in different processes, and often in
different modules. The three stage pipe might look more like this:
module pipeline (out, in, clock);
output out;
input in, clock;
reg
out, pipe1, pipe2;
always @(posedge clock)
out = pipe2;
always @(posedge clock)
pipe2 = pipe1;
always @(posedge clock)
pipe1 = in;
endmodule

This, however, doesn't work, and it is worth repeating that the source order of the
different always blocks makes no difference. As we have pointed out before, both of the
following alternatives will work.
always@(posedge clock)
out <= pipe2;

always@(posedge clock)
out = #d pipe2;

always@(posedge clock)
pipe2 <= pipe1;

always@(posedge clock)
pipe2 = #d pipe1;

always@(posedge clock)
pipe1 <= in;

always@(posedge clock)
pipe1 = #d in;

Many designers use an intra-assignment delay with a non-blocking assign in this case.
While it works, there is no benefit to doing it, and it is somewhat less efficient than either
of these two methods.

Pipelines: Pipeline Stages As Separate Module


Instances
It is common to make a single pipe stage module and use it repetitively, as follows:
module pipeline (out, in, clock);
output out;
input in, clock;
wire
s1out, s2out;
pipestage s1
s2
s3
endmodule

(s1out, in,
clock),
(s2out, s1out, clock),
(out,
s2out, clock);

module pipestage (out, in, clock);


output out;
input in, clock;
reg
out;
always @(posedge clock)
out <= in;
endmodule

Of course, this works just like the previous version, and the pipestage module is nothing
more than a D flip-flop.

Pipelines: Combinational Logic in the Pipeline


It is more interesting if there is some combinational logic associated with each pipe stage.
Suppose each stage has some logic represented by a function f1, f2, f3 which is applied to
the input.

Then, the pipeline might look like this:


module pipeline (out, in, clock);
output out;
input in, clock;
wire
s1out, s2out, s1in, s2in, s3in;
assign s1in = f1(in),
s2in = f2(s1out),
s3in = f3(s2out);
pipestage s1
s2
s3
endmodule

(s1out, s1in, clock),


(s2out, s2in, clock),
(out,
s3in, clock);

Notice that there is no need to put a delay on the continuous assignments, because the
delay is done in the pipestage module (using the NBA). Alternatively, one could make
the pipestage delay-less and put a delay on the continuous assignments.

QUESTION: Write a module which implements a 3-stage pipeline. Each stage is a


single bit, and there is a single bit as input. The output should be 1 whenever all
three stages contain a zero, which is the initial condition. The module template is:
module zero3 (out, in, clk);
output out;
input in, clk;
reg s1, s2, s3;
assign out = s1==0 & s2==0 & s3==0;
initial begin
s1 = 0;
s2 = 0;
s3 = 0;
end
always @(posedge clk) begin
s1 <= in;
s2 <= s1;
s3 <= s2;
end
endmodule

Test Module
module test;
wire out;
reg in, clk;
zero3 z3 (out, in, clk);
initial begin
in = 0;
clk = 0;
forever #5 clk = ~clk;
end

initial begin
$monitor($stime,,"clk: %b

in: %b

out: %b", clk, in,

out);

#1
end
endmodule

repeat (2) @(posedge


in <= 1;
repeat (2) @(posedge
in <= 0;
repeat (4) @(posedge
in <= 1;
repeat (3) @(posedge
@(posedge clk) in <=
repeat (4) @(posedge
$finish;

clk);
clk);
clk) ;
clk) in <= ~in;
0;
clk) ;

Pipeline Multiplier (from Xilinx site)


//Verilog example
module pipelined_multiplier ( a, b, clk, pdt);

/*
* parameter 'size' is the width of multiplier/multiplicand;.Application
Notes 10-5
* parameter 'level' is the intended number of stages of the
* pipelined multiplier;
* which is typically the smallest integer greater than or equal
* to base 2 logarithm of 'size'
*/

parameter size = 16, level = 4;


input [size-1 : 0] a;
input [size-1 : 0] b;
input clk;
output [2*size-1 : 0] pdt;
reg [size-1 : 0] a_int, b_int;
reg [2*size-1 : 0] pdt_int [level-1 : 0];
integer i;
assign pdt = pdt_int [level-1];
always @ (posedge clk)
begin
// registering input of the multiplier
a_int <= a;
b_int <= b;
// 'level' levels of registers to be inferred at the output
// of the multiplier
pdt_int[0] <= a_int * b_int;
for(i =1;i <level;i =i +1)
pdt_int [i] <= pdt_int [i-1];
end // always @ (posedge clk)
endmodule

// pipelined_multiplier

Вам также может понравиться