`timescale 1ns / 1ns module nanoengine(bus, CLK, ALE, CS0, WE, RD, INT); inout bus; input INT; output CLK, ALE, CS0, WE, RD; reg CLK, ALE, CS0, WE, RD; wire [31:0] bus; reg [3:0] state; reg bus_drive, bus_addr, INT_h1, INT_h2, int_pend, int_report; reg [15:0] data_reg, addr_reg, result; integer cc, wait_counter, rw; // 25 MHz Bus clock initial CLK = 1; always #20 CLK = ~CLK; // These registers receive command code and operand words from the // master command reader, and holds them while the task below // interpret them. reg [7:0] cmd; reg [31:0] op [15:0]; initial begin CS0 = 0; // Nothing else going on, just leave the bus enabled ALE = 0; WE = 1; RD = 1; state = 1; result = 0; INT_h1 = 0; INT_h2 = 0; int_pend = 0; int_report = 0; // 25 MHz bus clock for (cc = 1; cc < 1000; cc=cc+1) begin CLK = 0; #20; CLK = 1; #20; end end always @(posedge CLK) begin INT_h1 <= INT; INT_h2 <= INT_h1; if (INT_h1 & ~INT_h2) int_pend <= 1; case (state) 1: begin RD <= 1; WE <= 1; bus_drive <= 0; // interrupts? if (int_pend) begin int_pend <= 0; wait_counter = 0; int_report = 1; end if (wait_counter > 0) wait_counter <= wait_counter - 1; else begin $message_response(result, int_report); int_report = 0; $message_command(cmd, op); // $display("command %d",cmd); addr_reg = op[0]; data_reg = op[1]; wait_counter = op[2]; if (cmd == 1) state <= 2; // write if (cmd == 2) state <= 6; // read if (cmd == 3) $finish; // otherwise, stay idle end end 2: begin // ALE write $display("ALE 0x%x",addr_reg); ALE <= 1; bus_drive <= 1; bus_addr <= 1; state <= 3; end 3: begin // write gap $display("write data 0x%x",data_reg); ALE <= 0; state <= 4; end 4: begin // write 2 WE <= 0; bus_addr <= 0; state <= 5; end 5: begin // write 2 state <= 1; end 6: begin // ALE read $display("ALE 0x%x",addr_reg); ALE <= 1; bus_drive <= 1; bus_addr <= 1; state <= 7; end 7: begin // read gap ALE <= 0; state <= 8; end 8: begin // read 1 RD <= 0; bus_drive <= 0; state <= 9; end 9: begin // read 2 state <= 10; end 10: begin // read 3 $display("read value %x",bus); result <= bus; RD <= 1; state <= 1; end endcase end assign bus = bus_drive ? ( bus_addr ? addr_reg : data_reg ) : 16'hZZZZ; endmodule