Skip to content

Commit 5156db4

Browse files
committed
Added SMA and tb
1 parent 4cd95ad commit 5156db4

File tree

2 files changed

+207
-0
lines changed

2 files changed

+207
-0
lines changed

moving_average.sv

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//------------------------------------------------------------------------------
2+
// moving_average.sv
3+
// Konstantin Pavlov, pavlovconst@gmail.com
4+
//------------------------------------------------------------------------------
5+
6+
// INFO ------------------------------------------------------------------------
7+
// Simple moving average implementation in SystemVerilog
8+
//
9+
// Features:
10+
// - configurable depth and data width
11+
// - DEPTH doesnt have to be a power of two, but 2^N implementations are
12+
// the most efficient
13+
// - can be configured to implement in cells or block RAM
14+
//
15+
16+
17+
/* --- INSTANTIATION TEMPLATE BEGIN ---
18+
19+
moving_average #(
20+
.DEPTH( 12 ),
21+
.DATA_W( 32 )
22+
) MA (
23+
.clk( clk ),
24+
.nrst( 1'b1 ),
25+
.ena( 1'b1 ),
26+
27+
.id( ),
28+
.od( )
29+
);
30+
31+
--- INSTANTIATION TEMPLATE END ---*/
32+
33+
module moving_average #( parameter
34+
DEPTH = 12, // DEPTH doesnt have to be a power of two
35+
DEPTH_W = $clog2(DEPTH),
36+
37+
DATA_W = 32 // data field width
38+
)(
39+
40+
input clk, // clock
41+
input nrst, // inverted reset
42+
input ena, // data enable
43+
44+
input [DATA_W-1:0] id, // data input
45+
output logic [DATA_W-1:0] od // averaged data output
46+
);
47+
48+
49+
logic [DATA_W-1:0] id_delayed;
50+
delay #(
51+
.LENGTH( DEPTH ),
52+
.WIDTH( DATA_W ),
53+
.TYPE( "CELLS" ) // "ALTERA_BLOCK_RAM" infers block ram
54+
) delay_data_buf ( // "ALTERA_TAPS" infers altshift_taps
55+
.clk( clk ), // all other values infer registers
56+
.nrst( nrst ),
57+
.ena( ena ),
58+
59+
.in( id[DATA_W-1:0] ),
60+
.out( id_delayed[DATA_W-1:0] )
61+
);
62+
63+
logic [DATA_W-1+DEPTH_W:0] moving_summ = '0; // considering width expansion
64+
always_ff @(posedge clk) begin
65+
if( ~nrst ) begin
66+
moving_summ[DATA_W-1+DEPTH_W:0] <= '0;
67+
end else if( ena ) begin
68+
moving_summ[DATA_W-1+DEPTH_W:0] <=
69+
( moving_summ[DATA_W-1+DEPTH_W:0] +
70+
id[DATA_W-1:0] - // adding new item
71+
id_delayed[DATA_W-1:0]); // subtracting the last one
72+
end
73+
end
74+
75+
always_comb begin
76+
// when DEPTH is a power of two, division turns out like a simple bit-shift
77+
od[DATA_W-1:0] <= moving_summ[DATA_W-1+DEPTH_W:0] / DEPTH;
78+
end
79+
80+
endmodule
81+

moving_average_tb.sv

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
//------------------------------------------------------------------------------
2+
// moving_average_tb.sv
3+
// Konstantin Pavlov, pavlovconst@gmail.com
4+
//------------------------------------------------------------------------------
5+
6+
// INFO ------------------------------------------------------------------------
7+
// testbench for moving_average.sv module
8+
//
9+
10+
`timescale 1ns / 1ps
11+
12+
module moving_average_tb();
13+
14+
logic clk200;
15+
initial begin
16+
#0 clk200 = 1'b0;
17+
forever
18+
#2.5 clk200 = ~clk200;
19+
end
20+
21+
// external device "asynchronous" clock
22+
logic clk33;
23+
initial begin
24+
#0 clk33 = 1'b0;
25+
forever
26+
#15.151 clk33 = ~clk33;
27+
end
28+
29+
logic rst;
30+
initial begin
31+
#0 rst = 1'b0;
32+
#10.2 rst = 1'b1;
33+
#5 rst = 1'b0;
34+
//#10000;
35+
forever begin
36+
#9985 rst = ~rst;
37+
#5 rst = ~rst;
38+
end
39+
end
40+
41+
logic nrst;
42+
assign nrst = ~rst;
43+
44+
logic rst_once;
45+
initial begin
46+
#0 rst_once = 1'b0;
47+
#10.2 rst_once = 1'b1;
48+
#5 rst_once = 1'b0;
49+
end
50+
51+
logic nrst_once;
52+
assign nrst_once = ~rst_once;
53+
54+
logic [31:0] DerivedClocks;
55+
clk_divider #(
56+
.WIDTH( 32 )
57+
) cd1 (
58+
.clk( clk200 ),
59+
.nrst( nrst_once ),
60+
.ena( 1'b1 ),
61+
.out( DerivedClocks[31:0] )
62+
);
63+
64+
logic [31:0] E_DerivedClocks;
65+
edge_detect ed1[31:0] (
66+
.clk( {32{clk200}} ),
67+
.nrst( {32{nrst_once}} ),
68+
.in( DerivedClocks[31:0] ),
69+
.rising( E_DerivedClocks[31:0] ),
70+
.falling( ),
71+
.both( )
72+
);
73+
74+
logic [15:0] RandomNumber1;
75+
c_rand rng1 (
76+
.clk(clk200),
77+
.rst(rst_once),
78+
.reseed(1'b0),
79+
.seed_val(DerivedClocks[31:0]),
80+
.out( RandomNumber1[15:0] )
81+
);
82+
83+
logic start;
84+
initial begin
85+
#0 start = 1'b0;
86+
#100 start = 1'b1;
87+
#20 start = 1'b0;
88+
end
89+
90+
// Module under test ==========================================================
91+
92+
logic [15:0] seq_cntr = '0;
93+
94+
logic [31:0] id = '0;
95+
always_ff @(posedge clk200) begin
96+
if( ~nrst_once ) begin
97+
seq_cntr[15:0] <= '0;
98+
id[31:0] <= '0;
99+
end else begin
100+
// incrementing sequence counter
101+
if( seq_cntr[15:0]!= '1 ) begin
102+
seq_cntr[15:0] <= seq_cntr[15:0] + 1'b1;
103+
end
104+
105+
if( seq_cntr[15:0]<300 ) begin
106+
id[31:0] <= '1;
107+
//id[31:0] <= {4{RandomNumber1[15:0]}};
108+
end else begin
109+
id[31:0] <= '0;
110+
end
111+
end
112+
end
113+
114+
moving_average #(
115+
.DEPTH( 255 ),
116+
.DATA_W( 32 )
117+
) MA (
118+
.clk( clk200 ),
119+
.nrst( nrst_once ),
120+
.ena( 1'b1 ),
121+
122+
.id( id[31:0] ),
123+
.od( )
124+
);
125+
126+
endmodule

0 commit comments

Comments
 (0)