or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

binary-types.mdclock-generation.mdindex.mdlogging-utilities.mdsignal-handling.mdtask-management.mdtest-framework.mdtriggers-timing.md

binary-types.mddocs/

0

# Binary and Type System

1

2

Cocotb's binary and type system provides HDL-compatible data types for representing and manipulating binary values, logic states, arrays, and ranges. The system supports multiple binary representations, 4-value logic, and HDL-style indexing and slicing operations.

3

4

## Capabilities

5

6

### Binary Value Representation

7

8

Core class for representing binary values with multiple formats and automatic conversion capabilities.

9

10

```python { .api }

11

class BinaryValue(value=None, n_bits=None, bigEndian=True, binaryRepresentation=BinaryRepresentation.UNSIGNED):

12

"""

13

Binary value representation supporting multiple formats and bit manipulations.

14

15

Parameters:

16

- value: Initial value (int, str, bytes, or BinaryValue)

17

- n_bits: Number of bits (auto-detected if None)

18

- bigEndian: True for big-endian bit ordering

19

- binaryRepresentation: Binary format (UNSIGNED, SIGNED_MAGNITUDE, TWOS_COMPLEMENT)

20

21

Properties:

22

- integer: Value as unsigned integer

23

- signed_integer: Value as signed integer

24

- binstr: Binary string representation

25

- buff: Raw buffer data

26

- n_bits: Number of bits

27

- is_resolvable: True if value contains no X/Z states

28

29

Methods:

30

- assign(value): Assign new value

31

- hex(): Hexadecimal string representation

32

"""

33

34

@property

35

def integer(self) -> int:

36

"""Get value as unsigned integer."""

37

38

@property

39

def signed_integer(self) -> int:

40

"""Get value as signed integer."""

41

42

@property

43

def binstr(self) -> str:

44

"""Get binary string representation."""

45

46

@property

47

def buff(self) -> bytes:

48

"""Get raw buffer data."""

49

50

@property

51

def n_bits(self) -> int:

52

"""Get number of bits."""

53

54

@property

55

def is_resolvable(self) -> bool:

56

"""Check if value contains no X/Z states."""

57

58

def assign(self, value):

59

"""

60

Assign new value to BinaryValue.

61

62

Parameters:

63

- value: New value to assign

64

"""

65

66

def hex(self) -> str:

67

"""

68

Get hexadecimal string representation.

69

70

Returns:

71

Hexadecimal string (e.g., "0xABCD")

72

"""

73

74

class BinaryRepresentation:

75

"""Binary representation format constants."""

76

UNSIGNED = "UNSIGNED"

77

SIGNED_MAGNITUDE = "SIGNED_MAGNITUDE"

78

TWOS_COMPLEMENT = "TWOS_COMPLEMENT"

79

```

80

81

**Usage Examples:**

82

83

```python

84

@cocotb.test()

85

async def binary_value_test(dut):

86

"""Test demonstrating BinaryValue operations."""

87

88

# Create binary values with different representations

89

unsigned_val = BinaryValue(42, n_bits=8, binaryRepresentation=BinaryRepresentation.UNSIGNED)

90

signed_val = BinaryValue(-42, n_bits=8, binaryRepresentation=BinaryRepresentation.TWOS_COMPLEMENT)

91

92

# Access different representations

93

cocotb.log.info(f"Unsigned 42: binary={unsigned_val.binstr}, hex={unsigned_val.hex()}")

94

cocotb.log.info(f"Signed -42: binary={signed_val.binstr}, hex={signed_val.hex()}")

95

96

# Convert from different sources

97

from_string = BinaryValue("10101010", n_bits=8)

98

from_int = BinaryValue(170, n_bits=8)

99

from_hex = BinaryValue(0xAA, n_bits=8)

100

101

# All should be equivalent

102

assert from_string.integer == from_int.integer == from_hex.integer

103

104

# Assign to DUT signals

105

dut.data_bus.value = unsigned_val

106

await Timer(10, units="ns")

107

108

# Read back and verify

109

readback = BinaryValue(dut.data_bus.value, n_bits=8)

110

assert readback.integer == 42

111

112

@cocotb.test()

113

async def binary_formats_test(dut):

114

"""Test different binary representation formats."""

115

116

# Test unsigned format

117

unsigned = BinaryValue(200, n_bits=8, binaryRepresentation=BinaryRepresentation.UNSIGNED)

118

cocotb.log.info(f"Unsigned 200: {unsigned.integer} (0x{unsigned.integer:02X})")

119

120

# Test two's complement

121

twos_comp = BinaryValue(-56, n_bits=8, binaryRepresentation=BinaryRepresentation.TWOS_COMPLEMENT)

122

cocotb.log.info(f"2's complement -56: signed={twos_comp.signed_integer}, unsigned={twos_comp.integer}")

123

124

# Test sign-magnitude (rarely used)

125

sign_mag = BinaryValue(-56, n_bits=8, binaryRepresentation=BinaryRepresentation.SIGNED_MAGNITUDE)

126

cocotb.log.info(f"Sign-magnitude -56: {sign_mag.binstr}")

127

128

# Test big vs little endian

129

big_endian = BinaryValue(0x1234, n_bits=16, bigEndian=True)

130

little_endian = BinaryValue(0x1234, n_bits=16, bigEndian=False)

131

132

cocotb.log.info(f"Big endian 0x1234: {big_endian.binstr}")

133

cocotb.log.info(f"Little endian 0x1234: {little_endian.binstr}")

134

```

135

136

### Binary Utility Functions

137

138

Utility functions for binary string manipulation and X/Z value resolution.

139

140

```python { .api }

141

def resolve(string):

142

"""

143

Resolve X/Z values in binary string.

144

145

Converts X and Z characters to 0 for numeric operations.

146

147

Parameters:

148

- string: Binary string potentially containing X/Z

149

150

Returns:

151

Binary string with X/Z resolved to 0

152

"""

153

```

154

155

**Usage Examples:**

156

157

```python

158

@cocotb.test()

159

async def binary_utilities_test(dut):

160

"""Test demonstrating binary utility functions."""

161

162

# Handle X/Z values in signals

163

dut.test_signal.value = "10X1Z010" # String with X/Z

164

await Timer(1, units="ns")

165

166

# Read back signal value

167

signal_value = str(dut.test_signal.value)

168

cocotb.log.info(f"Signal with X/Z: {signal_value}")

169

170

# Resolve X/Z for numeric operations

171

resolved = resolve(signal_value)

172

cocotb.log.info(f"Resolved value: {resolved}")

173

174

# Convert to numeric value

175

numeric_val = BinaryValue(resolved)

176

cocotb.log.info(f"Numeric value: {numeric_val.integer}")

177

178

# Check if value is fully resolvable

179

test_values = ["11010101", "110X0101", "110Z0101", "XXXXXXXX"]

180

181

for test_val in test_values:

182

bv = BinaryValue(test_val)

183

cocotb.log.info(f"Value {test_val}: resolvable={bv.is_resolvable}")

184

```

185

186

### 4-Value Logic System

187

188

HDL-compatible logic types supporting 0, 1, X (unknown), and Z (high-impedance) states.

189

190

```python { .api }

191

class Logic:

192

"""

193

4-value logic type supporting 0, 1, X, Z states.

194

195

Constants:

196

- Logic.0: Logic 0 state

197

- Logic.1: Logic 1 state

198

- Logic.X: Unknown/uninitialized state

199

- Logic.Z: High-impedance state

200

201

Operations:

202

- & (and): Bitwise AND operation

203

- | (or): Bitwise OR operation

204

- ^ (xor): Bitwise XOR operation

205

- ~ (not): Bitwise NOT operation

206

"""

207

208

# Type alias for backward compatibility

209

Bit = Logic

210

211

class LogicArray:

212

"""

213

Array of Logic values with HDL semantics.

214

215

Properties:

216

- binstr: Binary string representation

217

- integer: Integer value (X/Z resolved to 0)

218

- signed_integer: Signed integer value

219

220

Methods:

221

- to_BinaryValue(): Convert to BinaryValue object

222

"""

223

224

@property

225

def binstr(self) -> str:

226

"""Get binary string representation."""

227

228

@property

229

def integer(self) -> int:

230

"""Get integer value (X/Z resolved to 0)."""

231

232

@property

233

def signed_integer(self) -> int:

234

"""Get signed integer value."""

235

236

def to_BinaryValue(self):

237

"""

238

Convert to BinaryValue object.

239

240

Returns:

241

BinaryValue representation of the LogicArray

242

"""

243

```

244

245

**Usage Examples:**

246

247

```python

248

@cocotb.test()

249

async def logic_types_test(dut):

250

"""Test demonstrating 4-value logic operations."""

251

252

# Create individual logic values

253

from cocotb.types import Logic

254

255

zero = Logic.0

256

one = Logic.1

257

unknown = Logic.X

258

high_z = Logic.Z

259

260

# Logic operations

261

and_result = one & zero # Should be Logic.0

262

or_result = one | zero # Should be Logic.1

263

xor_result = one ^ one # Should be Logic.0

264

not_result = ~zero # Should be Logic.1

265

266

cocotb.log.info(f"Logic operations:")

267

cocotb.log.info(f" 1 & 0 = {and_result}")

268

cocotb.log.info(f" 1 | 0 = {or_result}")

269

cocotb.log.info(f" 1 ^ 1 = {xor_result}")

270

cocotb.log.info(f" ~0 = {not_result}")

271

272

# Unknown value propagation

273

unknown_and = one & unknown # Should be Logic.X

274

unknown_or = zero | unknown # Should be Logic.X

275

276

cocotb.log.info(f"Unknown propagation:")

277

cocotb.log.info(f" 1 & X = {unknown_and}")

278

cocotb.log.info(f" 0 | X = {unknown_or}")

279

280

@cocotb.test()

281

async def logic_array_test(dut):

282

"""Test demonstrating LogicArray operations."""

283

284

from cocotb.types import LogicArray, Logic

285

286

# Create logic arrays

287

array1 = LogicArray([Logic.1, Logic.0, Logic.1, Logic.0]) # 0b1010

288

array2 = LogicArray([Logic.0, Logic.1, Logic.X, Logic.Z]) # with X and Z

289

290

# Access properties

291

cocotb.log.info(f"Array1 binary: {array1.binstr}")

292

cocotb.log.info(f"Array1 integer: {array1.integer}")

293

294

cocotb.log.info(f"Array2 binary: {array2.binstr}")

295

cocotb.log.info(f"Array2 integer: {array2.integer}") # X/Z resolved to 0

296

297

# Convert to BinaryValue

298

bv1 = array1.to_BinaryValue()

299

bv2 = array2.to_BinaryValue()

300

301

cocotb.log.info(f"BinaryValue1: 0x{bv1.integer:X}")

302

cocotb.log.info(f"BinaryValue2 resolvable: {bv2.is_resolvable}")

303

304

# Use with DUT signals

305

dut.logic_signal.value = array1

306

await Timer(10, units="ns")

307

```

308

309

### Container Types

310

311

HDL-compatible container types for arrays and ranges with proper indexing semantics.

312

313

```python { .api }

314

class Array[T](obj, range):

315

"""

316

Fixed-size arbitrarily-indexed array.

317

318

Parameters:

319

- obj: Object to wrap as array

320

- range: Range object defining array bounds

321

322

Properties:

323

- range: Range object for array bounds

324

325

Supports:

326

- Indexing: array[index]

327

- Slicing: array[start:end]

328

- Iteration: for item in array

329

"""

330

331

@property

332

def range(self):

333

"""Get range object defining array bounds."""

334

335

class Range(left, direction, right):

336

"""

337

HDL-style inclusive range specification.

338

339

Parameters:

340

- left: Left bound of range

341

- direction: "to" or "downto"

342

- right: Right bound of range

343

344

Properties:

345

- left: Left bound

346

- right: Right bound

347

- direction: Range direction

348

349

Methods:

350

- to_range(): Convert to Python range object

351

- from_range(range): Create Range from Python range

352

"""

353

354

@property

355

def left(self) -> int:

356

"""Get left bound of range."""

357

358

@property

359

def right(self) -> int:

360

"""Get right bound of range."""

361

362

@property

363

def direction(self) -> str:

364

"""Get range direction ('to' or 'downto')."""

365

366

def to_range(self):

367

"""

368

Convert to Python range object.

369

370

Returns:

371

Python range object with equivalent bounds

372

"""

373

374

@classmethod

375

def from_range(cls, range):

376

"""

377

Create Range from Python range object.

378

379

Parameters:

380

- range: Python range object

381

382

Returns:

383

Range object with equivalent bounds

384

"""

385

```

386

387

**Usage Examples:**

388

389

```python

390

@cocotb.test()

391

async def container_types_test(dut):

392

"""Test demonstrating container type operations."""

393

394

from cocotb.types import Array, Range

395

396

# Create HDL-style ranges

397

range1 = Range(31, "downto", 0) # 32-bit word, MSB first

398

range2 = Range(0, "to", 7) # 8-bit byte, LSB first

399

400

cocotb.log.info(f"Range1: {range1.left} {range1.direction} {range1.right}")

401

cocotb.log.info(f"Range2: {range2.left} {range2.direction} {range2.right}")

402

403

# Convert to Python ranges for iteration

404

py_range1 = range1.to_range()

405

py_range2 = range2.to_range()

406

407

cocotb.log.info(f"Python range1: {list(py_range1)}")

408

cocotb.log.info(f"Python range2: {list(py_range2)}")

409

410

# Create arrays with specific ranges

411

if hasattr(dut, 'register_file'):

412

reg_array = Array(dut.register_file, Range(31, "downto", 0))

413

414

# Access array elements using HDL indexing

415

first_reg = reg_array[31] # MSB

416

last_reg = reg_array[0] # LSB

417

418

# Set values

419

first_reg.value = 0xDEAD

420

last_reg.value = 0xBEEF

421

422

await Timer(10, units="ns")

423

424

cocotb.log.info(f"Register[31]: 0x{first_reg.value:X}")

425

cocotb.log.info(f"Register[0]: 0x{last_reg.value:X}")

426

427

@cocotb.test()

428

async def array_slicing_test(dut):

429

"""Test demonstrating array slicing operations."""

430

431

from cocotb.types import Array, Range

432

433

# Create array representing a memory

434

if hasattr(dut, 'memory_block'):

435

memory = Array(dut.memory_block, Range(1023, "downto", 0))

436

437

# Write test pattern to slice

438

for i in range(16):

439

memory[i].value = i * 0x10

440

441

await Timer(50, units="ns")

442

443

# Read back slice

444

for i in range(16):

445

value = memory[i].value

446

expected = i * 0x10

447

assert value == expected, f"Memory[{i}]: expected {expected}, got {value}"

448

449

cocotb.log.info("Array slicing test passed")

450

```

451

452

### Type Operations

453

454

Operations for combining and manipulating HDL-compatible types.

455

456

```python { .api }

457

def concat(a, b, *args):

458

"""

459

Concatenate arrays or values.

460

461

Parameters:

462

- a: First array/value

463

- b: Second array/value

464

- *args: Additional arrays/values to concatenate

465

466

Returns:

467

Concatenated result

468

"""

469

```

470

471

**Usage Examples:**

472

473

```python

474

@cocotb.test()

475

async def type_operations_test(dut):

476

"""Test demonstrating type operations."""

477

478

from cocotb.types import LogicArray, Logic, concat

479

480

# Create arrays to concatenate

481

high_nibble = LogicArray([Logic.1, Logic.0, Logic.1, Logic.1]) # 0xB

482

low_nibble = LogicArray([Logic.0, Logic.1, Logic.0, Logic.1]) # 0x5

483

484

# Concatenate to form byte

485

full_byte = concat(high_nibble, low_nibble)

486

487

cocotb.log.info(f"High nibble: {high_nibble.binstr}")

488

cocotb.log.info(f"Low nibble: {low_nibble.binstr}")

489

cocotb.log.info(f"Concatenated: {full_byte.binstr}")

490

cocotb.log.info(f"Result: 0x{full_byte.integer:02X}")

491

492

# Multiple concatenation

493

byte1 = LogicArray([Logic.1, Logic.1, Logic.0, Logic.0]) # 0xC

494

byte2 = LogicArray([Logic.0, Logic.0, Logic.1, Logic.1]) # 0x3

495

byte3 = LogicArray([Logic.1, Logic.0, Logic.1, Logic.0]) # 0xA

496

497

word = concat(byte1, byte2, byte3, low_nibble) # 16-bit word

498

499

cocotb.log.info(f"Multi-concat result: {word.binstr}")

500

cocotb.log.info(f"Word value: 0x{word.integer:04X}")

501

502

# Use with DUT

503

dut.concat_result.value = word

504

await Timer(10, units="ns")

505

```

506

507

## Advanced Type Usage

508

509

### Custom Type Wrappers

510

511

```python

512

class SignedByte:

513

"""Custom wrapper for signed 8-bit values."""

514

515

def __init__(self, value=0):

516

self._value = BinaryValue(value, n_bits=8,

517

binaryRepresentation=BinaryRepresentation.TWOS_COMPLEMENT)

518

519

@property

520

def value(self):

521

return self._value.signed_integer

522

523

@value.setter

524

def value(self, val):

525

self._value.assign(val)

526

527

@property

528

def binary_value(self):

529

return self._value

530

531

def __str__(self):

532

return f"SignedByte({self.value})"

533

534

@cocotb.test()

535

async def custom_types_test(dut):

536

"""Test demonstrating custom type wrappers."""

537

538

# Create signed byte values

539

sb1 = SignedByte(100)

540

sb2 = SignedByte(-50)

541

542

cocotb.log.info(f"Signed byte 1: {sb1}")

543

cocotb.log.info(f"Signed byte 2: {sb2}")

544

545

# Use with DUT

546

dut.signed_input.value = sb1.binary_value

547

await Timer(10, units="ns")

548

549

# Arithmetic with overflow handling

550

sb1.value = 127 # Maximum positive

551

cocotb.log.info(f"Max positive: {sb1}")

552

553

sb1.value = 128 # Wraps to -128

554

cocotb.log.info(f"Overflow to: {sb1}")

555

```

556

557

### Type Conversion Utilities

558

559

```python

560

def to_logic_array(value, width=None):

561

"""Convert various types to LogicArray."""

562

from cocotb.types import LogicArray, Logic

563

564

if isinstance(value, str):

565

# Convert binary string

566

logic_bits = []

567

for char in value:

568

if char == '0':

569

logic_bits.append(Logic.0)

570

elif char == '1':

571

logic_bits.append(Logic.1)

572

elif char.upper() == 'X':

573

logic_bits.append(Logic.X)

574

elif char.upper() == 'Z':

575

logic_bits.append(Logic.Z)

576

return LogicArray(logic_bits)

577

578

elif isinstance(value, int):

579

# Convert integer to LogicArray

580

if width is None:

581

width = value.bit_length() if value > 0 else 1

582

583

binary_str = format(value, f'0{width}b')

584

return to_logic_array(binary_str)

585

586

else:

587

raise ValueError(f"Cannot convert {type(value)} to LogicArray")

588

589

@cocotb.test()

590

async def conversion_test(dut):

591

"""Test demonstrating type conversion utilities."""

592

593

# Convert from different sources

594

from_string = to_logic_array("1010X01Z")

595

from_int = to_logic_array(0xAB, width=8)

596

597

cocotb.log.info(f"From string: {from_string.binstr}")

598

cocotb.log.info(f"From int: {from_int.binstr}")

599

600

# Use converted values

601

dut.test_input1.value = from_string

602

dut.test_input2.value = from_int

603

604

await Timer(20, units="ns")

605

```