0%

2.5 Exercise

2.5 Exercise

FIR Filter

$y[n] = b_0 x[n] + b_1 x[n-1] + b_2 x[n-2] + …$

  • $y[n]$ is the output signal at time $n$
  • $x[n]$ is the input signal
  • $b_i$ are the filter coefficients or impulse response
  • $n-1$, $n-2$, … are time $n$ delayed by 1, 2, … cycles
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class My4ElementFir(b0: Int, b1: Int, b2: Int, b3: Int) extends Module {
val io = IO(new Bundle {
val in = Input(UInt(8.W))
val out = Output(UInt(8.W))
})
// val shiftReg1 = RegInit(0.U(8.W))
// val shiftReg2 = RegInit(0.U(8.W))
// val shiftReg3 = RegInit(0.U(8.W))
// shiftReg1 := io.in
// shiftReg2 := shiftReg1
// shiftReg3 := shiftReg2

val shiftReg1 = RegNext(io.in, 0.U)
val shiftReg2 = RegNext(shiftReg1, 0.U)
val shiftReg3 = RegNext(shiftReg2, 0.U)

io.out := b0.U(8.W) * io.in
+ b1.U(8.W) * shiftReg1
+ b2.U(8.W) * shiftReg2
+ b3.U(8.W) * shiftReg3
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
module My4ElementFir(
input clock,
input reset,
input [7:0] io_in,
output [7:0] io_out
);
reg [7:0] shiftReg1; // @[cmd58.sc 7:26]
reg [7:0] shiftReg2; // @[cmd58.sc 8:26]
reg [7:0] shiftReg3; // @[cmd58.sc 9:26]
wire [15:0] _T = 8'h1 * io_in; // @[cmd58.sc 19:23]
wire [15:0] _T_1 = 8'h1 * shiftReg1; // @[cmd58.sc 19:43]
wire [15:0] _T_3 = _T + _T_1; // @[cmd58.sc 19:31]
wire [15:0] _T_4 = 8'h1 * shiftReg2; // @[cmd58.sc 19:67]
wire [15:0] _T_6 = _T_3 + _T_4; // @[cmd58.sc 19:55]
wire [15:0] _T_7 = 8'h1 * shiftReg3; // @[cmd58.sc 19:91]
wire [15:0] _T_9 = _T_6 + _T_7; // @[cmd58.sc 19:79]
assign io_out = _T_9[7:0]; // @[cmd58.sc 19:10]
always @(posedge clock) begin
if (reset) begin // @[cmd58.sc 7:26]
shiftReg1 <= 8'h0; // @[cmd58.sc 7:26]
end else begin
shiftReg1 <= io_in; // @[cmd58.sc 7:26]
end
if (reset) begin // @[cmd58.sc 8:26]
shiftReg2 <= 8'h0; // @[cmd58.sc 8:26]
end else begin
shiftReg2 <= shiftReg1; // @[cmd58.sc 8:26]
end
if (reset) begin // @[cmd58.sc 9:26]
shiftReg3 <= 8'h0; // @[cmd58.sc 9:26]
end else begin
shiftReg3 <= shiftReg2; // @[cmd58.sc 9:26]
end
end
endmodule

FIR Filter Generator

The generator has 3 inputs:

  • in, the input to the filter
  • valid, a boolean that says when the input is valid
  • consts, a vector for all the taps

and 1 output:

  • out, the filtered input
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class MyManyDynamicElementVecFir(length: Int) extends Module {
val io = IO(new Bundle {
val in = Input(UInt(8.W))
val valid = Input(Bool())
val out = Output(UInt(8.W))
val consts = Input(Vec(length, UInt(8.W)))
})

// Such concision! You'll learn what all this means later.
val taps = Seq(io.in) ++ Seq.fill(io.consts.length - 1)(RegInit(0.U(8.W)))
taps.zip(taps.tail).foreach { case (a, b) => when (io.valid) { b := a } }

io.out := taps.zip(io.consts).map { case (a, b) => a * b }.reduce(_ + _)
}

visualize(() => new MyManyDynamicElementVecFir(4))