// A Verilog example taken from comp.lang.verilog
//-----------------------Cache Coherence Protocol-----------------------------
// This finite-state machine (Melay type) reads bus
// per cycle and changes the state of each block in cache.
module cache_coherence (
new_state,
Cache_Sector_Fill,
Invalidate,
AdrRetry,
RMS,
RME,
WM,
WH,
SHR,
SHW,
state,
READ_DONE,
clk,
reset,
send_abort,
write_back_done,
AllInvDone);
input RMS, RME, WM, WH, SHR, SHW, READ_DONE, clk,
reset, send_abort, write_back_done, AllInvDone;
input [2:0] state;
output [2:0] new_state;
output Cache_Sector_Fill, Invalidate, AdrRetry;
reg Cache_Sector_Fill, Invalidate, AdrRetry ;
reg [2:0] new_state;
// The four possible states (symbolic names) for a sector
// in the cache plus 2 mandatory states
parameter /*[2:0]*/ // synopsys enum state_info
INVALID = 3'b000,
SHARED_1 = 3'b001,
EXCLUSIVE = 3'b010,
MODIFIED = 3'b011,
Cache_Fill = 3'b100,
start_write_back = 3'b101,
/* start_write_back = 5, */
WaitUntilAllInv = 3'b110;
// Declare current_state and next_state variable.
reg [2:0] /* synopsys enum state_info */ present_state;
reg [2:0] /* synopsys enum state_info */ next_state;
// synopsys state_vector present_state
/* Combinational */
always @(present_state or RMS or RME or WM or WH or SHW or READ_DONE
or SHR or write_back_done or AllInvDone or send_abort or state or reset)
begin
Cache_Sector_Fill = 0; // Default values
Invalidate = 0;
AdrRetry = 0;
next_state = present_state;
if (reset) next_state = state; else
begin
case(present_state) // synopsys full_case
INVALID:
// ReadMiss (shared/exclusive), Write Miss
if (RMS || RME || WM)
begin
Cache_Sector_Fill = 1;
next_state = Cache_Fill ;
end
else
begin
next_state = INVALID;
end
Cache_Fill:
/* During This State Cache is filled with the sector,
But if any other processor have that copy in modified
state, it sends an abort signal. If no other cache has
that copy in modified state. Requesting processor waits
for the read from memory to be done.
*/
if (send_abort)
begin
next_state = INVALID;
end
else if (READ_DONE)
begin
if (RMS)
begin
next_state = SHARED_1;
end
else if (RME)
begin
next_state = EXCLUSIVE;
end
else if (WM)
begin
Invalidate = 1;
next_state = WaitUntilAllInv;
end
else
begin
next_state = Cache_Fill ;
end
end
else
begin
next_state = Cache_Fill ;
end
SHARED_1:
if (SHW) // Snoop Hit on a Write.
begin
next_state = INVALID;
end
else if (WH) // Write Hit
begin
Invalidate = 1;
next_state = WaitUntilAllInv;
end
else
begin // Snoop Hit on a Read or Read Hit or any other
next_state = SHARED_1;
end
WaitUntilAllInv:
/* In this state Requesting Processor waits for the
all other processor's to invalidate its cache copy.
*/
if (AllInvDone)
begin
next_state = MODIFIED;
end
else
begin
next_state = WaitUntilAllInv;
end
EXCLUSIVE:
if (SHR) // Snoop Hit on a Read:
begin
AdrRetry = 0;
next_state = SHARED_1;
end
else if (SHW) // Snoop Hit on a Write
begin
next_state = INVALID;
end
else if (WH) // Write Hit
begin
next_state = MODIFIED;
end
else
begin // Read Hit
next_state = EXCLUSIVE;
end
MODIFIED:
if (SHW) // Snoop Hit on a Write
begin
next_state = INVALID;
end
else if (SHR) // Snoop Hit on a Read
begin
AdrRetry = 1;
next_state = start_write_back;
end
else // Read Hit or Write Hit or anything else.
begin
next_state = MODIFIED;
end
start_write_back:
/* In this state, Processor waits until other processor
has written back the modified copy.
*/
if (write_back_done)
begin
next_state = SHARED_1;
end
else
begin
next_state = start_write_back;
end
endcase
end
end
/* Sequential */
always @(posedge clk)
begin
present_state = next_state;
new_state = next_state;
end
endmodule
//--------------Test File: Maintaining Cache coherence in 2-processor Systems------
/* Test File for Maintaining Cache Coherence in 2-processor system */
module cache;
reg RMS, RME, WM, WH, RH, SHR, SHW, clk, READ_DONE , reset,
send_abort, write_back_done, AllInvDone, PA, PB, countE;
reg [2:0] state, SectorInCacheA, SectorInCacheB;
reg [3:0] count;
integer file1;
parameter CYCLE = 10;
wire [2:0] new_state;
wire Cache_Sector_Fill, Invalidate;
cache_coherence u1 (
new_state,
Cache_Sector_Fill,
Invalidate,
AdrRetry,
RMS, RME,
WM, WH,
SHR, SHW,
state, READ_DONE, clk, reset, send_abort, write_back_done, AllInvDone);
initial
begin
$display("Example: maintaining cache coherence in 2-processor system");
file1 = $fopen("cache.list");
$fdisplay(file1, "Example: maintaining cache coherence in 2-processor system");
/* The states of sector in both caches are initialized to Invalid (0). */
SectorInCacheA = 0; SectorInCacheB = 0;
/* Signals set/rest by cache controller */
// Write Hit
WH = 0;
// ReadMiss (Shared)
RMS = 0;
// WriteMiss
WM = 0;
// Snoop hit on read operation
SHR = 0;
// Snoop hit on write operation
SHW = 0;
// This signal is set/reset,
// when a cache controller starts or finish reading a sector from memory
READ_DONE = 0;
// This signal is set when all other cache controllers
// invalidate their copy.
AllInvDone = 0;
// This signal is set when cache controller finishes updating memory.
write_back_done = 0;
// This signal is set when snoopy cache controller sends
// AdrRetry Signal to retry the operation.
send_abort = 0;
// Present State of the Sector is INVALID in PA's local cache.
// So, it puts the address of this sector on the bus and starts
// reading this sector from memory.
state = SectorInCacheA ; PA = 1; PB = 0; RME = 1;
reset = 1; #6 reset = 0;
// After 15 time units Processor B will declare
// Snoop Hit on the Read operation done by Processor A.
#40 PA = 0; PB = 1; RME = 0; RMS = 1; state = SectorInCacheB;
reset = 1;#10 reset = 0;
#50 PB = 0; PA = 1; SHR = 1; state = SectorInCacheA;
reset = 1; #10 reset = 0;
#20 SHR = 0; WH = 1; state = SectorInCacheA;
reset = 1; #10 reset = 0;
#50 PA = 0; PB = 1; RMS = 1; WH = 0; state = SectorInCacheB;
reset = 1; #10 reset = 0;
#30 SHR = 1; RMS = 0; PA = 1; PB = 0; state = SectorInCacheA;
reset = 1; #10 reset = 0;
#20 PB = 1; PA = 0; SHR = 0; state = SectorInCacheB;
reset = 1; #10 reset = 0;
// PA states writing back.
#20 PB = 0; PA = 1; state = SectorInCacheA;
reset = 1; #10 reset = 0;
// This signal is broadcast on the bus to tell every body that
// Processor B has written back its Modified data back to the Memory
// to make everything consistent. After 5 time units it is set back to
// Zero.
#30 write_back_done = 1;
#10 write_back_done = 0;
// PB retry.
#10 PA = 0; PB = 1; RMS = 1; state = SectorInCacheB;
reset = 1; #10 reset = 0;
// #100 $stop;
// #100 $finish;
end
always @(new_state)
begin
if (PA == 1) SectorInCacheA = new_state ;
else if (PB == 1) SectorInCacheB = new_state ;
end
always @(posedge clk)
begin
if (Invalidate)
begin
#10 SectorInCacheB = 0;
#10 AllInvDone = 1;
#15 AllInvDone = 0;
end
else if (Cache_Sector_Fill)
begin
count = 0;
countE = 1;
// Intialize the Read_Done variable to 0; it
// it will be set to 1 by this test file after
// some delay.
READ_DONE = 0;
end
else if (AdrRetry)
begin
countE = 0;
send_abort = 1;
#40 send_abort = 0;
end
end
always @(posedge clk)
begin
if (READ_DONE == 1) READ_DONE = 0;
if (countE == 1)
begin
if ( count == 2 )
begin
READ_DONE = 1;
countE = 0;
end
else count = count + 1;
end
$display("SHit %b Abort %b RD_DONE %b WB_DONE %b Cache_Sector_Fill %b Inv
%b AllInvDone %b stateA %b stateB %b",
SHR, send_abort, READ_DONE, write_back_done, Cache_Sector_Fill, Invalidate,
AllInvDone, SectorInCacheA, SectorInCacheB);
// Added for v2v testing
$fdisplay(file1, $time,,"SHit %b Abort %b RD_DONE %b WB_DONE %b Cache_Sector_Fill
%b Inv %b AllInvDone %b stateA %b stateB %b",
SHR, send_abort, READ_DONE, write_back_done, Cache_Sector_Fill, Invalidate,
AllInvDone, SectorInCacheA, SectorInCacheB);
end
initial clk = 0;
always #(CYCLE/2) clk = ~clk ;
endmodule
//---------------------------------THANKS---------
|