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.