diff --git a/chipware/src/CW_tap.scala b/chipware/src/CW_tap.scala new file mode 100644 index 0000000..3d9aa6a --- /dev/null +++ b/chipware/src/CW_tap.scala @@ -0,0 +1,105 @@ +import chisel3._ +import chisel3.experimental._ +import chisel3.util._ + +/** + * == CW_tap == + * + * === Abstract === + * + * TAP Controller + * + * === Parameters === + * + * | Parameter | Legal Range | Default | Description | + * |------------|--------------|----------|--------------| + * | width | 2 to 32 | 2 | Width of instruction register | + * | id | 0 or 1 | 0 | Determines whether the device identification register is present. 0 = not present, 1 = present | + * | version | 0 to 15 | 0 | 4-bit version number | + * | part | 0 to 65535 | 0 | 16-bit part number | + * | man_num | 0 to 2047, man_num !=127 | 0 | 11-bit JEDEC manufacturer identity code | + * | sync_mode | 0 or 1 | 0 | Determines whether the bypass, device identification, and instruction registers are synchronous with respect to tck. 0 = asynchronous, 1 = synchronous | + * + * === Ports === + * + * | Name | Width | Direction | Description | + * |----------------|--------------|-----------|--------------| + * | tck | 1 bit | Input | Test clock | + * | trst_n | 1 bit | Input | Test reset, active low | + * | tms | 1 bit | Input | Test mode select | + * | tdi | 1 bit | Input | Test data in | + * | so | 1 bit | Input | Serial data from boundary scan registers and data registers | + * | bypass_sel | 1 bit | Input | Selects bypass register, active high | + * | sentinel_val | width-1 bit(s) | Input | User defined status bits | + * | clock_dr | 1 bit | Output | Clock's in data in asynchronous mode | + * | shift_dr | 1 bit | Output | Enables shifting of data in both synchronous and asynchronous mode | + * | update_dr | 1 bit | Output | Enables updating data in asynchronous mode | + * | tdo | 1 bit | Output | Test data out | + * | tdo_en | 1 bit | Output | Enables for tdo output buffer | + * | tap_state | 16 bits | Output | Current state of the TAP finite state machine | + * | extest | 1 bit | Output | EXTEST decoded instruction | + * | samp_load | 1 bit | Output | SAMPLE/PRELOAD decoded instruction | + * | instructions | width bit(s) | Output | Instruction register output | + * | sync_capture_en | 1 bit | Output | Enable for synchronous capture | + * | sync_update_dr | 1 bit | Output | Enable updating new data in | + * | test | 1 bit | Input | For scannable designs, the test_mode pin is held active (HIGH) during testing. For normal operation , it is held inactive (LOW) | + * + * @param width Width of instruction register + * @param id Determines whether the device identification register is present. 0 = not present, 1 = present + * @param version 4-bit version number + * @param part 16-bit part number + * @param man_num 11-bit JEDEC manufacturer identity code + * @param sync_mode Determines whether the bypass, device identification, and instruction registers are synchronous with respect to tck. 0 = asynchronous, 1 = synchronous + */ +class CW_tap( + val width: Int = 2, + val id: Int = 0, + val version: Int = 0, + val part: Int = 0, + val man_num: Int = 0, + val sync_mode: Int = 0) + extends BlackBox( + Map( + "width" -> width, + "id" -> id, + "version" -> version, + "part" -> part, + "man_num" -> man_num, + "sync_mode" -> sync_mode + ) + ) + with HasBlackBoxPath { + // Validation of all parameters + require(width >= 2 && width <= 32, "width must be in the range [2, 32]") + require(id == 0 || id == 1, "id must be 0 or 1") + require(version >= 0 && version <= 15, "version must be in the range [0, 15]") + require(part >= 0 && part <= 65535, "part must be in the range [0, 65535]") + require( + man_num >= 0 && man_num <= 2047 && man_num != 127, + "man_num must be in the range [0, 2047] and not equal to 127" + ) + require(sync_mode == 0 || sync_mode == 1, "sync_mode must be 0 or 1") + + // Define ports with type annotations + val io = IO(new Bundle { + val tck: Clock = Input(Clock()) + val trst_n: Bool = Input(Bool()) + val tms: Bool = Input(Bool()) + val tdi: Bool = Input(Bool()) + val so: Bool = Input(Bool()) + val bypass_sel: Bool = Input(Bool()) + val sentinel_val: UInt = Input(UInt((width - 1).W)) + val clock_dr: Bool = Output(Bool()) + val shift_dr: Bool = Output(Bool()) + val update_dr: Bool = Output(Bool()) + val tdo: Bool = Output(Bool()) + val tdo_en: Bool = Output(Bool()) + val tap_state: UInt = Output(UInt(16.W)) + val extest: Bool = Output(Bool()) + val samp_load: Bool = Output(Bool()) + val instructions: UInt = Output(UInt(width.W)) + val sync_capture_en: Bool = Output(Bool()) + val sync_update_dr: Bool = Output(Bool()) + val test: Bool = Input(Bool()) + }) +} diff --git a/chipware/src/CW_tap_uc.scala b/chipware/src/CW_tap_uc.scala new file mode 100644 index 0000000..9310cdc --- /dev/null +++ b/chipware/src/CW_tap_uc.scala @@ -0,0 +1,127 @@ +import chisel3._ +import chisel3.util._ +import chisel3.experimental._ + +/** + * == CW_tap_uc == + * + * === Abstract === + * + * TAP Controller with Usercode support. + * + * === Parameters === + * + * | Parameter | Legal Range | Default | Description | + * |----------------|------------------------------|----------|-----------------------------------------| + * | width | 2 to 32 | 2 | Width of instruction register | + * | id | 0 or 1 | 0 | Determines presence of ID register | + * | idcode_opcode | 1 to ((2(width))-1) | 1 | Opcode for IDCODE instruction | + * | version | 0 to 15 | 0 | 4-bit version number | + * | part | 0 to 65535 | 0 | 16-bit part number | + * | man_num | 0 to 2047, man_num != 127 | 0 | 11-bit JEDEC manufacturer identity code| + * | sync_mode | 0 or 1 | 0 | Synchronous mode for registers | + * | tst_mode | 0 or 1 | 0 | Test pin control | + * + * === Ports === + * + * | Name | Width | Direction | Description | + * |----------------|------------------------------|-----------|-----------------------------------------| + * | tck | 1 bit | Input | Test clock | + * | trst_n | 1 bit | Input | Test reset, active low | + * | tms | 1 bit | Input | Test mode select | + * | tdi | 1 bit | Input | Test data in | + * | so | 1 bit | Input | Serial data from boundary scan registers and data registers | + * | bypass_sel | 1 bit | Input | Selects bypass register, active high | + * | sentinel_val | width - 2 (s) bits | Input | User defined status bits | + * | ver_sel | 1 bit | Input | Selects version from parameter or ver input port | + * | device_id_sel | 1 bit | Input | Selects device identification register, active high | + * | user_code_sel | 1 bit | Input | Selects user_code_val bus for input into device identification register, active high | + * | user_code_val | 32 bits | Input | 32-bit user defined code | + * | ver | 4 bits | Input | 4-bit version number | + * | part_num | 16 bits | Input | 16-bit part number | + * | part_num_sel | 1 bit | Input | Selects part from parameter or part_num from input port | + * | mnfr_id | 11 bits | Input | 11-bit JEDEC manufacturer's identity code (mnfr_id != 127) | + * | mnfr_id_sel | 1 bit | Input | Selects man_num from parameter or mnfr_id from input port | + * | test | 1 bit | Input | Scantest enable pin, NOT used in CW | + * | clock_dr | 1 bit | Output | Clock's in data in asynchronous mode | + * | shift_dr | 1 bit | Output | Enables shifting of data in both synchronous and asynchronous mode | + * | update_dr | 1 bit | Output | Enables updating data in asynchronous mode | + * | tdo | 1 bit | Output | Test data out | + * | tdo_en | 1 bit | Output | Enables for tdo output buffer | + * | tap_state | 16 bits | Output | Current state of the TAP finite state machine | + * | instructions | width bit(s) | Output | Instruction register output | + * | sync_capture_en | 1 bit | Output | Enable for synchronous capture | + * | sync_update_dr | 1 bit | Output | Enable updating new data in synchronous mode | + * + * @param width Width of instruction register + * @param id Determines presence of ID register + * @param idcode_opcode Opcode for IDCODE instruction + * @param version 4-bit version number + * @param part 16-bit part number + * @param man_num 11-bit JEDEC manufacturer identity code + * @param sync_mode Synchronous mode for registers + * @param tst_mode Test pin control + */ +class CW_tap_uc( + val width: Int = 2, + val id: Int = 0, + val idcode_opcode: Int = 1, + val version: Int = 0, + val part: Int = 0, + val man_num: Int = 0, + val sync_mode: Int = 0, + val tst_mode: Int = 0) + extends BlackBox( + Map( + "width" -> width, + "id" -> id, + "idcode_opcode" -> idcode_opcode, + "version" -> version, + "part" -> part, + "man_num" -> man_num, + "sync_mode" -> sync_mode, + "tst_mode" -> tst_mode + ) + ) + with HasBlackBoxPath { + // Add validations for parameters + require(width >= 2 && width <= 32, "width must be between 2 and 32") + require(id == 0 || id == 1, "id must be 0 or 1") + require(idcode_opcode >= 1 && idcode_opcode < Math.pow(2, width), "idcode_opcode out of range") + require(version >= 0 && version <= 15, "version must be between 0 and 15") + require(part >= 0 && part <= 65535, "part must be between 0 and 65535") + require(man_num >= 0 && man_num <= 2047 && man_num != 127, "man_num must be between 0 and 2047 (excluding 127)") + require(sync_mode == 0 || sync_mode == 1, "sync_mode must be 0 or 1") + require(tst_mode == 0 || tst_mode == 1, "tst_mode must be 0 or 1") + + // Define ports with type annotations + val io = IO(new Bundle { + val tck: Bool = Input(Bool()) // Test clock + val trst_n: Bool = Input(Bool()) // Test reset, active low + val tms: Bool = Input(Bool()) // Test mode select + val tdi: Bool = Input(Bool()) // Test data in + val so: Bool = Input(Bool()) // Serial data from boundary scan registers and data registers + val bypass_sel: Bool = Input(Bool()) // Selects bypass register, active high + val sentinel_val: UInt = Input(UInt((width - 2).W)) // User defined status bits + val ver_sel: Bool = Input(Bool()) // Selects version from parameter or ver input port + val device_id_sel: Bool = Input(Bool()) // Selects device identification register, active high + val user_code_sel: Bool = + Input(Bool()) // Selects user_code_val bus for input into device identification register, active high + val user_code_val: UInt = Input(UInt(32.W)) // 32-bit user defined code + val ver: UInt = Input(UInt(4.W)) // 4-bit version number + val part_num: UInt = Input(UInt(16.W)) // 16-bit part number + val part_num_sel: Bool = Input(Bool()) // Selects part from parameter or part_num from input port + val mnfr_id: UInt = Input(UInt(11.W)) // 11-bit JEDEC manufacturer's identity code (mnfr_id != 127) + val mnfr_id_sel: Bool = Input(Bool()) // Selects man_num from parameter or mnfr_id from input port + val test: Bool = Input(Bool()) // Scantest enable pin, NOT used in CW + val clock_dr: Bool = Output(Bool()) // Clock's in data in asynchronous mode + val shift_dr: Bool = Output(Bool()) // Enables shifting of data in both synchronous and asynchronous mode + val update_dr: Bool = Output(Bool()) // Enables updating data in asynchronous mode + val tdo: Bool = Output(Bool()) // Test data out + val tdo_en: Bool = Output(Bool()) // Enables for tdo output buffer + val tap_state: UInt = Output(UInt(16.W)) // Current state of the TAP finite state machine + val instructions: UInt = Output(UInt(width.W)) // Instruction register output + val sync_capture_en: Bool = Output(Bool()) // Enable for synchronous capture + val sync_update_dr: Bool = Output(Bool()) // Enable updating new data in synchronous mode + }) +} diff --git a/chipware/src/CW_thermdec.scala b/chipware/src/CW_thermdec.scala new file mode 100644 index 0000000..f3772d4 --- /dev/null +++ b/chipware/src/CW_thermdec.scala @@ -0,0 +1,43 @@ +import chisel3._ +import chisel3.experimental._ +import chisel3.util._ + +/** + * == CW_thermdec == + * + * === Abstract === + * + * Decoder + * + * === Parameters === + * + * | Parameter | Legal Range | Default | Description | + * |---------------|--------------|--------------|----------------| + * | width | 1 to 16 | 3 | Bit width of input a | + * + * === Ports === + * + * | Name | Width | Direction | Description | + * |--------|--------------|-----------|------------------------| + * | en | 1 | Input | Enable input (active high) | + * | a | width | Input | Binary Input | + * | b | 2width | Output | Decode output | + * @param width Bit width of input a + */ +class CW_thermdec(val width: Int = 3) + extends BlackBox( + Map( + "width" -> width + ) + ) + with HasBlackBoxPath { + // Validation of width parameter + require(width >= 1 && width <= 16, "width must be in the range [1, 16]") + + // Define ports with type annotations + val io = IO(new Bundle { + val en: Bool = Input(Bool()) + val a: UInt = Input(UInt(width.W)) + val b: UInt = Output(UInt((1 << width).W)) + }) +} diff --git a/chipware/test/src/utest/tap.scala b/chipware/test/src/utest/tap.scala new file mode 100644 index 0000000..39f5a46 --- /dev/null +++ b/chipware/test/src/utest/tap.scala @@ -0,0 +1,69 @@ +import chisel3._ +import circt.stage._ +import utest._ + +class tap( + val width: Int = 2, + val id: Int = 0, + val version: Int = 0, + val part: Int = 0, + val man_num: Int = 0, + val sync_mode: Int = 0) + extends RawModule { + val io = IO(new Bundle { + val tck: Clock = Input(Clock()) + val trst_n: Bool = Input(Bool()) + val tms: Bool = Input(Bool()) + val tdi: Bool = Input(Bool()) + val so: Bool = Input(Bool()) + val bypass_sel: Bool = Input(Bool()) + val sentinel_val: UInt = Input(UInt((width - 1).W)) + val clock_dr: Bool = Output(Bool()) + val shift_dr: Bool = Output(Bool()) + val update_dr: Bool = Output(Bool()) + val tdo: Bool = Output(Bool()) + val tdo_en: Bool = Output(Bool()) + val tap_state: UInt = Output(UInt(16.W)) + val extest: Bool = Output(Bool()) + val samp_load: Bool = Output(Bool()) + val instructions: UInt = Output(UInt(width.W)) + val sync_capture_en: Bool = Output(Bool()) + val sync_update_dr: Bool = Output(Bool()) + val test: Bool = Input(Bool()) + }) + + protected val U1: CW_tap = Module(new CW_tap(width, id, version, part, man_num, sync_mode)) + U1.io.tck := io.tck + U1.io.trst_n := io.trst_n + U1.io.tms := io.tms + U1.io.tdi := io.tdi + U1.io.so := io.so + U1.io.bypass_sel := io.bypass_sel + U1.io.sentinel_val := io.sentinel_val + U1.io.test := io.test + io.clock_dr := U1.io.clock_dr + io.shift_dr := U1.io.shift_dr + io.update_dr := U1.io.update_dr + io.tdo := U1.io.tdo + io.tdo_en := U1.io.tdo_en + io.tap_state := U1.io.tap_state + io.extest := U1.io.extest + io.samp_load := U1.io.samp_load + io.instructions := U1.io.instructions + io.sync_capture_en := U1.io.sync_capture_en + io.sync_update_dr := U1.io.sync_update_dr +} + +object tap extends TestSuite { + val tests: Tests = Tests { + test("should instantiate tapTester") { + def top = new tap(2, 0, 0, 0, 0, 0) + + val generator = Seq(chisel3.stage.ChiselGeneratorAnnotation(() => top)) + (new ChiselStage).execute( + args = Array("--target-dir", "./build"), + annotations = generator :+ CIRCTTargetAnnotation(CIRCTTarget.SystemVerilog) + ) + } + } +} diff --git a/chipware/test/src/utest/tap_uc.scala b/chipware/test/src/utest/tap_uc.scala new file mode 100644 index 0000000..2ac65a4 --- /dev/null +++ b/chipware/test/src/utest/tap_uc.scala @@ -0,0 +1,89 @@ +import chisel3._ +import circt.stage._ +import utest._ + +class tap_uc( + val width: Int = 2, + val id: Int = 0, + val idcode_opcode: Int = 1, + val version: Int = 0, + val part: Int = 0, + val man_num: Int = 0, + val sync_mode: Int = 0, + val tst_mode: Int = 0) + extends RawModule { + val io = IO(new Bundle { + val tck: Bool = Input(Bool()) // Test clock + val trst_n: Bool = Input(Bool()) // Test reset, active low + val tms: Bool = Input(Bool()) // Test mode select + val tdi: Bool = Input(Bool()) // Test data in + val so: Bool = Input(Bool()) // Serial data from boundary scan registers and data registers + val bypass_sel: Bool = Input(Bool()) // Selects bypass register, active high + val sentinel_val: UInt = Input(UInt((width - 2).W)) // User defined status bits + val ver_sel: Bool = Input(Bool()) // Selects version from parameter or ver input port + val device_id_sel: Bool = Input(Bool()) // Selects device identification register, active high + val user_code_sel: Bool = + Input(Bool()) // Selects user_code_val bus for input into device identification register, active high + val user_code_val: UInt = Input(UInt(32.W)) // 32-bit user defined code + val ver: UInt = Input(UInt(4.W)) // 4-bit version number + val part_num: UInt = Input(UInt(16.W)) // 16-bit part number + val part_num_sel: Bool = Input(Bool()) // Selects part from parameter or part_num from input port + val mnfr_id: UInt = Input(UInt(11.W)) // 11-bit JEDEC manufacturer's identity code (mnfr_id != 127) + val mnfr_id_sel: Bool = Input(Bool()) // Selects man_num from parameter or mnfr_id from input port + val test: Bool = Input(Bool()) // Scantest enable pin, NOT used in CW + val clock_dr: Bool = Output(Bool()) // Clock's in data in asynchronous mode + val shift_dr: Bool = Output(Bool()) // Enables shifting of data in both synchronous and asynchronous mode + val update_dr: Bool = Output(Bool()) // Enables updating data in asynchronous mode + val tdo: Bool = Output(Bool()) // Test data out + val tdo_en: Bool = Output(Bool()) // Enables for tdo output buffer + val tap_state: UInt = Output(UInt(16.W)) // Current state of the TAP finite state machine + val instructions: UInt = Output(UInt(width.W)) // Instruction register output + val sync_capture_en: Bool = Output(Bool()) // Enable for synchronous capture + val sync_update_dr: Bool = Output(Bool()) // Enable updating new data in synchronous mode + }) + + // Define the BlackBox instantiation + protected val U1: CW_tap_uc = Module( + new CW_tap_uc(width, id, idcode_opcode, version, part, man_num, sync_mode, tst_mode) + ) + U1.io.tck := io.tck + U1.io.trst_n := io.trst_n + U1.io.tms := io.tms + U1.io.tdi := io.tdi + U1.io.so := io.so + U1.io.bypass_sel := io.bypass_sel + U1.io.sentinel_val := io.sentinel_val + U1.io.ver_sel := io.ver_sel + U1.io.device_id_sel := io.device_id_sel + U1.io.user_code_sel := io.user_code_sel + U1.io.user_code_val := io.user_code_val + U1.io.ver := io.ver + U1.io.part_num := io.part_num + U1.io.part_num_sel := io.part_num_sel + U1.io.mnfr_id := io.mnfr_id + U1.io.mnfr_id_sel := io.mnfr_id_sel + U1.io.test := io.test + io.clock_dr := U1.io.clock_dr + io.shift_dr := U1.io.shift_dr + io.update_dr := U1.io.update_dr + io.tdo := U1.io.tdo + io.tdo_en := U1.io.tdo_en + io.tap_state := U1.io.tap_state + io.instructions := U1.io.instructions + io.sync_capture_en := U1.io.sync_capture_en + io.sync_update_dr := U1.io.sync_update_dr +} + +object tap_uc extends TestSuite { + val tests: Tests = Tests { + test("should instantiate tap_uc") { + def top = new tap_uc(2, 1, 1, 0, 0, 0, 0, 0) + + val generator = Seq(chisel3.stage.ChiselGeneratorAnnotation(() => top)) + (new ChiselStage).execute( + args = Array("--target-dir", "./build"), + annotations = generator :+ CIRCTTargetAnnotation(CIRCTTarget.SystemVerilog) + ) + } + } +} diff --git a/chipware/test/src/utest/thermdec.scala b/chipware/test/src/utest/thermdec.scala new file mode 100644 index 0000000..3ec57b5 --- /dev/null +++ b/chipware/test/src/utest/thermdec.scala @@ -0,0 +1,30 @@ +import chisel3._ +import circt.stage._ +import utest._ + +class thermdec(val width: Int = 3) extends RawModule { + val io = IO(new Bundle { + val en: Bool = Input(Bool()) + val a: UInt = Input(UInt(width.W)) + val b: UInt = Output(UInt((1 << width).W)) + }) + + protected val U1: CW_thermdec = Module(new CW_thermdec(width)) + U1.io.en := io.en + U1.io.a := io.a + io.b := U1.io.b +} + +object thermdec extends TestSuite { + val tests: Tests = Tests { + test("should instantiate thermdec") { + def top = new thermdec(3) + + val generator = Seq(chisel3.stage.ChiselGeneratorAnnotation(() => top)) + (new ChiselStage).execute( + args = Array("--target-dir", "./build"), + annotations = generator :+ CIRCTTargetAnnotation(CIRCTTarget.SystemVerilog) + ) + } + } +}