/* * Animated prcessor RTL, Version 1.0 * Andrei Terechko, August 2005 * http://www.terechko.net/art/anim_proc/ * * Animated prcessor is a software art project illustrating the * possibility to create a dedicated processor hardware * for software art. The ISA (Instruction Set Architecture) * of the processor can be fine-tuned to the artistic software, * breaking free from the "boring" calculation-oriented ISAs * of x86, PowerPC, etc. * * The processor is written in Verilog, synthesizable for FPGAs * and ASIC technologies. A non-synthesizable testbench module * included for simulation purposes at the end of the file. * * NOTES: * - try synthesis * - try with icarus * - instruction interpret can be improved */ // processor and testbench defines `define ART_PERIOD 10 `define ART_C2Q 1 `define ART_MEM_SZ_LOG 8 `define ART_MEM_SZ (1<<`ART_MEM_SZ_LOG) `define ART_STRING_SZ 9 // ISA (Instruction Set Architecture) `define ART_GETBORN 0 `define ART_DIE 1 `define ART_RESURRECT 2 `define ART_BORE 3 `define ART_AGAIN 4 `define ART_DICE 5 `define ART_BOOZE 6 `define ART_PONDER 7 `define ART_HESITATE 8 `define ART_INTERPRET 9 `define ART_LIE 10 `define ART_CRY 11 `define ART_JOKE 12 `define ART_NAP 13 `define ART_FIL 14 `define ART_FUCK 15 `define ART_NUM_OPCODE 16 // outputs `define ART_BEG 3'd0 `define ART_MUTTER 3'd1 `define ART_SNORE 3'd2 `define ART_BULLSHIT 3'd3 `define ART_FLIRT 3'd4 `define ART_LOVE 3'd5 `define ART_INVENT 3'd6 `define ART_ITCH 3'd7 // state `define ART_DRINK_SOBER 2'b00 `define ART_DRINK_THIRSTY 2'b01 `define ART_DRINK_DRUNK 2'b10 `define ART_DRINK_HANGOV 2'b11 `define ART_TALK_SCREAM 2'b00 `define ART_TALK_LAUGH 2'b01 `define ART_TALK_WHISTLE 2'b10 `define ART_TALK_LISTEN 2'b11 `define ART_SLEEP_AWAKE 2'b00 `define ART_SLEEP_DROWSY 2'b01 `define ART_SLEEP_ASLEEP 2'b10 `define ART_SLEEP_SNORE 2'b11 `define ART_SEX_HORNY 2'b00 `define ART_SEX_EXCITED 2'b01 `define ART_SEX_INDIFFER 2'b10 `define ART_SEX_IMPOTENT 2'b11 `define ART_DEAD_NO 1'b0 `define ART_DEAD_YES 1'b1 module animated_processor ( // in/outs input [3:0] cmd, // instruction output reg [2:0] out, // output output [`ART_MEM_SZ_LOG-1:0] addr, // instruction address input clk, // clock input rst_an // asynchronous reset ); // processor state reg [1:0] sleep_state; reg [1:0] sex_state; reg [1:0] talk_state; reg [1:0] drink_state; reg [1:0] pos_state; reg dead_state; // are we dead? reg [`ART_MEM_SZ_LOG-1:0] pc; // program counter reg [31:0] prandom; // pseudo random TRUE/FALSE wire r1 = ^prandom; // logic always @(posedge clk or negedge rst_an) begin if (!rst_an) begin sleep_state <= #`ART_C2Q `ART_SLEEP_DROWSY; sex_state <= #`ART_C2Q `ART_SEX_INDIFFER; talk_state <= #`ART_C2Q `ART_TALK_LISTEN; drink_state <= #`ART_C2Q `ART_DRINK_SOBER; dead_state <= #`ART_C2Q `ART_DEAD_NO; pc <= #`ART_C2Q `ART_MEM_SZ_LOG'd0; prandom <= #`ART_C2Q 32'd1; // pseudo random basis end else begin prandom <= #`ART_C2Q prandom + 1; // pseudo random basis // program counter update if (cmd == `ART_AGAIN && r1) // pseudo random again pc <= #`ART_C2Q pc - `ART_MEM_SZ_LOG'd1; // prev else if (cmd == `ART_DICE && r1) // pseudo random dice pc <= #`ART_C2Q pc + `ART_MEM_SZ_LOG'd2; // skip else pc <= #`ART_C2Q pc + `ART_MEM_SZ_LOG'd1; // next // defaults: if (!r1) out <= #`ART_C2Q `ART_INVENT; // random invent else if (sleep_state == `ART_SLEEP_SNORE) // if fast asleep out <= #`ART_C2Q `ART_ITCH; // random itching else if (cmd == `ART_FUCK) out <= #`ART_C2Q `ART_LOVE; else if (cmd == `ART_LIE) out <= #`ART_C2Q `ART_BEG; else out <= #`ART_C2Q `ART_MUTTER; // drink_state if (cmd == `ART_GETBORN || cmd == `ART_RESURRECT) drink_state <= #`ART_C2Q `ART_DRINK_SOBER; else if (cmd == `ART_BOOZE || cmd == `ART_PONDER) drink_state <= #`ART_C2Q `ART_DRINK_DRUNK; else if (cmd == `ART_CRY || cmd == `ART_FUCK) drink_state <= #`ART_C2Q `ART_DRINK_THIRSTY; else if (drink_state == `ART_DRINK_DRUNK) drink_state <= #`ART_C2Q `ART_DRINK_HANGOV; if (drink_state == `ART_DRINK_DRUNK || drink_state == `ART_DRINK_HANGOV) begin if (cmd != `ART_NAP) // cross state influence talk_state <= #`ART_C2Q `ART_TALK_LAUGH; out <= #`ART_C2Q `ART_MUTTER; end // talk_state if (cmd == `ART_CRY || cmd == `ART_FUCK) talk_state <= #`ART_C2Q `ART_TALK_SCREAM; else if (cmd == `ART_RESURRECT || cmd == `ART_LIE || cmd == `ART_JOKE) talk_state <= #`ART_C2Q `ART_TALK_LAUGH; else if (cmd == `ART_DICE || cmd == `ART_PONDER) talk_state <= #`ART_C2Q `ART_TALK_WHISTLE; else if (cmd == `ART_BORE || cmd == `ART_HESITATE || cmd == `ART_INTERPRET || cmd == `ART_NAP) talk_state <= #`ART_C2Q `ART_TALK_LISTEN; if (cmd == `ART_LIE || cmd == `ART_JOKE) out <= #`ART_C2Q `ART_BULLSHIT; // sleep_state if (cmd == `ART_GETBORN || cmd == `ART_RESURRECT || cmd == `ART_PONDER || cmd == `ART_CRY || cmd == `ART_JOKE || cmd == `ART_DICE || cmd == `ART_FIL || cmd == `ART_FUCK) sleep_state <= #`ART_C2Q `ART_SLEEP_AWAKE; else if (cmd == `ART_BORE || cmd == `ART_AGAIN) sleep_state <= #`ART_C2Q `ART_SLEEP_DROWSY; else if (cmd == `ART_NAP) begin if (sleep_state == `ART_SLEEP_ASLEEP) begin sleep_state <= #`ART_C2Q `ART_SLEEP_SNORE; out <= #`ART_C2Q `ART_SNORE; end else sleep_state <= #`ART_C2Q `ART_SLEEP_ASLEEP; end else if (cmd == `ART_DIE) begin sleep_state <= #`ART_C2Q `ART_SLEEP_SNORE; end // sex_state if (cmd == `ART_DICE || cmd == `ART_CRY || cmd == `ART_FUCK) sex_state <= #`ART_C2Q `ART_SEX_HORNY; else if (cmd == `ART_RESURRECT || cmd == `ART_INTERPRET || cmd == `ART_LIE || cmd == `ART_FIL) sex_state <= #`ART_C2Q `ART_SEX_EXCITED; else if (cmd == `ART_BORE || cmd == `ART_AGAIN || cmd == `ART_NAP || cmd == `ART_PONDER) sex_state <= #`ART_C2Q `ART_SEX_INDIFFER; else if (cmd == `ART_HESITATE) sex_state <= #`ART_C2Q `ART_SEX_IMPOTENT; else if (cmd == `ART_BOOZE) begin // cross state dependencies if (sleep_state == `ART_SLEEP_AWAKE && sex_state == `ART_SEX_EXCITED) sex_state <= #`ART_C2Q `ART_SEX_HORNY; else sex_state <= #`ART_C2Q `ART_SEX_IMPOTENT; end if (sex_state == `ART_SEX_HORNY) // state dependent output out <= #`ART_C2Q `ART_LOVE; else if (sex_state == `ART_SEX_EXCITED) out <= #`ART_C2Q `ART_FLIRT; // special commands: if (cmd == `ART_DIE || (cmd != `ART_RESURRECT && dead_state == `ART_DEAD_YES)) begin sleep_state <= #`ART_C2Q `ART_SLEEP_DROWSY; sex_state <= #`ART_C2Q `ART_SEX_INDIFFER; talk_state <= #`ART_C2Q `ART_TALK_LISTEN; drink_state <= #`ART_C2Q `ART_DRINK_SOBER; dead_state <= #`ART_C2Q `ART_DEAD_YES; out <= #`ART_C2Q `ART_MUTTER; end else dead_state <= #`ART_C2Q `ART_DEAD_NO; end end assign addr = pc; endmodule // animated_processor `ifdef ART_SIMULATE // non-synthesizable testbench for simulation module animated_processor_tb; wire [3:0] cmd; // instruction wire [2:0] out; // output wire [`ART_MEM_SZ_LOG-1:0] addr; // instruction address reg clk; // clock reg rst_an; // asynchronous reset reg [3:0] mem[0:`ART_MEM_SZ-1]; // memory with the program integer counter; // instantiate DUT (design under test) animated_processor dut (cmd, out, addr, clk, rst_an ); // clk, rst_an initial begin counter = 32'd0; clk = 1'b0; // resetting the processor rst_an = 1'b1; #`ART_PERIOD ; // delay for 1 cycle rst_an = 1'b0; #(1*`ART_PERIOD) ; // reset for 3 cycles rst_an = 1'b1; end always forever #(`ART_PERIOD/2) clk = ~clk; // flip the clk always @(posedge clk) begin counter <= #`ART_C2Q counter + 32'd1; end // initialize the memory array with the code initial begin: memory_init integer i; integer rseed; integer temp; for (i = 0; i < `ART_MEM_SZ; i = i + 1) mem[i] = `ART_BORE; // default instructions is BORE /* -----\/----- EXCLUDED -----\/----- // PROGRAM 1. mem[0] = `ART_GETBORN; mem[1] = `ART_DIE; mem[2] = `ART_RESURRECT; mem[3] = `ART_DIE; -----/\----- EXCLUDED -----/\----- */ /* -----\/----- EXCLUDED -----\/----- // PROGRAM 2. mem[0] = `ART_GETBORN; mem[1] = `ART_BORE; mem[2] = `ART_AGAIN; mem[3] = `ART_BOOZE; mem[4] = `ART_AGAIN; mem[5] = `ART_NAP; mem[6] = `ART_DIE; -----/\----- EXCLUDED -----/\----- */ /* -----\/----- EXCLUDED -----\/----- // PROGRAM 3. mem[0] = `ART_GETBORN; mem[1] = `ART_FIL; mem[2] = `ART_FUCK; mem[3] = `ART_AGAIN; mem[4] = `ART_GETBORN; mem[5] = `ART_DIE; -----/\----- EXCLUDED -----/\----- */ /* -----\/----- EXCLUDED -----\/----- // PROGRAM 4. mem[0] = `ART_GETBORN; mem[1] = `ART_BORE; mem[2] = `ART_AGAIN; mem[3] = `ART_PONDER; mem[4] = `ART_HESITATE; mem[5] = `ART_PONDER; mem[6] = `ART_CRY; mem[7] = `ART_AGAIN; mem[8] = `ART_DICE; mem[9] = `ART_JOKE; mem[10] = `ART_DIE; -----/\----- EXCLUDED -----/\----- */ // PROGRAM N. Random. rseed = 0; for (i = 0; i < `ART_MEM_SZ; i = i + 1) begin temp = $random(rseed) % `ART_NUM_OPCODE; // %#operations if (temp < 0) temp = -temp; mem[i] = temp; end end assign cmd = mem[addr]; // insruction goes to the proc `ifdef ART_TRACE_ON // debug instruction trace // drink_state string function [`ART_STRING_SZ*8-1:0] drink_state_str; input integer number; begin case (number) `ART_DRINK_SOBER: drink_state_str = "sober"; `ART_DRINK_THIRSTY: drink_state_str = "thirsty"; `ART_DRINK_DRUNK: drink_state_str = "drunk"; `ART_DRINK_HANGOV: drink_state_str = "hangover"; default: drink_state_str = "x"; endcase // case(number) end endfunction // drink_state_str // talk_state string function [`ART_STRING_SZ*8-1:0] talk_state_str; input integer number; begin case (number) `ART_TALK_SCREAM: talk_state_str = "scream"; `ART_TALK_LAUGH: talk_state_str = "laugh"; `ART_TALK_WHISTLE: talk_state_str = "whistle"; `ART_TALK_LISTEN: talk_state_str = "listen"; default: talk_state_str = "x"; endcase // case(number) end endfunction // talk_state_str // sleep_state string function [`ART_STRING_SZ*8-1:0] sleep_state_str; input integer number; begin case (number) `ART_SLEEP_AWAKE: sleep_state_str = "awake"; `ART_SLEEP_DROWSY: sleep_state_str = "drowsy"; `ART_SLEEP_ASLEEP: sleep_state_str = "asleep"; `ART_SLEEP_SNORE: sleep_state_str = "snoring"; default: sleep_state_str = "x"; endcase // case(number) end endfunction // sleep_state_str // sex_state string function [`ART_STRING_SZ*8-1:0] sex_state_str; input integer number; begin case (number) `ART_SEX_HORNY: sex_state_str = "horny"; `ART_SEX_EXCITED: sex_state_str = "excited"; `ART_SEX_INDIFFER: sex_state_str = "dont care"; `ART_SEX_IMPOTENT: sex_state_str = "impotent"; default: sex_state_str = "x"; endcase // case(number) end endfunction // sex_state_str // command string function [`ART_STRING_SZ*8-1:0] cmd_str; input integer number; begin case (number) `ART_GETBORN: cmd_str = "getborn"; `ART_DIE: cmd_str = "die"; `ART_RESURRECT: cmd_str = "resurrect"; `ART_BORE: cmd_str = "bore"; `ART_AGAIN: cmd_str = "again"; `ART_DICE: cmd_str = "dice"; `ART_BOOZE: cmd_str = "booze"; `ART_PONDER: cmd_str = "ponder"; `ART_HESITATE: cmd_str = "hesitate"; `ART_INTERPRET: cmd_str = "interpret"; `ART_LIE: cmd_str = "lie"; `ART_CRY: cmd_str = "cry"; `ART_JOKE: cmd_str = "joke"; `ART_NAP: cmd_str = "nap"; `ART_FIL: cmd_str = "fil"; `ART_FUCK: cmd_str = "fuck"; default: cmd_str = "x"; endcase // case(number) end endfunction // cmd_str // output string function [`ART_STRING_SZ*8-1:0] out_str; input integer number; begin case (number) `ART_BEG : out_str = "beg"; `ART_MUTTER : out_str = "mutter"; `ART_SNORE : out_str = "snore"; `ART_BULLSHIT : out_str = "bullshit"; `ART_FLIRT : out_str = "flirt"; `ART_LOVE : out_str = "love"; `ART_INVENT : out_str = "invent"; `ART_ITCH : out_str = "itch"; default: out_str = "x"; endcase // case(number) end endfunction // cmd_str initial begin $display ("CLK PC COMMAND OUTPUT DRINK_STATE TALK_STATE SLEEP_STATE SEX_STATE"); $display ("-------------------------------------------------------------------------------------------------"); end always @(negedge clk) $display ("%02d: %h\t%s\t%s\t%s\t%s\t%s\t%s", counter, dut.pc, cmd_str(dut.cmd), out_str(dut.out), drink_state_str(dut.drink_state), talk_state_str(dut.talk_state), sleep_state_str(dut.sleep_state), sex_state_str(dut.sex_state)); `endif // break the simulation initial #(`ART_MEM_SZ*`ART_PERIOD) $finish; // finish the simulation endmodule // animated_processor_tb `endif