Interfacing and Memory
Martin Schoeberl
Technical University of Denmark Embedded Systems Engineering
April 21, 2022
Overview
I Quick reminder on FSMD I Interfaces
I Memory (intern and extern) I Serial interface (RS 232)
I The course evaluation should be open for feedback I Lab is the vending machine
I What is your lab status? Display multiplexing working?
I have seen similar code
when ( io . coin2 ) { sum := sum + 2. U } . elsewhen ( io . coin5 ) {
sum := sum + 5. U }
I This may work for tiny projects
I This style does not scale for larger designs I I recommend using an FSM + datapath
I Split responsibility I Can be individually tested I Can be developed in parallel
Usage of an FSMD
I Of course for your VM
I The VM is a simple processor I But not Turing complete
I Canonlyprocess coins of 2 and 5
I Have the FSM and the data path in twoModules I An FSMD can be used to build a processor I Fine for simple processors
I E.g.,Lipsi
I Pipelined processor topic of
I Computer Architecture Engineering (02155)
Test the FSMD for the VM
I This is the main part your vending machine
I Can be design and tested just with Chisel testers (no FPGA board needed)
I See the given tester I Sets the price to 7 I Adds two coins (2 and 5) I Presses the buy button
I Extend the test along the development I Remember test driven development?
I Maybe write the test before the implementation
I Maybe test developer and FSMD developer are not always the same person
Testing Your Vending Machine
I Write (unit) tests for each component/module
I E.g., one for the data path, one for the state machine I Then one (integration) test for the top-level
component/module
I Maybe do someextreme programming (XP) I Write the test first
I Then the code of the component I The test can serve as a specification I We can doagilehardware development
Memory
I Registers are storage elements == memory I Just use aRegof aVec
I This is 1 KiB of memory
val memoryReg = Reg ( Vec (1024 , UInt (8. W))) // writing into memory
memoryReg ( wrAddr ) := wrData // reading from the memory val rdData = memoryReg ( rdAddr ) I Simple, right?
I But is this a good solution?
A Flip-Flop
I Remember the circuit of a register (flip-flop)?
I Two latches: master and slave
I One (enable) latch can be built with 4 NAND gates
I a NAND gate needs 6 transistors, an inverter 2 transistors I A flip-flop needs 20 transistors (for a single bit)
I Can we do better?
A Memory Cell
I A single bit can be stored in6 transistors I That is how larger memories are built I FPGAs have this type of on-chip memories I Usually many of them in units of 2 KiB or 4 KiB I We need some Chisel code to represent it I More memory needs an extrnal chip
I Then we need to interface this memory from the FPGA
SRAM Memory
I RAM stands for random access memory I SRAM stands for static RAM
I There is also something called DRAM for dynamic RAM I Uses a capacitor and a transistor
I DRAM is smaller than SRAM I But needs refreshes
I Different technology than technology for logic I All on-chip memory is SRAM (today)
Memory Interface
I Interface
I Address input (e.g., 10 bits for 1 KiB) I Write signal (e.g., we)
I Data input I Data output
I May share pins for the data input and output (tri-state) I May have read and write addresses
I A so-called dual ported memory
I Can do a read and a write in the same clock cycle
On-Chip Memory
I SRAM by itself is asynchronous I No clock, just the correct timing
I Apply the address and after some time the data is valid I But one can add input registers, which makes it a
synchronous SRAM
I Current FPGAs have only synchronous memories
I This means the result of a read is available one clock cycle after the address is given
I This is different from the use of flip-flops (Reg(Vec(..))) I FPGAs usually have dual-ported memories
Synchronous Memory
rdAddr
wrAddr
wrData
rdData
wrEna
Memory
Use of a Chisel SyncReadMem
class Memory() extends Module { val io = IO (new Bundle {
val rdAddr = Input ( UInt (10. W)) val rdData = Output ( UInt (8. W)) val wrEna = Input ( Bool () ) val wrData = Input ( UInt (8. W)) val wrAddr = Input ( UInt (10. W)) })
val mem = SyncReadMem (1024 , UInt (8. W)) io . rdData := mem . read ( io . rdAddr )
when ( io . wrEna ) {
mem . write ( io . wrAddr , io . wrData ) }
}
Read-During-Write
I What happens when one writes to and reads from the same address?
I Which value is returned?
I Three possibilities:
1. The newly written value 2. The old value
3. Undefined (mix of old and new)
I Depends on technology, FPGA family, ...
I We want to have a defined read-during-write I We add hardware toforwardthe written value
Condition for Forwarding
I If read and write addresses are equal I If write enable is true
I Multiplex the output to take the new write value instead of the (old) read value
I Delay that forwarded write value to have the same timing
Memory with Forwarding
rdAddr
wrAddr
wrData
rdData
wrEna
=
AND
dout
Memory
Forwarding in Chisel
val mem = SyncReadMem (1024 , UInt (8. W)) val wrDataReg = RegNext ( io . wrData )
val doForwardReg = RegNext ( io . wrAddr ===
io . rdAddr && io . wrEna )
val memData = mem . read ( io . rdAddr ) when ( io . wrEna ) {
mem . write ( io . wrAddr , io . wrData ) }
io . rdData := Mux ( doForwardReg , wrDataReg , memData )
External Memory
I On-chip memory is limited
I We can add an external memory chip I Is cheaper than FPGA on-chip memory
I Sadly the Basys3 board has no external memory I Simple memory is an asynchronous SRAM
External SRAM
I Webuya CY7C1041CV33 I Let us look into thedata sheet
Interfacing the SRAM
I FPGA output drives address, control, and data (sometimes)
I FPGA reads data
I The read signal is asynchronous to the FPGA clock I Do we need an input synchronizer?
Synchronous Interface
I Logic is synchroous I Memory is asynchronous
I How to interface?
I Output signals
I Generate timing with synchronous circuit I Small FSM
I Asynchronous input signale
I Usually 2 register for input synchronization I Really needed for the SRAM interface?
I We would loose 2 clock cycles
SRAM Read
I Asynchronous timing definition (data sheet)
I But, we know the timing and we trigger the SRAM address from our synchronous design
I No need to use synchronization registers I Justget the timing correct
I Draw the example
I Address - SRAM - data I Relative to the FPGA clock
Read Timing Continued
I Add all time delays I Within FPGA I Pad to pin I PCB traces I SRAM read timing I PCB traces back I Pin to pad
I Into FPGA register
I Setup and hold time for FPGA register
Connecting to the World
I Logic in the FPGA I Described in Chisel
I Abstracting away electronic properties I Interface to the world
I Simple switches and LEDs I Did we think about timing?
I FPGA is one component of the system I Need interconnect to
I Write outputs I Read inputs
I Connect to other chips
Bus Interface
I Memory interface can be generalized
I We use a so-called bus to connect several devices I Usually a microprocessor connected to devices (memory,
IO)
I The microprocessor is the master I A bus is an interface definition
I Logic and timing I Electrical interface I Parallel or serial data
I Asynchronous or synchronous
I But interface clock is usually not the logic clock
Bus Properties
I Address bus and data bus I Control lines (read and write) I Several devices connected
I Multiple outputs
I Use tri-state to avoid multiple driver I Single or multiple master
I Arbitration for multiple master
I Sketch a small microprocessor system
Serial I/O Interface
I Use only one wire for data transfer I Bits are serialized
I That is where you need your shift register
I Shared wire or dedicated wires for transmit and receive I Self timed
I Serial UART (RS 232) I Ethernet
I USB
I With a clock signal I SPI, I2C, ...
RS 232
I Old, but still common interface standard I Was common in 90’ in PCs
I Now substituted by USB
I Still common in embedded systems I Your Basys3 board has a RS 232 interface I Standard defines
I Electrical characteristics
I ’1’ is negative voltage (-15 to -3 V) I ’0’ is positive voltage (+3 to +15 V)
I Converted by a RS 232 driver tonormallogic voltage levels
Serial Transmission
I Transmission consists of I Start bit (low)
I 8 data bits I Stop bit(s) (high)
I Common baud rate is 115200 bits/s
b0 b1 b2 b3 b4 b5 b6 b7
RS 232 Interface
I How would we implement this?
I Baud rate is 115200 bit/s (ca. 10 us) I Clock on Basys 3 is 100 MHz (10 ns) I Output (transmit)
I Input (receive)
I Let us do it now together
RS 232 Interface
I Generate bit clock with with counter
I Like clock tick generation for display multiplexer I Output (transmit)
I Use shift register for parallel to serial conversion I Small FSM to generate start bit, data bits, and stop bits I Input (receive)
I Detect start with the falling edge of the start bit I Positioninto middle of start bit
I Sample individual bits
I Serial to parallel conversion with a shift register
Chisel Code for RS 232
I More explanation can be found in section 11.2 I The code is in the Chisel book
I uart.scala
I Also see example usage inchisel-examplesrepo
RS 232 on the Basys3
I Basys3 has an FTDI chip for the USB interface I USB interface for FPAG programming
I But also provides a RS 232 to the FPGA I You can talk with your laptop
I Your VM could write out some text I Use the Chisel code I showed you I Open a terminal to watch
RS 232 from ip-contributions
I A collection of Chisel hardware components I Contains the RS232 interface
I Distributed as library from Maven Central I No need to copy source around
I Just include it in yourbuild.sbt
I Very easy distribution of open-source components I You can contribute!
I ip-contributions
Today’s and next Lab
I Work on your Vending Machine I As usual, show and discuss with a TA
I Get a tick from a TA when done. This is VERY important!
I Add features and show again to the TA
I Next week: no lecture, just development in the lab
Summary
I Use an FSMD for the vending machine and simple processors
I We need to connect to the world
I FPGA (or any chip) is only part of a system I Bus interface to external devices (e.g., memory) I Serial interface to connect systems
I E.g., your Basys3 board to the laptop I Testing is more than looking at waveforms