Skip to content

Commit

Permalink
feat: convert CW_iir*
Browse files Browse the repository at this point in the history
Closes #20
  • Loading branch information
SingularityKChen committed Aug 4, 2023
1 parent a4ee4d4 commit 802eaad
Show file tree
Hide file tree
Showing 4 changed files with 350 additions and 0 deletions.
99 changes: 99 additions & 0 deletions chipware/src/CW_iir_dc.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import chisel3._
import chisel3.experimental._
import chisel3.util._

/**
* == CW_iir_dc ==
*
* === Abstract ===
*
* High-Speed Digital IIR Filter with Dynamic Coefficients
*
* === Parameters ===
*
* | Parameter | Legal Range | Default | Description |
* |--------------------|------------------------------|---------|-------------|
* | data_in_width | >=2 | 8 | Input data word length |
* | data_out_width | >=2 | 16 | Width of output data |
* | frac_data_out_width| 0 to data_out_width-1 | 4 | Width of fraction portion of data_out |
* | feedback_width | >=2 | 12 | Width of feedback_data |
* | max_coef_width | >=2 | 8 | Maximum coefficient word length |
* | frac_coef_width | 0 to max_coef_width-1 | 4 | Width of the fraction portion of the coefficients |
* | saturation_mode | 0 or 1 | 0 | Controls the mode of operation of the saturation output |
* | out_reg | 0 or 1 | 1 | Controls whether data_out and saturation are registered |
*
* === Ports ===
*
* | Name | Width | Direction | Description |
* |------------|------------------|-----------|-------------|
* | clk | 1 bit | In | Clock signal |
* | rst_n | 1 bit | In | Asynchronous reset, active-low |
* | init_n | 1 bit | In | Synchronous, active-low signal to clear all registers |
* | enable | 1 bit | In | Active-high signal to enable all registers |
* | A1_coef | max_coef_width | In | Two's complement value of coefficient A1 |
* | A2_coef | max_coef_width | In | Two's complement value of coefficient A2 |
* | B0_coef | max_coef_width | In | Two's complement value of coefficient B0 |
* | B1_coef | max_coef_width | In | Two's complement value of coefficient B1 |
* | B2_coef | max_coef_width | In | Two's complement value of coefficient B2 |
* | data_in | data_in_width | In | Input data |
* | data_out | data_out_width | Out | Accumulated sum of products of the IIR filter |
* | saturation | 1 bit | Out | Used to indicate the output data or feedback data is in saturation |
*
* @param data_in_width Input data word length
* @param data_out_width Width of output data
* @param frac_data_out_width Width of fraction portion of data_out
* @param feedback_width Width of feedback_data
* @param max_coef_width Maximum coefficient word length
* @param frac_coef_width Width of the fraction portion of the coefficients
* @param saturation_mode Controls the mode of operation of the saturation output
* @param out_reg Controls whether data_out and saturation are registered
*/
class CW_iir_dc(
val data_in_width: Int = 8,
val data_out_width: Int = 16,
val frac_data_out_width: Int = 4,
val feedback_width: Int = 12,
val max_coef_width: Int = 8,
val frac_coef_width: Int = 4,
val saturation_mode: Int = 0,
val out_reg: Int = 1)
extends BlackBox(
Map(
"data_in_width" -> data_in_width,
"data_out_width" -> data_out_width,
"frac_data_out_width" -> frac_data_out_width,
"feedback_width" -> feedback_width,
"max_coef_width" -> max_coef_width,
"frac_coef_width" -> frac_coef_width,
"saturation_mode" -> saturation_mode,
"out_reg" -> out_reg
)
) {
require(data_in_width >= 2, "data_in_width must be >= 2")
require(data_out_width >= 2, "data_out_width must be >= 2")
require(
frac_data_out_width >= 0 && frac_data_out_width < data_out_width,
"frac_data_out_width should be in range [0, data_out_width)"
)
require(feedback_width >= 2, "feedback_width must be >= 2")
require(max_coef_width >= 2, "max_coef_width must be >= 2")
require(
frac_coef_width >= 0 && frac_coef_width < max_coef_width,
"frac_coef_width should be in range [0, max_coef_width)"
)

val io = IO(new Bundle {
val clk: Clock = Input(Clock())
val rst_n: Bool = Input(Bool())
val init_n: Bool = Input(Bool())
val enable: Bool = Input(Bool())
val A1_coef: SInt = Input(SInt(max_coef_width.W))
val A2_coef: SInt = Input(SInt(max_coef_width.W))
val B0_coef: SInt = Input(SInt(max_coef_width.W))
val B1_coef: SInt = Input(SInt(max_coef_width.W))
val B2_coef: SInt = Input(SInt(max_coef_width.W))
val data_in: SInt = Input(SInt(data_in_width.W))
val data_out: SInt = Output(SInt(data_out_width.W))
val saturation: Bool = Output(Bool())
})
}
112 changes: 112 additions & 0 deletions chipware/src/CW_iir_sc.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import chisel3._
import chisel3.experimental._
import chisel3.util._

/**
* == CW_iir_sc ==
*
* === Abstract ===
*
* High-Speed Digital IIR Filter with Static Coefficients
*
* === Parameters ===
*
* | Parameter | Legal Range | Default | Description |
* |--------------------|--------------------------------------------------|---------|-----------------------------------------------------------------------------|
* | data_in_width | >=2 | 4 | Input data word length |
* | data_out_width | >=2 | 6 | Width of output data |
* | frac_data_out_width| 0 to data_out_width-1 | 0 | Width of fraction portion of data_out |
* | feedback_width | >=2 | 8 | Width of feedback_data (feedback_data is internal to the CW_iir_sc) |
* | max_coef_width | 2 to 31 | 4 | Maximum coefficient word length |
* | frac_coef_width | 0 to max_coef_width-1 | 0 | Width of the fraction portion of the coefficients |
* | saturation_mode | 0 or 1 | 1 | Controls the mode of operation of the saturation output |
* | out_reg | 0 or 1 | 1 | Controls whether data_out and saturation are registered |
* | A1_coef | -2<sup>(max_coef_width-1)</sup> to 2<sup>(max_coef_width-1)</sup> -1 | -2 | Constant coefficient value A1 |
* | A2_coef | -2<sup>(max_coef_width-1)</sup> to 2<sup>(max_coef_width-1)</sup> -1 | 3 | Constant coefficient value A2 |
* | B0_coef | -2<sup>(max_coef_width-1)</sup> to 2<sup>(max_coef_width-1)</sup> -1 | 5 | Constant coefficient value B0 |
* | B1_coef | -2<sup>(max_coef_width-1)</sup> to 2<sup>(max_coef_width-1)</sup> -1 | -6 | Constant coefficient value B1 |
* | B2_coef | -2<sup>(max_coef_width-1)</sup> to 2<sup>(max_coef_width-1)</sup> -1 | -2 | Constant coefficient value B2 |
*
* === Ports ===
*
* | Name | Width | Direction | Description |
* |--------------|---------------|-----------|-------------------------------------------------------------|
* | clk | 1 bit | Input | Clock signal. All internal registers are sensitive on the positive edge of clk and all setup and hold times are with respect to this edge of clk. |
* | rst_n | 1 bit | Input | Synchronous reset. Clears all registers |
* | init_n | 1 bit | Input | Synchronous signal to clear all registers |
* | enable | 1 bit | Input | Active-high signal to enable all registers |
* | data_in | data_in_width bit(s) | Input | Input data. |
* | data_out | data_out_width bit(s) | Output | Accumulated sum of products of the IIR filter. |
* | saturation | 1 bit | Output | Used to indicate the output data or feedback data is in saturation. |
*
* @param data_in_width Input data word length
* @param data_out_width Width of output data
* @param frac_data_out_width Width of fraction portion of data_out
* @param feedback_width Width of feedback_data (internal to CW_iir_sc)
* @param max_coef_width Maximum coefficient word length
* @param frac_coef_width Width of the fraction portion of the coefficients
* @param saturation_mode Controls the mode of operation of the saturation output
* @param out_reg Controls whether data_out and saturation are registered
* @param A1_coef Constant coefficient value A1
* @param A2_coef Constant coefficient value A2
* @param B0_coef Constant coefficient value B0
* @param B1_coef Constant coefficient value B1
* @param B2_coef Constant coefficient value B2
*/
class CW_iir_sc(
val data_in_width: Int = 4,
val data_out_width: Int = 6,
val frac_data_out_width: Int = 0,
val feedback_width: Int = 8,
val max_coef_width: Int = 4,
val frac_coef_width: Int = 0,
val saturation_mode: Int = 1,
val out_reg: Int = 1,
val A1_coef: Int = -2,
val A2_coef: Int = 3,
val B0_coef: Int = 5,
val B1_coef: Int = -6,
val B2_coef: Int = -2)
extends BlackBox(
Map(
"data_in_width" -> data_in_width,
"data_out_width" -> data_out_width,
"frac_data_out_width" -> frac_data_out_width,
"feedback_width" -> feedback_width,
"max_coef_width" -> max_coef_width,
"frac_coef_width" -> frac_coef_width,
"saturation_mode" -> saturation_mode,
"out_reg" -> out_reg,
"A1_coef" -> A1_coef,
"A2_coef" -> A2_coef,
"B0_coef" -> B0_coef,
"B1_coef" -> B1_coef,
"B2_coef" -> B2_coef
)
)
with HasBlackBoxPath {
require(data_in_width >= 2, "data_in_width must be >= 2")
require(data_out_width >= 2, "data_out_width must be >= 2")
require(
frac_data_out_width >= 0 && frac_data_out_width <= data_out_width - 1,
"frac_data_out_width should be in range [0, data_out_width - 1]"
)
require(feedback_width >= 2, "feedback_width must be >= 2")
require(max_coef_width >= 2 && max_coef_width <= 31, "max_coef_width should be in range [2, 31]")
require(
frac_coef_width >= 0 && frac_coef_width <= max_coef_width - 1,
"frac_coef_width should be in range [0, max_coef_width - 1]"
)
require(saturation_mode == 0 || saturation_mode == 1, "saturation_mode must be 0 or 1")
require(out_reg == 0 || out_reg == 1, "out_reg must be 0 or 1")

val io = IO(new Bundle {
val clk: Clock = Input(Clock())
val rst_n: Bool = Input(Bool())
val init_n: Bool = Input(Bool())
val enable: Bool = Input(Bool())
val data_in: UInt = Input(UInt(data_in_width.W))
val data_out: UInt = Output(UInt(data_out_width.W))
val saturation: Bool = Output(Bool())
})
}
69 changes: 69 additions & 0 deletions chipware/test/src/utest/iir_dc.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import chisel3._
import circt.stage._
import utest._

class iir_dc(
val data_in_width: Int = 8,
val data_out_width: Int = 16,
val frac_data_out_width: Int = 4,
val feedback_width: Int = 12,
val max_coef_width: Int = 8,
val frac_coef_width: Int = 4,
val saturation_mode: Int = 0,
val out_reg: Int = 1)
extends RawModule {

val io = IO(new Bundle {
val clk: Clock = Input(Clock())
val rst_n: Bool = Input(Bool())
val init_n: Bool = Input(Bool())
val enable: Bool = Input(Bool())
val A1_coef: SInt = Input(SInt(max_coef_width.W))
val A2_coef: SInt = Input(SInt(max_coef_width.W))
val B0_coef: SInt = Input(SInt(max_coef_width.W))
val B1_coef: SInt = Input(SInt(max_coef_width.W))
val B2_coef: SInt = Input(SInt(max_coef_width.W))
val data_in: SInt = Input(SInt(data_in_width.W))
val data_out: SInt = Output(SInt(data_out_width.W))
val saturation: Bool = Output(Bool())
})

protected val U1: CW_iir_dc = Module(
new CW_iir_dc(
data_in_width,
data_out_width,
frac_data_out_width,
feedback_width,
max_coef_width,
frac_coef_width,
saturation_mode,
out_reg
)
)
U1.io.clk := io.clk
U1.io.rst_n := io.rst_n
U1.io.init_n := io.init_n
U1.io.enable := io.enable
U1.io.A1_coef := io.A1_coef
U1.io.A2_coef := io.A2_coef
U1.io.B0_coef := io.B0_coef
U1.io.B1_coef := io.B1_coef
U1.io.B2_coef := io.B2_coef
U1.io.data_in := io.data_in
io.data_out := U1.io.data_out
io.saturation := U1.io.saturation
}

object iir_dc extends TestSuite {
val tests: Tests = Tests {
test("should instantiate iir_dc") {
def top = new iir_dc(8, 16, 4, 12, 8, 4, 0, 1)

val generator = Seq(chisel3.stage.ChiselGeneratorAnnotation(() => top))
(new ChiselStage).execute(
args = Array("--target-dir", "./build"),
annotations = generator :+ CIRCTTargetAnnotation(CIRCTTarget.SystemVerilog)
)
}
}
}
70 changes: 70 additions & 0 deletions chipware/test/src/utest/iir_sc.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import chisel3._
import circt.stage._
import utest._

class iir_sc(
data_in_width: Int = 4,
data_out_width: Int = 6,
frac_data_out_width: Int = 0,
feedback_width: Int = 8,
max_coef_width: Int = 4,
frac_coef_width: Int = 0,
saturation_mode: Int = 1,
out_reg: Int = 1,
A1_coef: Int = -2,
A2_coef: Int = 3,
B0_coef: Int = 5,
B1_coef: Int = -6,
B2_coef: Int = -2)
extends RawModule {

val io = IO(new Bundle {
val clk: Clock = Input(Clock())
val rst_n: Bool = Input(Bool())
val init_n: Bool = Input(Bool())
val enable: Bool = Input(Bool())
val data_in: UInt = Input(UInt(data_in_width.W))
val data_out: UInt = Output(UInt(data_out_width.W))
val saturation: Bool = Output(Bool())
})

protected val U1: CW_iir_sc = Module(
new CW_iir_sc(
data_in_width,
data_out_width,
frac_data_out_width,
feedback_width,
max_coef_width,
frac_coef_width,
saturation_mode,
out_reg,
A1_coef,
A2_coef,
B0_coef,
B1_coef,
B2_coef
)
)

U1.io.clk := io.clk
U1.io.rst_n := io.rst_n
U1.io.init_n := io.init_n
U1.io.enable := io.enable
U1.io.data_in := io.data_in
io.data_out := U1.io.data_out
io.saturation := U1.io.saturation
}

object iir_sc extends TestSuite {
val tests: Tests = Tests {
test("should instantiate CW_iir_scWrapper") {
def top = new iir_sc(4, 6, 0, 8, 4, 0, 1, 1, -2, 3, 5, -6, -2)

val generator = Seq(chisel3.stage.ChiselGeneratorAnnotation(() => top))
(new ChiselStage).execute(
args = Array("--target-dir", "./build"),
annotations = generator :+ CIRCTTargetAnnotation(CIRCTTarget.SystemVerilog)
)
}
}
}

0 comments on commit 802eaad

Please sign in to comment.