-
Notifications
You must be signed in to change notification settings - Fork 55
/
stack2pipe4.v
76 lines (49 loc) · 2.01 KB
/
stack2pipe4.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
`default_nettype none
`define WIDTH 16
module stack2pipe4(
input wire clk,
output wire [`WIDTH-1:0] rd,
input wire we,
input wire [1:0] delta,
input wire [`WIDTH-1:0] wd);
parameter DEPTH = 18;
localparam BITS = (`WIDTH * DEPTH) - 1;
localparam STATESIZE = `WIDTH * (DEPTH + 1); // complete size of a stack, ie tail+head.
// there are four stacks in total, accessed always in round-robin order.
localparam STATEBITS = STATESIZE - 1; // for wire out of delay
localparam DELAYBITS = (STATESIZE * 3) - 1; // bits to hold the other three stacks.
wire move = delta[0];
wire pop = delta[1];
// these two still written to "now", ie, are the results to save from the present cycle.
reg [15:0] head;
reg [BITS:0] tail;
reg [DELAYBITS:0] delay;
wire [15:0] headN, oldhead;
wire [BITS:0] tailN, oldtail;
wire [DELAYBITS:0] delayN;
// read from the delay fifo, replaced head and tail as the place to read from the old version of current stack.
assign {oldtail, oldhead} = delay[STATEBITS:0];
assign rd = oldhead;
// note these retain old values if not move (and not we and not push). This used to be implicit, but can't be now, since head and tail will cycle through all the stacks, even if neither a move nor a write.
assign headN = we ? wd : (move ? oldtail[15:0] : oldhead);
assign tailN = move ? (pop ? {16'h55aa, oldtail[BITS:16]} : {oldtail[BITS-16:0], oldhead}) : oldtail;
// this is a clock stale already, since it takes it *from* head and tail.
// delay will delay it another three clock cycles.
assign delayN = {tail, head, delay[DELAYBITS:STATESIZE]};
always @(posedge clk) begin
// pass around the other three stacks.
delay <= delayN;
// update the current stack.
head <= headN;
tail <= tailN;
end
`ifdef VERILATOR
int depth /* verilator public_flat */;
always @(posedge clk) begin
if (delta == 2'b11)
depth <= depth - 1;
if (delta == 2'b01)
depth <= depth + 1;
end
`endif
endmodule