52
Basic Digital Circuits in Chisel Martin Schoeberl Technical University of Denmark Embedded Systems Engineering February 13, 2020 1 / 52

Basic Digital Circuits in Chisel - compute.dtu.dk · JVM Hello.Þr chisel3.lib scala.lib Verilog Emitter JVM Treadle JVM Hello.vcd Hello.v FIRRTL JVM Chisel Tester JVM good/bad

  • Upload
    others

  • View
    59

  • Download
    1

Embed Size (px)

Citation preview

Basic Digital Circuits in Chisel

Martin Schoeberl

Technical University of DenmarkEmbedded Systems Engineering

February 13, 2020

1 / 52

Overview

I Quick repeat of last lectureI If something is unclear, please ask!

I Basic digital building blocksI And the coding in ChiselI Some coding style

2 / 52

The Digital Abstraction

I Just two values: 0 and 1,or low and hight

I Represented as voltageI Digital signals tolerate

noiseI Digital Systems are simple,

just:I Combinational circuits

andI Registers

AND

OR

ba

clogic

D Q

clock

3 / 52

Chisel

I A hardware construction languageI Constructing Hardware In a Scala Embedded LanguageI If it compiles, it is synthesisable hardwareI Say goodby to your unintended latches

I Chisel is not a high-level synthesis languageI Single source for two targets

I Cycle accurate simulation (testing)I Verilog for synthesis

I Embedded in ScalaI Full power of Scala availableI But to start with, no Scala knowledge needed

I Developed at UC Berkeley

4 / 52

Chisel is Part of the C Language Family

C

Verilog

SystemVerilog

C++

SystemC

Java

Scala

Chisel

C#

5 / 52

Tool Flow for Chisel Defined Hardware

Hello.scala

scalac

Hello.class

ChiselJVM

Hello.fir

scala.libchisel3.lib

Verilog Emitter

JVMTreadle

JVM

Hello.vHello.vcd

FIRRTLJVM

Chisel TesterJVM

good/bad

GTKWave CircuitSynthesis

Hello.bit

6 / 52

Signal/Wire Types and Width

I All types in hardware are a collection of bitsI The base type in Chisel is BitsI UInt represents an unsigned integerI SInt represents a signed integer (in two’s complement)I The number of bits is the widthI The width written as number followed by .W

Bits(8.W)

UInt(8.W)

SInt(10.W)

7 / 52

Constants

I Constants can represent signed or unsigned numbersI We use .U and .S to distinguish

0.U // defines a UInt constant of 0

-3.S // defines a SInt constant of -3

I Constants can also be specified with a width

3.U(4.W) // An 4-bit constant of 3

I Use the string notation for a different base

"hff".U // hexadecimal representation of

255

"o377".U // octal representation of 255

"b1111_1111".U // binary representation of 255

8 / 52

Combinational Circuits

I Chisel uses Boolean operators, similar to C or JavaI & is the AND operator and | is the OR operatorI The following code is the same as the schematicsI val logic gives the circuit/expression the name logicI That name can be used in following expressions

AND

OR

ba

clogic

val logic = (a & b) | c

9 / 52

Arithmetic and Logic Operations

I Same as in Java or CI But this is hardware

val add = a + b // addition

val sub = a - b // subtraction

val neg = -a // negate

val mul = a * b // multiplication

val div = a / b // division

val mod = a % b // modulo operation

val and = a & b // bitwise and

val or = a | b // bitwise or

val xor = a ˆ b // bitwise xor

val not = ˜a // bitwise negation

10 / 52

Wires

I A signal (or wire) can be first definedI And later assigned an expression with :=

val w = Wire(UInt())

w := a & b

11 / 52

Subfields and Concatenation

A single bit can be extracted as follows:

val sign = x(31)

A subfield can be extracted from end to start position:

val lowByte = largeWord(7, 0)

Bit fields are concatenated with Cat:

val word = Cat(highByte, lowByte)

12 / 52

A Multiplexer

ay

sel

b

I A Multiplexer selects between alternativesI So common that Chisel provides a construct for itI Selects a when sel is true.B otherwise b

val result = Mux(sel, a, b)

13 / 52

Register

I A register is a collection of flip-flopsI Updated on the rising edge of the clockI May be set to a value on reset

D Q

reset

d

0 q

clock

14 / 52

A Register with Reset

Following code defines an 8-bit register, initialized with 0 atreset:

val reg = RegInit(0.U(8.W))

An input is connected to the register with the := updateoperator and the output of the register can be used just with thename in an expression:

reg := d

val q = reg

15 / 52

Reminder: We Construct Hardware

I Chisel code looks much like Java codeI But it is not a program in the usual senseI It represents a circuitI We should be able to draw that circuitI The “program” constructs the circuitI All statements are “executed” in parallelI Statement order has mostly no meaning

16 / 52

Interlude

I Before we look at new materialI Sprinkle in some info on general development toolsI Get better at using your computerI Learn some toolsI Don’t be afraid of the command line ;-)I

I

I Engineers are power users!

17 / 52

What is git?

I git is a distributed version-control systemI What does that mean?I Wikipedia on gitI Draw a figure

I To manage source code or other documentsI Track changes in computer filesI Created by Linus Torvalds for Linux kernel developmentI Good tool for cooperationI Mostly used at the command lineI But graphical clients are available (i.e., with a GUI)

18 / 52

What is GitHub?

I GitHub is a git repository serverI GitHub is a classic startup, based in San FranciscoI Acquired 2018 by Microsoft for $7.5 billionI Many open-source projects are on GitHub (e.g., Chisel)

I 85 million repositories, and 28 million developersI Our DE2 material is hosted on GitHub

I Lab material (you have used it)I The slidesI The Chisel bookI see https://github.com/schoeberlI Everyone can contribute via GitHub ;-)

19 / 52

Comment on Character Usage and Language

I Computers used for long time ASCII charactersI Show ASCII tableI Does NOT contain the special letters of DK, SE, AT,...I Only a subset of ASCII was allowed for identifiersI Languages such as Java or Scala are now more tolerant

I You could use Chinese characters for your Java program!I Please do not use any special characters

I Also not in file namesI Programming is international

I Use English identifiers and commentsI Avoid spaces in file names and folders

20 / 52

Coding Style

I Similar to JavaI Use readable, meaningful names

I E.g., sum instead of yI Use camelCase for identifiersI Modules (classes) start with uppercase

I E.g., VendingMachineI Mark you register with a postfix Reg

I E.g., countRegI Use consistent indentation

I Chisel style is 2 spaces (blanks)I Use ASCII only ;-)

21 / 52

Combinational Circuits

I Simplest is a Boolean expressionI Assigned a name (e)I This expression can be reused in another expression

val e = (a & b) | c

22 / 52

Fixed Expression

I Expression is fixedI Trying to reassign with = results in an errorI Trying the Chisel conditional update := results in runtime

error

val e = (a & b) | c

e := c & b

23 / 52

Combinational Circuit with Conditional Update

I Chisel supports conditional updateI Value first needs to be wrapped into a WireI Updates with the Chisel update operation :=I With when we can express a conditional updateI The resulting circuit is a multiplexerI The rule is that the last enabled assignment counts

I Here the order of statements has a meaning

val w = Wire(UInt())

w := 0.U

when (cond) {

w := 3.U

}

24 / 52

The “Else” Branch

I We can express a form of “else”I Note the . in .otherwise

val w = Wire(UInt())

when (cond) {

w := 1.U

} .otherwise {

w := 2.U

}

25 / 52

A Chain of Conditions

I To test for different conditionsI Select with a priority orderI The first that is true countsI The hardware is a chain of multiplexers

val w = Wire(UInt())

when (cond) {

w := 1.U

} .elsewhen (cond2) {

w := 2.U

} .otherwise {

w := 3.U

}

2

cond2

3

w

cond

1

26 / 52

Default Assignment

I Practical for complex expressionsI Forgetting to assign a value on all conditions

I Would describe a latchI Runtime error in Chisel

I Assign a default value is good practise

val w = WireDefault(0.U)

when (cond) {

w := 3.U

}

// ... and some more complex conditional

assignments

27 / 52

Logic Can Be Expressed as a Table

I Sometimes more convenientI Still combinational logic (gates)I Is converted to Boolean expressionsI Let the synthesize tool do the conversion!I We use the switch statement

result := 0.U

switch(sel) {

is (0.U) { result := 1.U}

is (1.U) { result := 2.U}

is (2.U) { result := 4.U}

is (3.U) { result := 8.U}

}

28 / 52

A Decoder

a1Decoder

a0

b0

b1

b2

b3

I Converts a binary number of n bits to an m-bit signal,where m ≤ 2n

I The output is one-hot encoded (exactly one bit is one)I Building block for a m-way MuxI Used for address decoding in a computer system

29 / 52

Truth Table of a Decoder

a b

00 000101 001010 010011 1000

I Does this look like the table we have seen?

30 / 52

Decoder in Chisel

I Binary strings are a clearer representation

switch (sel) {

is ("b00".U) { result := "b0001".U}

is ("b01".U) { result := "b0010".U}

is ("b10".U) { result := "b0100".U}

is ("b11".U) { result := "b1000".U}

}

31 / 52

An Encoder

a1Encoder

a0

a2

a3

b0

b1

I Converts one-hot encoded signalI To binary representation

32 / 52

Truth Table of an Encoder

a b

0001 000010 010100 101000 11???? ??

I Only defined for one-hot input

33 / 52

Encoder in Chisel

I We cannot describe a function with undefined outputsI We use a default assignment of "b00"

b := "b00".U

switch (a) {

is ("b0001".U) { b := "b00".U}

is ("b0010".U) { b := "b01".U}

is ("b0100".U) { b := "b10".U}

is ("b1000".U) { b := "b11".U}

}

34 / 52

Register (Again)

I Sequential building blocksI Contain a registerI Plus combinational circuits

D Q

clock

val q = RegNext(d)

35 / 52

Register in Two Steps

val delayReg = Reg(UInt(4.W))

delayReg := delayIn

36 / 52

Register With Reset

D Qinit

reset

data

val valReg = RegInit(0.U(4.W))

valReg := inVal

37 / 52

Timing Diagram of the Register with Reset

clock

reset

inVal 3 5 2 7 4

regVal 0 5 2 7

A B C D E F

I Also called waveform diagramI Logic function over timeI Can be used to describe a circuit functionI Useful for debugging

38 / 52

Register with Enable

D Q

enable

data

I Only when enable true is a value is stored

val enableReg = Reg(UInt(4.W))

when (enable) {

enableReg := inVal

}

39 / 52

Timing Diagram for an Enable Register

clock

enable

inVal 2 3 5 2 7 4

regEnable 2 3 5 2 7

A B C D E F

40 / 52

More on Register

I We can combine initialization and enable

val resetEnableReg = RegInit(0.U(4.W))

when (enable) {

resetEnableReg := inVal

}

I A register can also be part of an expressionI What does the following circuit do?

val risingEdge = din & !RegNext(din)

41 / 52

Combine a Register with an Adder

D Q +

1

I Is a free running counterI 0, 1, ... 14, 15, 0, 1, ...

val cntReg = RegInit(0.U(4.W))

cntReg := cntReg + 1.U

42 / 52

A Counter

val cntReg = RegInit(0.U(8.W))

cntReg := Mux(cntReg === 9.U, 0.U, cntReg + 1.U)

I This counter counts from 0 to 9I And starts from 0 again after reaching 9

I Starting from 0 is common in computer engineeringI A counter is the hardware version of a for loopI Often neededI Can you draw the schematic?

43 / 52

Counting Events

D Q +

1

event

0

I Is the schematics and the code the same?

val cntEventsReg = RegInit(0.U(4.W))

when(event) {

cntEventsReg := cntEventsReg + 1.U

}

44 / 52

Structure With Bundles

I A Bundle to groups signalsI Can be different typesI Defined by a class that extends BundleI List the fields as vals within the block

class Channel() extends Bundle {

val data = UInt(32.W)

val valid = Bool()

}

45 / 52

Using a Bundle

I Create it with newI Wrap it into a WireI Field access with dot notation

val ch = Wire(new Channel())

ch.data := 123.U

ch.valid := true.B

val b = ch.valid

46 / 52

A Collection of Signals with Vec

I Chisel Vec is a collection of signals of the same typeI The collection can be accessed by an indexI Similar to an array in other languages

val v = Wire(Vec(3, UInt(4.W)))

47 / 52

Using a Vec

v(0) := 1.U

v(1) := 3.U

v(2) := 5.U

val idx = 1.U(2.W)

val a = v(idx)

I Reading from an Vec is a multplexerI We can put a Vec into a Reg

val registerFile = Reg(Vec(32, UInt(32.W)))

An element of that register file is accessed with an index andused as a normal register.

registerFile(idx) := dIn

val dOut = registerFile(idx)

48 / 52

Mixing Vecs and Bundles

I We can freely mix bundles and vectorsI When creating a vector with a bundle type, we need to

pass a prototype for the vector fields. Using our Channel,which we defined above, we can create a vector ofchannels with:

val vecBundle = Wire(Vec(8, new Channel()))

I A bundle may as well contain a vector

class BundleVec extends Bundle {

val field = UInt(8.W)

val vector = Vec(4,UInt(8.W))

}

49 / 52

Lab Today

I Combinational circuits in ChiselI Lab 2 PageI You need to download again, as I have updated the lab

I Or learn to use git and do a git pull ;-)I Each exercise contains a test, which initially failsI sbt test runs them all

I To just run a single test, run e.g.,sbt "testOnly MajorityPrinter"

When all test succeed your are done ;-)I Components contain a comment where you shall add your

implementationI The initial majority example has an optional

implementation in an FPGA

50 / 52

Summary

I Think in hardwareI Draw “boxes”

I Combinational logic (= Boolean function)I Logical and arithmetic expressionsI Conditional update (when)I Function tables with switchI Large multiplexer with a Vec

I RegistersI Define as Reg, RegNext, or RegInit

51 / 52

Summary

I We looked at basic digital circuit blocksI Now you know all you need to build any digital circuit!

I Digital controllerI MP3 playerI MicroprocessorI Data center acceleratorI ...

I Will show you some constructs for a more elegant styleI Next lecture is given by Jens Sparsoe and is on timing

52 / 52