vram/VRAM: at last, a video RAM, with all the gubbins
This commit is contained in:
parent
fb57903021
commit
1929bbe3cc
|
@ -0,0 +1,99 @@
|
||||||
|
package VRAM;
|
||||||
|
|
||||||
|
import Connectable::*;
|
||||||
|
import GetPut::*;
|
||||||
|
import ClientServer::*;
|
||||||
|
import Vector::*;
|
||||||
|
import FIFOF::*;
|
||||||
|
import SpecialFIFOs::*;
|
||||||
|
|
||||||
|
import MemArbiter::*;
|
||||||
|
import VRAMCore::*;
|
||||||
|
|
||||||
|
// Re-exports from VRAMCore
|
||||||
|
export VRAMAddr, VRAMData, VRAMRequest(..), VRAMResponse(..);
|
||||||
|
|
||||||
|
export VRAMServer(..);
|
||||||
|
export VRAM(..), mkVRAM;
|
||||||
|
|
||||||
|
typedef Server#(VRAMRequest, VRAMResponse) VRAMServer;
|
||||||
|
|
||||||
|
// mkArbitratedVRAMServers expands a VRAMServer port into multiple
|
||||||
|
// ports through the use of a MemArbiter.
|
||||||
|
module mkArbitratedVRAMServers(VRAMServer ram, MemArbiter#(n, VRAMAddr) arb, Vector#(n, VRAMServer) ifc)
|
||||||
|
provisos (Min#(n, 1, 1),
|
||||||
|
Alias#(port_idx, UInt#(TLog#(n))));
|
||||||
|
Vector#(n, FIFOF#(VRAMRequest)) requests <- replicateM(mkBypassFIFOF());
|
||||||
|
Vector#(n, FIFOF#(VRAMResponse)) responses <- replicateM(mkBypassFIFOF());
|
||||||
|
Reg#(Maybe#(port_idx)) awaiting_response[2] <- mkCReg(2, tagged Invalid);
|
||||||
|
|
||||||
|
(* fire_when_enabled *)
|
||||||
|
rule request_ports;
|
||||||
|
for (Integer i=0; i<valueOf(n); i=i+1)
|
||||||
|
if (requests[i].notEmpty) begin
|
||||||
|
let req = requests[i].first;
|
||||||
|
let arb_req = MemArbiterOp{
|
||||||
|
write: isValid(req.data),
|
||||||
|
addr: req.addr
|
||||||
|
};
|
||||||
|
arb.ports[i].request(arb_req);
|
||||||
|
end
|
||||||
|
endrule
|
||||||
|
|
||||||
|
(* fire_when_enabled *)
|
||||||
|
rule submit (awaiting_response[1] matches tagged Invalid);
|
||||||
|
let port = arb.granted_port();
|
||||||
|
ram.request.put(requests[port].first);
|
||||||
|
requests[port].deq();
|
||||||
|
awaiting_response[1] <= tagged Valid port;
|
||||||
|
endrule
|
||||||
|
|
||||||
|
(* fire_when_enabled *)
|
||||||
|
rule response (awaiting_response[0] matches tagged Valid .port &&& responses[port].notFull);
|
||||||
|
let resp <- ram.response.get();
|
||||||
|
responses[port].enq(resp);
|
||||||
|
awaiting_response[0] <= tagged Invalid;
|
||||||
|
endrule
|
||||||
|
|
||||||
|
return map(uncurry(toGPServer), zip(requests, responses));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
// VRAM is a GARY video RAM and its memory ports.
|
||||||
|
interface VRAM;
|
||||||
|
interface VRAMServer cpu;
|
||||||
|
interface VRAMServer debugger;
|
||||||
|
interface VRAMServer palette;
|
||||||
|
interface VRAMServer tile1;
|
||||||
|
interface VRAMServer tile2;
|
||||||
|
interface VRAMServer sprite;
|
||||||
|
endinterface
|
||||||
|
|
||||||
|
// mkVRAM constructs a VRAM of the requested size. Memory access is
|
||||||
|
// spread across two internal ports as follows:
|
||||||
|
//
|
||||||
|
// Port A: strict most-important-wins priority: CPU, then debugger,
|
||||||
|
// then palette DAC.
|
||||||
|
// Port B: equal round-robin prioritization between two tile engines
|
||||||
|
// and the sprite engine.
|
||||||
|
module mkVRAM(Integer num_kilobytes, VRAM ifc);
|
||||||
|
VRAMCore ram <- mkVRAMCore(num_kilobytes);
|
||||||
|
|
||||||
|
MemArbiter#(3, VRAMAddr) arbA <- mkPriorityMemArbiter();
|
||||||
|
Vector#(3, VRAMServer) portA <- mkArbitratedVRAMServers(ram.portA, arbA);
|
||||||
|
|
||||||
|
MemArbiter#(3, VRAMAddr) arbB <- mkRoundRobinMemArbiter();
|
||||||
|
Vector#(3, VRAMServer) portB <- mkArbitratedVRAMServers(ram.portB, arbB);
|
||||||
|
|
||||||
|
// Connect up the arbiters so they correctly prevent write-write
|
||||||
|
// and write-read conflicts.
|
||||||
|
mkConnection(arbA, arbB);
|
||||||
|
|
||||||
|
interface cpu = portA[0];
|
||||||
|
interface debugger = portA[1];
|
||||||
|
interface palette = portA[2];
|
||||||
|
interface tile1 = portB[0];
|
||||||
|
interface tile2 = portB[1];
|
||||||
|
interface sprite = portB[2];
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
endpackage
|
Loading…
Reference in New Issue