+ship: Counter
+
+== Ports ===========================================================
+data in: in1
+data in: in2
+data in: inOp
+ constant REPEAT_C1_V1: 0
+ constant REPEAT_C1_V2: 1
+ constant REPEAT_C2_V1: 2
+ constant REPEAT_C2_V2: 3
+ constant PASS_C1_V1: 4
+ constant PASS_C1_V2: 5
+ constant PASS_C2_V1: 6
+ constant PASS_C2_V2: 7
+ constant DROP_C1_V1: 8
+ constant DROP_C1_V2: 9
+ constant DROP_C2_V1: 10
+ constant DROP_C2_V2: 11
+ constant COUNT: 12
+data out: out
+
+== Fleeterpreter ====================================================
+public void service() { }
+
+== FleetSim ==============================================================
+
+== FPGA ==============================================================
+
+ reg [`DATAWIDTH-1:0] temp;
+ initial temp = {`DATAWIDTH{1'b1}};
+ reg full;
+ initial full = 0;
+ wire op_count; assign op_count = inOp_d==12;
+ wire op_repeat; assign op_repeat = inOp_d[3:2]==0;
+ wire op_pass; assign op_pass = inOp_d[3:2]==1;
+ wire op_drop; assign op_drop = inOp_d[3:2]==2;
+ wire op_c1; assign op_c1 = (op_repeat || op_pass || op_drop) && !inOp_d[1];
+ wire op_c2; assign op_c2 = (op_repeat || op_pass || op_drop) && inOp_d[1];
+ wire op_v1; assign op_v1 = (op_repeat || op_pass || op_drop) && !inOp_d[0];
+ wire op_v2; assign op_v2 = (op_repeat || op_pass || op_drop) && inOp_d[0];
+ assign out_d_ = op_v1 ? in1_d : op_v2 ? in2_d : temp;
+
+ // FIXME: REPEAT with a count of zero will not work properly
+
+ always @(posedge clk) begin
+ if (!rst) begin
+ `reset
+ full <= 0;
+ end else begin
+ `flush
+ if (!in1_r && in1_a) in1_a <= 0;
+ if (!in2_r && in2_a) in2_a <= 0;
+ if (!inOp_r && inOp_a) inOp_a <= 0;
+ if (!inOp_r && !inOp_a) full <= 0;
+ if (out_r && out_a) begin
+ out_r <= 0;
+ if (op_count) temp <= temp - in2_d;
+ else temp <= temp - 1;
+ if (op_pass && op_v1) in1_a <= 1;
+ if (op_pass && op_v2) in2_a <= 1;
+ end else if (inOp_r && !inOp_a) begin
+ if (!full) begin
+ if (op_count && in1_r && !in1_a && in2_r && !in2_a) begin
+ temp <= in1_d[`DATAWIDTH-1:0] - in2_d[`DATAWIDTH-1:0];
+ in1_a <= 1;
+ full <= 1;
+ end else if (op_c1 && in1_r && !in1_a) begin
+ temp <= in1_d[`DATAWIDTH-1:0]-1;
+ in1_a <= 1;
+ full <= 1;
+ end else if (op_c2 && in2_r && !in2_a) begin
+ temp <= in2_d[`DATAWIDTH-1:0]-1;
+ in2_a <= 1;
+ full <= 1;
+ end
+ end else if (temp[`DATAWIDTH-1]) begin
+ full <= 0;
+ inOp_a <= 1;
+ if (op_count) begin
+ in2_a <= 1;
+ end else if (op_repeat && op_v1) begin
+ in1_a <= 1;
+ end else if (op_repeat && op_v2) begin
+ in2_a <= 1;
+ end
+ end else if (!out_r && !out_a) begin
+ if (op_count) begin
+ out_r <= 1;
+ end else if (op_v1 && in1_r && !in1_a) begin
+ if (op_drop) begin in1_a <= 1; temp <= temp-1; end
+ else out_r <= 1;
+ end else if (op_v2 && in2_r && !in2_a) begin
+ if (op_drop) begin in2_a <= 1; temp <= temp-1; end
+ else out_r <= 1;
+ end
+ end
+ end
+ end
+ end
+
+== Test =================================================================
+
+#ship counter : Counter
+#ship debug : Debug
+
+#expect 6
+#expect 3
+#expect 0
+#expect 2
+#expect 1
+#expect 0
+#expect 2
+#expect 2
+#expect 2
+#expect 2
+#expect 9
+#expect 9
+#expect 9
+
+counter.in1:
+ set word=9;
+ deliver;
+ set word=3;
+ deliver;
+ set word=4;
+ deliver;
+ set word=3;
+ deliver;
+
+counter.in2:
+ set word=3;
+ deliver;
+ set word=1;
+ deliver;
+ set word=2;
+ deliver;
+ set word=9;
+ deliver;
+
+counter.inOp:
+ set word=12;
+ deliver;
+ deliver;
+ set word=1;
+ deliver;
+ deliver;
+
+counter.out:
+ set ilc=*;
+ collect, send to debug.in;
+
+debug.in:
+ set ilc=*;
+ recv, deliver;
+
+== Contributors =========================================================
+Adam Megacz <megacz@cs.berkeley.edu>