util_cic: Allow partial gating of CIC comb and int stages

Allow to split a CIC int or comb block into multiple stages and be able to
dynamically gate some of the stages. Also prevent carry propagation in
gated stages to keep the adder output constant.

This is useful for multi-rate filter where not all bits are needed all the
time.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
main
Lars-Peter Clausen 2017-04-04 15:44:20 +02:00
parent 3e7325b29a
commit 17dff9ce90
2 changed files with 46 additions and 16 deletions

View File

@ -37,10 +37,13 @@
module cic_comb #( module cic_comb #(
parameter DATA_WIDTH = 32, parameter DATA_WIDTH = 32,
parameter SEQ = 1 parameter SEQ = 1,
parameter STAGE_WIDTH = 1,
parameter NUM_STAGES = 1
) ( ) (
input clk, input clk,
input ce, input ce,
input [NUM_STAGES-1:0] enable,
input [DATA_WIDTH-1:0] data_in, input [DATA_WIDTH-1:0] data_in,
output [DATA_WIDTH-1:0] data_out output [DATA_WIDTH-1:0] data_out
); );
@ -76,8 +79,10 @@ end
end end
endgenerate endgenerate
wire [DATA_WIDTH-1:0] mask;
reg [DATA_WIDTH-1:0] data_in_seq; reg [DATA_WIDTH-1:0] data_in_seq;
wire [DATA_WIDTH-1:0] storage_out; wire [DATA_WIDTH-1:0] storage_out;
wire [DATA_WIDTH-1:0] diff = (data_in_seq | ~mask) - (storage_out & mask);
always @(*) begin always @(*) begin
if (ce == 1'b1) begin if (ce == 1'b1) begin
@ -87,18 +92,19 @@ always @(*) begin
end end
end end
always @(posedge clk) begin
if (ce == 1'b1 || active == 1'b1) begin
state <= data_in_seq - storage_out;
end
end
generate generate
genvar i; genvar i, j;
for (i = 0; i < DATA_WIDTH; i = i + 1) begin: shift_r for (j = 0; j < NUM_STAGES; j = j + 1) begin
localparam k = NUM_STAGES - j - 1;
localparam H = DATA_WIDTH - STAGE_WIDTH * j - 1;
localparam L = k == 0 ? 0 : DATA_WIDTH - STAGE_WIDTH * (j+1);
assign mask[H:L] = {{H-L{1'b1}},k != 0 ? enable[k] : 1'b1};
for (i = L; i <= H; i = i + 1) begin: shift_r
always @(posedge clk) begin always @(posedge clk) begin
if (ce == 1'b1 || active == 1'b1) begin if (enable[k] == 1'b1 && (ce == 1'b1 || active == 1'b1)) begin
if (SEQ > 1) begin if (SEQ > 1) begin
storage[i] <= {storage[i][SEQ-2:0],data_in_seq[i]}; storage[i] <= {storage[i][SEQ-2:0],data_in_seq[i]};
end else begin end else begin
@ -108,7 +114,16 @@ generate
end end
assign storage_out[i] = storage[i][SEQ-1]; assign storage_out[i] = storage[i][SEQ-1];
end end
always @(posedge clk) begin
if (enable[k] == 1'b1 && (ce == 1'b1 || active == 1'b1)) begin
state[H:L] <= diff[H:L];
end
end
end
endgenerate endgenerate
assign data_out = state; assign data_out = state;

View File

@ -36,24 +36,39 @@
// *************************************************************************** // ***************************************************************************
module cic_int #( module cic_int #(
parameter DATA_WIDTH = 12 parameter DATA_WIDTH = 12,
parameter STAGE_WIDTH = 1,
parameter NUM_STAGES = 1
) ( ) (
input clk, input clk,
input ce, input [NUM_STAGES-1:0] ce,
input [DATA_WIDTH-1:0] data_in, input [DATA_WIDTH-1:0] data_in,
output [DATA_WIDTH-1:0] data_out output [DATA_WIDTH-1:0] data_out
); );
reg [DATA_WIDTH-1:0] state = 'h00; reg [DATA_WIDTH-1:0] state = 'h00;
wire [DATA_WIDTH-1:0] sum; wire [DATA_WIDTH-1:0] sum;
wire [DATA_WIDTH-1:0] mask;
assign data_out = state; assign data_out = state;
assign sum = data_in + state; assign sum = (data_in & mask) + (state & mask);
generate
genvar i;
for (i = 0; i < NUM_STAGES; i = i + 1) begin
localparam j = NUM_STAGES - i - 1;
localparam H = DATA_WIDTH - STAGE_WIDTH * i - 1;
localparam L = j == 0 ? 0 : DATA_WIDTH - STAGE_WIDTH * (i+1);
assign mask[H:L] = {{H-L{1'b1}},j != 0 ? ce[j] : 1'b1};
always @(posedge clk) begin always @(posedge clk) begin
if (ce == 1'b1) begin if (ce[j] == 1'b1) begin
state <= sum; state[H:L] <= sum[H:L];
end
end end
end end
endgenerate
endmodule endmodule