module critter_control (
input clock,
input reset,
input enable,
output val,
output [8:0] comp_addr,
input [64:0] comp_gene,
output [9:0] env_X,
output [9:0] env_Y,
input [17:0] env_param,
input [64:0] gene_in,
output [64:0] gene_out,
output child
);
parameter water = 4'd3, veg = 4'd7, temp = 4'd11, terrain = 4'd15,
alive = 65'd0, spec = 65'd1, actd = 65'd2,
pos_x = 65'd11, pos_y = 65'd20,
age = 65'd30, hunger = 65'd40,
gene1 = 65'd50, // camo-eyesight/metabolism
gene2 = 65'd60, // max age/disease resistance
cldwn = 65'd64, // cooldown for reproduction
rst = 4'd0, // reset
surv_1 = 4'd1, // age
surv_2 = 4'd2, // food
surv_3 = 4'd3, // disease
colide = 4'd4, // collision
mate_1 = 4'd5, // crossover gene1
mate_2 = 4'd6, // crossover gene2
pryprd = 4'd7, // prey/predator
muta_1 = 4'd8, // gene1 mutation
muta_2 = 4'd9, // gene2 mutation
move_1 = 4'd10, // x movement
move_2 = 4'd11, // y movement
p_xovr = 16'h2000, // 12.5%
p_mutH = 16'h0080, // 3.13%
p_mutL = 16'h0020; // 0.78%
reg [8:0] addr, env_addr_X, env_addr_Y;
reg valid, offspring;
reg [64:0] out;
assign gene_out = out;
assign val = valid;
assign child = offspring;
assign comp_addr = addr;
assign env_X = env_addr_X;
assign env_Y = env_addr_Y;
wire in_alive, in_spec, in_actd, comp_alive, comp_spec, comp_actd;
wire [8:0] in_x, in_y, comp_x, comp_y;
wire [9:0] in_age, in_hunger, in_gene1, in_gene2,
comp_age, comp_gene1, comp_gene2;
wire [3:0] in_cldwn, comp_cldwn;
assign in_alive = gene_in[alive];
assign in_spec = gene_in[spec];
assign in_actd = gene_in[actd];
assign in_x = gene_in[pos_x:actd+1];
assign in_y = gene_in[pos_y:pos_x+1];
assign in_age = gene_in[age:pos_y+1];
assign in_hunger = gene_in[hunger:age+1];
assign in_gene1 = gene_in[gene1:hunger+1];
assign in_gene2 = gene_in[gene2:gene1+1];
assign in_cldwn = gene_in[cldwn:gene2+1];
assign comp_alive = comp_gene[alive];
assign comp_spec = comp_gene[spec];
assign comp_actd = comp_gene[actd];
assign comp_x = comp_gene[pos_x:actd+1];
assign comp_y = comp_gene[pos_y:pos_x+1];
assign comp_age = comp_gene[age:pos_y+1];
assign comp_gene1 = comp_gene[gene1:hunger+1];
assign comp_gene2 = comp_gene[gene2:gene1+1];
assign comp_cldwn = comp_gene[cldwn:gene2+1];
reg [15:0] threshold[1:0];
wire rng_out[1:0];
wire rng_half;
RNG_decision rng_module1 (
.clk(clock),
.reset(reset),
.init(32'h2af45f44),
.threshold(threshold[0]),
.out(rng_out[0])
);
RNG_decision rng_module2 (
.clk(clock),
.reset(reset),
.init(32'h2af45f44),
.threshold(threshold[1]),
.out(rng_out[1])
);
RNG_decision rng_half_module (
.clk(clock),
.reset(reset),
.init(32'h2af45f44),
.threshold(16'h8000),
.out(rng_half)
);
wire signed [4:0] dst = (in_spec == comp_spec) ? 5'd2 : 5'd10;
wire in_range;
InRange range_module (
.x_1(in_x),
.x_2(comp_x),
.y_1(in_y),
.y_2(comp_y),
.range(dst),
.yn(in_range)
);
reg [3:0] state;
always @ (negedge clock) begin
if (reset) begin
state <= rst;
valid <= 1'b0;
end
else if (enable) begin
if (state == rst) begin
valid <= 1'b0;
// if alive, continue
if (in_alive) begin
addr <= 9'd0;
env_addr_X <= in_x;
env_addr_Y <= in_y;
out <= gene_in;
out[actd] <= 1'b0;
out[cldwn:gene2+1] <= (in_cldwn == 0) ? 4'd0 : in_cldwn - 4'd1;
offspring <= 1'b0;
state <= surv_1;
end
// if dead, ignore
else begin
valid <= 1'b1;
out <= gene_in;
end
end
// age check
else if (state == surv_1) begin
out[age:pos_y+1] <= in_age + 10'd1;
if (out[age:pos_y+1] > in_gene2) begin
out[alive] <= 1'b0;
valid <= 1'b1;
state <= rst;
end
else begin
state <= surv_2;
end
end
// food check
else if (state == surv_2) begin
// predator starved to death
if (in_spec == 1 && in_hunger <
({7'd0, gene_in[hunger+1], gene_in[hunger+3],
gene_in[hunger+5]} + 1)) begin
out[alive] <= 1'b0;
valid <= 1'b1;
state <= rst;
end
// prey starved to death
else if (in_spec == 0 && in_hunger <
({6'd0, gene_in[hunger+1], gene_in[hunger+3],
gene_in[hunger+5], gene_in[hunger+7]} + 1)) begin
out[alive] <= 1'b0;
valid <= 1'b1;
state <= rst;
end
else begin
state <= surv_3;
if (in_spec == 1) begin
out[hunger:age+1] <= in_hunger - 10'd1
- {7'd0, gene_in[hunger+1], gene_in[hunger+3],
gene_in[hunger+5]};
end
else begin
// rng for food spawn
threshold[0] <= {2'd0, env_param[water:0], 4'd0}
+ {2'd0, env_param[veg:water+1], 4'd0}
+ {4'd0, env_param[temp:veg+1], 2'd0}
- {4'd0, env_param[terrain:temp+1], 2'd0};
if (rng_out[0])
out[hunger:age+1] <= in_hunger
+ 10'h020 - {6'd0, gene_in[hunger+1], gene_in[hunger+3],
gene_in[hunger+5], gene_in[hunger+7]};
else
out[hunger:age+1] <= in_hunger - 10'd1
- {6'd0, gene_in[hunger+1], gene_in[hunger+3],
gene_in[hunger+5], gene_in[hunger+7]};
end
end
end
// disease check
else if (state == surv_3) begin
// rng for disease
threshold[0] <= {6'd0, env_param[water:0]}
+ {6'd0, env_param[veg:water+1]}
+ {6'd0, env_param[temp:veg+1]}
+ {4'd0, in_gene2, 2'd0};
// death by sickness
if (rng_out[0]) begin
out[alive] <= 1'b0;
valid <= 1'b1;
state <= rst;
end
else begin
state <= colide;
end
end
// collision check
else if (state == colide) begin
if (comp_alive && !comp_actd && in_range) begin
if (in_spec == comp_spec)
state <= mate_1;
else
state <= pryprd;
end
else begin
if (addr == 9'd10)
state <= muta_1;
else
addr <= addr + 9'd1;
end
end
// mating check
else if (state == mate_1) begin
if (in_actd || in_cldwn != 0 || comp_cldwn != 0 ||
in_age < (in_gene2>>3) || comp_age < (comp_gene2>>3)) begin
if (addr == 9'd10)
state <= muta_1;
else begin
addr <= addr + 9'd1;
state <= colide;
end
end
else begin
if(rng_half)
out[gene1:hunger+1] <= comp_gene1;
state <= mate_2;
end
end
else if (state == mate_2) begin
if(rng_half)
out[gene2:gene1+1] <= comp_gene2;
out[actd] <= 1'b1;
out[cldwn:gene2+1] <= 4'd15;
offspring <= 1'b1;
state <= muta_1;
end
// prey-predator check
else if (state == pryprd) begin
// comp is predator and current is prey
if (in_spec == 0 && in_gene1 < comp_gene1) begin
out[alive] <= 1'b0;
valid <= 1'b1;
state <= rst;
end
// current is predator and comp is prey
else if (in_spec == 1 && in_gene1 > comp_gene1) begin
out[hunger:age+1] <= in_hunger + 10'd040;
state <= muta_1;
end
else begin
if (addr == 9'd10)
state <= muta_1;
else begin
addr <= addr + 9'd1;
state <= colide;
end
end
end
// mutation
else if (state == muta_1) begin
threshold[0] <= p_mutL;
threshold[1] <= p_mutH;
if (rng_half) begin
if (rng_out[0] && rng_out[1])
out[gene1:hunger+1] <= out[gene1:hunger+1] + 10'd3;
else if (rng_out[1])
out[gene1:hunger+1] <= out[gene1:hunger+1] + 10'd2;
else if (rng_out[0])
out[gene1:hunger+1] <= out[gene1:hunger+1] + 10'd1;
end
else begin
if (rng_out[0] && rng_out[1])
out[gene1:hunger+1] <= out[gene1:hunger+1] - 10'd3;
else if (rng_out[1])
out[gene1:hunger+1] <= out[gene1:hunger+1] - 10'd2;
else if (rng_out[0])
out[gene1:hunger+1] <= out[gene1:hunger+1] - 10'd1;
end
state <= muta_2;
end
else if (state == muta_2) begin
if (rng_half) begin
if (rng_out[0] && rng_out[1])
out[gene2:gene1+1] <= out[gene2:gene1+1] + 10'd3;
else if (rng_out[1])
out[gene2:gene1+1] <= out[gene2:gene1+1] + 10'd2;
else if (rng_out[0])
out[gene2:gene1+1] <= out[gene2:gene1+1] + 10'd1;
end
else begin
if (rng_out[0] && rng_out[1])
out[gene2:gene1+1] <= out[gene2:gene1+1] - 10'd3;
else if (rng_out[1])
out[gene2:gene1+1] <= out[gene2:gene1+1] - 10'd2;
else if (rng_out[0])
out[gene2:gene1+1] <= out[gene2:gene1+1] - 10'd1;
end
state <= move_1;
end
// movement
else if (state == move_1) begin
threshold[0] <= 16'h4000 + {1'b0,in_hunger,5'b0};
if (rng_out[0]) begin
if (rng_half)
out[pos_x:actd+1] <= in_x + 9'd8 - {6'd0, env_param[terrain-1:temp+1]};
else
out[pos_x:actd+1] <= in_x - 9'd8 + {6'd0, env_param[terrain-1:temp+1]};
end
state <= move_2;
end
else if (state == move_2) begin
if (rng_out[0]) begin
if (rng_half)
out[pos_y:pos_x+1] <= in_y + 9'd8 - {6'd0, env_param[terrain-1:temp+1]};
else
out[pos_y:pos_x+1] <= in_y - 9'd8 + {6'd0, env_param[terrain-1:temp+1]};
end
valid <= 1'b1;
state <= rst;
end
end
end
endmodule
module RNG_decision (
input clk,
input reset,
input [31:0] init,
input [15:0] threshold,
output out
);
reg [31:0] gen_rand; // current random number
//make decision based on comparison to threshold
assign out = (gen_rand[31:16] <= threshold) ? 1'b1 : 1'b0;
//generate the random number
always @ (posedge clk) begin
if (reset)
gen_rand <= init;
else
gen_rand <= {gen_rand[30:0], gen_rand[27] ^ gen_rand[31]};
end
endmodule
module InRange (
input [8:0] x_1,
input [8:0] x_2,
input [8:0] y_1,
input [8:0] y_2,
input signed [4:0] range,
output yn
);
reg result;
assign yn = result;
wire signed [8:0] x = x_1 - x_2;
wire signed [8:0] y = y_1 - y_2;
always @ (*) begin
if ((x<range && x>-range) && (y<range && y>-range))
result <= 1'b1;
else
result <= 1'b0;
end
endmodule