Part A: Give a circuit description for an 1K RAM module, using appropriate register-transfer-leve primitives, as were assumed to be available in the Notes on Large Scale System Design.
circuit RAM1K( integer address ); -- an addressable 1K RAM module, designed to plug into a SOCKET(slave). -- designed by D W Jones, Feb 2001 -- makes global references to -- range -- word = ... -- circuits -- ram( range wordselect, range word, time speed ) -- ram -- compc( range word, time speed, integer const ) -- comparitor -- driver( range word, time speed ) -- bus driver range wordselect = 0 .. 9; range bankselect = 10 .. last(word); assert word = wordselect | bankselect; inputs read, write, addr(word), datain(word); outputs dataout(word); parts M: ram( wordselect, word , 70 * ns ); C: compc( bankselect, 10 * ns, address ); D: driver( word, 10 * ns ); readgate, writegate: and(2); wires -- data path datain to M.data; M.out to D.in; D.out to dataout; -- address decode for i in bankselect do addr(i) to C.in(i); endfor; for i in wordselect do addr(i) to M.addr(i); endfor; C.out to readgate.in(1); C.out to writegate.in(1); -- clock and enable distribution read to readgate.in(2); readgate.out to D.enable; write to writegate.in(2); writegate.out to M.strobe; end.
Part B: Finish the definition of the following register-transfer level component:
circuit addressdecode( range word, range subword, integer address); -- given A:addressdecode( word, 1..2, 4 ) -- The values of A.in(1) through A.in(2) are checked against the -- cooresponding bits of the constant 4; if they are equal, A.out -- is true, else A.out is false. assert first(word) = 0; assert first(subword) >= 0; assert last(subword) <= last(word); inputs in(word); outputs out; -- finished with the following: parts compbit(1 .. onebits( const )): not; combine: nor(size(subword)); wires -- data paths for i in subword do if odd( const / 2**i ) then in(i) to compbit(onebits( const / 2**i )).in; compbit(onebits( const / 2**i )).out to combine.in(i+F); else in(i) to combine.in(i+F); endif endfor; combine.out to out; end;
Part A: Give a simplified timing diagram to replace The timing diagram given in Figure 3 of The Ultimate RISC.
| . . . | . . . | . . . | . . . | _______ PCMUX |_______________________| | unchanged _______ WTEMP |_______________________|// | lengthened _______ CTEMP ________|//// /|________________ greatly lengthened _______ _______ CADDR |//// /|_______|//// /|_______| greatly lengthened _______ _______ CPC |///// |_______|///// |_______| greatly lengthened _______ _______ ADMUX |_______| |_______| | unchanged _______ WRITE ________________________|//// /| greatly lengthened _______________________ READ |// /// /// |_______| greatly lengthened
Part B: Why would both timing diagrams work equally well to control the machine?
This would work equally well under some fairly fragile instructions. We have assumed that all registers and memory units are either positive pulse triggered or negative edge triggered, we have assumed that all negative edges on clock signals are simultaneous! If any results propagate to the outputs of a register before the recipient of the data from that register sees its negative going edge, the design will cease working.Second, the enables lines for the bus drivers all come from read and write. When we enable one bus driver at exactly the same time that we disable another driver on the same bus, as the long-pulse logic here implies, power consumption on the bus drivers goes up, and if the enable signal to one driver arrives even slightly before the enable on another is released, the bus will be driven simultaneously by two drivers, raising the power consumption to a level that may be destructive.
In sum, this is a classic example of "bleeding edge design", it might just work, but there is no safety margin.