From f2ac09472bd691f3a20c8e4ccf0fec2a2e9c98c4 Mon Sep 17 00:00:00 2001 From: Gagan Kumar Date: Fri, 3 Jan 2025 23:32:21 -0800 Subject: [PATCH 1/8] Improve verilog files --- emulator/chipset.v | 184 +++++++++------ emulator/chipset_test.v | 10 + emulator/com/add_4.v | 6 + emulator/com/add_4_test.v | 20 ++ emulator/com/alu.v | 30 +++ emulator/com/alu_test.v | 128 ++++++++++ emulator/com/decoder.v | 22 ++ emulator/com/decoder_test.v | 61 +++++ emulator/com/flipflop.v | 30 +++ emulator/com/flipflop_test.v | 58 +++++ emulator/com/latch.v | 13 ++ emulator/com/latch_test.v | 73 ++++++ emulator/com/mux.v | 28 +++ emulator/com/mux_test.v | 69 ++++++ emulator/{module/mblock => com}/rom.v | 12 +- emulator/{module/mblock => com}/rom_boot.bin | 0 emulator/{module/mblock => com}/rom_test.bin | 0 emulator/{module/mblock => com}/rom_test.v | 10 +- emulator/com/stage0.v | 26 +++ emulator/com/stage0_test.v | 64 +++++ emulator/com/stage1.v | 36 +++ emulator/com/stage1_test.v | 54 +++++ emulator/lib/adder.v | 7 - emulator/lib/adder_test.v | 22 -- emulator/lib/alu.v | 25 -- emulator/lib/alu_test.v | 106 --------- emulator/lib/decoder.v | 22 -- emulator/lib/decoder_test.v | 61 ----- emulator/lib/flipflop.v | 30 --- emulator/lib/flipflop_test.v | 58 ----- emulator/lib/latch.v | 13 -- emulator/lib/latch_test.v | 73 ------ emulator/lib/mux.v | 55 ----- emulator/lib/mux_test.v | 70 ------ emulator/module/boot_control.v | 25 +- emulator/module/boot_control_test.v | 51 ++-- emulator/module/clock.v | 84 +++---- emulator/module/clock_test.v | 30 +-- emulator/module/mblock/mblock.v | 52 ++--- emulator/module/mblock/mblock_test.v | 116 ++++----- emulator/module/mblock/mconst.v | 14 +- emulator/module/mblock/mconst_test.v | 42 ++-- emulator/module/mblock/ram.v | 15 -- emulator/module/mblock_mux.v | 100 ++++---- emulator/module/stage0_ins_resolver.v | 14 -- emulator/seq/ram.v | 18 ++ emulator/{module/mblock => seq}/ram_test.v | 17 +- emulator/seq/register.v | 23 ++ emulator/seq/register_test.v | 63 +++++ output/programs/3_led_switch.bin | 4 - output/programs/3_led_switch_resolved.asm | 4 - output/programs/boot_sequence.bin | 17 -- output/programs/boot_sequence_resolved.asm | 17 -- output/programs/ping_pong.bin | 198 ---------------- output/programs/ping_pong_resolved.asm | 234 ------------------- planner/memory.py | 4 +- planner/sim/bin_parser.py | 14 +- planner/sim/devices.py | 12 +- programs/boot_sequence.asm | 11 +- programs/ping_pong.asm | 3 - 60 files changed, 1253 insertions(+), 1405 deletions(-) create mode 100644 emulator/chipset_test.v create mode 100644 emulator/com/add_4.v create mode 100644 emulator/com/add_4_test.v create mode 100644 emulator/com/alu.v create mode 100644 emulator/com/alu_test.v create mode 100644 emulator/com/decoder.v create mode 100644 emulator/com/decoder_test.v create mode 100644 emulator/com/flipflop.v create mode 100644 emulator/com/flipflop_test.v create mode 100644 emulator/com/latch.v create mode 100644 emulator/com/latch_test.v create mode 100644 emulator/com/mux.v create mode 100644 emulator/com/mux_test.v rename emulator/{module/mblock => com}/rom.v (55%) rename emulator/{module/mblock => com}/rom_boot.bin (100%) rename emulator/{module/mblock => com}/rom_test.bin (100%) rename emulator/{module/mblock => com}/rom_test.v (88%) create mode 100644 emulator/com/stage0.v create mode 100644 emulator/com/stage0_test.v create mode 100644 emulator/com/stage1.v create mode 100644 emulator/com/stage1_test.v delete mode 100644 emulator/lib/adder.v delete mode 100644 emulator/lib/adder_test.v delete mode 100644 emulator/lib/alu.v delete mode 100644 emulator/lib/alu_test.v delete mode 100644 emulator/lib/decoder.v delete mode 100644 emulator/lib/decoder_test.v delete mode 100644 emulator/lib/flipflop.v delete mode 100644 emulator/lib/flipflop_test.v delete mode 100644 emulator/lib/latch.v delete mode 100644 emulator/lib/latch_test.v delete mode 100644 emulator/lib/mux.v delete mode 100644 emulator/lib/mux_test.v delete mode 100644 emulator/module/mblock/ram.v delete mode 100644 emulator/module/stage0_ins_resolver.v create mode 100644 emulator/seq/ram.v rename emulator/{module/mblock => seq}/ram_test.v (88%) create mode 100644 emulator/seq/register.v create mode 100644 emulator/seq/register_test.v delete mode 100644 output/programs/3_led_switch.bin delete mode 100644 output/programs/3_led_switch_resolved.asm delete mode 100644 output/programs/boot_sequence.bin delete mode 100644 output/programs/boot_sequence_resolved.asm delete mode 100644 output/programs/ping_pong.bin delete mode 100644 output/programs/ping_pong_resolved.asm diff --git a/emulator/chipset.v b/emulator/chipset.v index cb67033..31f0b23 100644 --- a/emulator/chipset.v +++ b/emulator/chipset.v @@ -1,15 +1,46 @@ `include "emulator/module/clock.v" +`include "emulator/seq/register.v" -module CHIPSET(); - // Global Registers - reg execute_from_brom; - // Stages +module CHIPSET( + input reset, + input[31:0] ram_value, + output[31:0] ram_address, + output ram_is_write, + ); + + reg is_powered_on; + reg execute_from_ram; + reg[15:0] pc, pc_next; + + // Clock wire[0:3] clk; - wire[0:3] is_stage; CLOCK clock( - .clk(clk[0:3]), - .is_stage(is_stage[0:3])); + .clk(clk[0:3])); + + // BROM + wire[15:0] brom_address; + wire[31:0] brom_value; + ROM_BOOT brom(.out(brom_value), .address(brom_address)); + + // RAM + reg ram_is_write; + wire[15:0] ram_address; + reg[31:0] ram_in; + wire[31:0] ram_value; + RAM_32bit_16aline ram( + .out(ram_value), + .in(ram_in), + .address(ram_address), + .is_write(ram_is_write), + .clk(clk[3])); + + + wire[15:0] ram_address_stage0; + // TODO: Updated ram_address + assign ram_address = ram_address_stage0; + + // Boot Sequence // @@ -23,50 +54,53 @@ module CHIPSET(); // // Assumption: No stateful IO devices are connected. // TODO: Implement `execute_from_brom` update implementation. - wire is_powered_on; - BOOT_CONTROL boot_control(.is_powered_on(is_powered_on)); - - - // MBLOCK is a continous circuit and doesn't depend on clock - // but the behaviour do depend on stage which is abstracted. - wire[15:0] program_counter; - wire[1:0] mblock_selector; - wire[15:0] mblock_address; - wire[31:0] mblock_input; - wire[31:0] mblock_output; - wire mblock_write; - - MBLOCK_MUX mblock_mux( - .mblock_address(mblock_address[15:0]), - .mblock_selector(mblock_selector[1:0]), - .execute_from_brom(execute_from_brom), - .is_stage(is_stage[0:3]), - .address0(program_counter), - .address1(v0_source), - .address2(v1_source), - .address3(v2_source), - .is_write(4'b0000)); - - MBLOCK mblock( - .out(mblock_output), - .selector(mblock_selector), - .in(mblock_input), - .address(mblock_address), - .is_write(mblock_write)); + + // Operates on clk[3] down + BOOT_CONTROL boot_control( + .is_powered_on(is_powered_on), + .pc_next(pc_next), + .flags(flags), + .reset(reset), + .clk(clk[3]), + ); + + + // Following circuit is continous within each stages + // with exception of RAM write which relies on clock; + // wire[15:0] program_counter; + // wire[1:0] mblock_selector; + // wire[15:0] mblock_address; + // wire[31:0] mblock_input; + // wire[31:0] mblock_output; + // wire mblock_write; + // STAGE0 + wire[31:0] instruction_binary; + STAGE0 instruction_resolver( + .instruction_binary(instruction_binary), + .ram_address(ram_address_stage0), + .brom_address(brom_address), + .ram_value(ram_value), + .brom_value(brom_value), + .pc(pc), + .execute_from_ram(execute_from_ram)); + + // STAGE1 + wire[31:0] instruction_binary_cached; + REGISTER_up_16b r_ins_bin( + .out(instruction_binary_cached), + .in(instruction_binary), + .clk(clk[1])); + + wire[3:0] mblock_alu_op = instruction_binary_cached[3:0]; + wire[3:0] mblock_s1 = instruction_binary_cached[5:4]; + wire[1:0] mblock_s2 = instruction_binary_cached[8:6]; + wire[2:0] mblock_s3 = instruction_binary_cached[11:9]; + wire[7:0] vrw_source = instruction_binary_cached[23:16]; + wire[7:0] vr_source = instruction_binary_cached[31:24]; - // TODO: Ensure MBLOCK supplies expectations. - // MBLOCK_MUX is expected to fetch MBLOCK at `program_counter` from - // BROM / RAM based on `execute_from_brom` and redirect the value - // to full_ins via mblock_output. - // @stage0 posedge following values should freeze. - wire[7:0] v0_source, v1_source, v2_source, instruction_op; - INS_RESOLVER stage0( - .v0(v0_source), .v1(v1_source), .v2(v2_source), .op(instruction_op), - .full_ins(.mblock_output), - clk[0]); // STAGE1 @@ -77,10 +111,15 @@ module CHIPSET(); // instruction_op breakdowns and redirect the value into v0. // @stage1 posedge following should freeze. - wire[31:0] v0; + wire[31:0] vr_value; +; FETCH_AND_STORE stage1( - .value(v0), - .in(mblock_output), + .vr_value(vr_value), + .is_powered_on(is_powered_on), + .pc_next(pc_next), + .pc(pc), + .vr_source(vr_source), + .mblock_s1(mblock_s1), .clk(clk[1])); // STAGE2 @@ -90,39 +129,30 @@ module CHIPSET(); // instruction_op breakdowns and redirect the value into v0. // @stage2 posedge following should freeze. - wire[31:0] v1; + wire[31:0] vrw_value; FETCH_AND_STORE stage2( - .value(v1), - .in(mblock_output), + .vrw_value(vrw_value), + .is_powered_on(is_powered_on), + .vr_source(vr_source), + .vr_value(vr_value), + .vrw_source(vr_source), + .mblock_s2(mblock_s2), .clk(clk2)); - // STAGE3 - // TODO: alu_op should be computed using instruction_op breakdowns. - wire[3:0] alu_op; - wire[31:0] v2; - - wire flag_alu_zero; + wire[31:0] vw_value; ALU alu( - .out(v2), - .is_zero(flag_alu_zero), - .op(alu_op), - .in0(v0), - .in1(v1)); - - // MBLOCK input only comes from ALU output. - assign mblock_input = v2; - - // TODO: jump instruction - PC_NEXT pc_next( - .program_counter_next(program_counter_next), - .program_counter(program_counter), - .is_powered_on(is_powered_on)); + .out(vw_value), + .is_zero(flags[FLAGS_BIT_VW_ZERO]), + .vr_value(vr_value), + .vrw_value(vrw_value), + .op(mblock_alu_op)); // @stage3 posedge following should freeze. - wire[15:0] program_counter_next; - flipflop16 pc( - .out(program_counter), - .in(program_counter_next), + FETCH_AND_STORE stage2( + .vw_value(vw_value), + .vrw_value(vrw_value), + .vrw_source(vrw_source), + .mblock_s3(mblock_s3), .clk(clk3)); endmodule \ No newline at end of file diff --git a/emulator/chipset_test.v b/emulator/chipset_test.v new file mode 100644 index 0000000..c0a5449 --- /dev/null +++ b/emulator/chipset_test.v @@ -0,0 +1,10 @@ +// `include "emulator/chipset.v" + +module chipset_test; + // wire reset; // reset button + // CHIPSET dut(.reset(reset)); + + // initial begin + // assign reset = 0; // button is never pressed. + // end +endmodule diff --git a/emulator/com/add_4.v b/emulator/com/add_4.v new file mode 100644 index 0000000..ee5470d --- /dev/null +++ b/emulator/com/add_4.v @@ -0,0 +1,6 @@ +module ADD_4_16b( + output[15:0] out, + input[15:0] in); + + assign out = in + 4; +endmodule diff --git a/emulator/com/add_4_test.v b/emulator/com/add_4_test.v new file mode 100644 index 0000000..9a00d4f --- /dev/null +++ b/emulator/com/add_4_test.v @@ -0,0 +1,20 @@ +`include "emulator/com/add_4.v" + +module adder_test; + reg[15:0] in; + wire[15:0] out; + + ADD_4_16b dut( + .out(out), + .in(in)); + + initial begin + in = 2536; + # 10 + $display("ADDER_TEST: in=%b out=%b", in, out); + if (out !== 2540) begin + $error("latch failed"); + $fatal(1); + end + end +endmodule diff --git a/emulator/com/alu.v b/emulator/com/alu.v new file mode 100644 index 0000000..8f4bb7f --- /dev/null +++ b/emulator/com/alu.v @@ -0,0 +1,30 @@ +`define ALU_OP_ADD 4'b0000 + + +module ALU ( + output[31:0] out, + output is_zero, + input[3:0] op, + input[31:0] in_r, + input[31:0] in_rw); + + reg[31:0] mem; + + always @(op, in_r, in_rw) begin + case(op) + 4'b0000: mem = in_r+in_rw; + 4'b0001: mem = in_r-in_rw; + 4'b0010: mem = (in_r<>in_rw); + 4'b0100: mem = (in_r); + 4'b0101: mem = (in_rw); + 4'b0110: mem = (in_r&in_rw); + 4'b0111: mem = (in_r|in_rw); + 4'b1000: mem = (in_r^in_rw); + 4'b1001: mem = (((in_r&255)<<8)|in_rw&255); + endcase + end + assign out[31:0] = mem[31:0]; + assign is_zero = (mem == 0); + +endmodule diff --git a/emulator/com/alu_test.v b/emulator/com/alu_test.v new file mode 100644 index 0000000..245ab11 --- /dev/null +++ b/emulator/com/alu_test.v @@ -0,0 +1,128 @@ +`include "emulator/com/alu.v" + +module alu_test; + reg[31:0] in_r, in_rw; + reg[3:0] op; + wire[31:0] out; + wire is_zero; + + ALU dut( + .out(out), + .is_zero(is_zero), + .op(op), + .in_r(in_r), + .in_rw(in_rw)); + + initial begin + // ADD + op = 4'b0000; + in_r = 2536; + in_rw = 113; + # 10 + $display("ALU_TEST: op=%b in_r=%b in_rw=%b", op, in_r, in_rw); + if (out !== 2649 || is_zero !== 0) begin + $error("alu failed"); + $fatal(1); + end + + // SUB + op = 4'b0001; + in_r = 2536; + in_rw = 113; + # 10 + $display("ALU_TEST: op=%b in_r=%b in_rw=%b", op, in_r, in_rw); + if (out !== 2423 || is_zero !== 0) begin + $error("alu failed"); + $fatal(1); + end + + // LSR + op = 4'b0010; + in_r = 2536; + in_rw = 2; + # 10 + $display("ALU_TEST: op=%b in_r=%b in_rw=%b", op, in_r, in_rw); + if (out !== 10144 || is_zero !== 0) begin + $error("alu failed"); + $fatal(1); + end + + // RSR + op = 4'b0011; + in_r = 2536; + in_rw = 4; + # 10 + $display("ALU_TEST: op=%b in_r=%b in_rw=%b", op, in_r, in_rw); + if (out !== 158 || is_zero !== 0) begin + $error("alu failed"); + $fatal(1); + end + + // Fist Operand + op = 4'b0100; + in_r = 2536; + in_rw = 4; + # 10 + $display("ALU_TEST: op=%b in_r=%b in_rw=%b", op, in_r, in_rw); + if (out !== 2536 || is_zero !== 0) begin + $error("alu failed"); + $fatal(1); + end + + // Second Operand + op = 4'b0101; + in_r = 2536; + in_rw = 4; + # 10 + $display("ALU_TEST: op=%b in_r=%b in_rw=%b", op, in_r, in_rw); + if (out !== 4 || is_zero !== 0) begin + $error("alu failed"); + $fatal(1); + end + + // AND + op = 4'b0110; + in_r = 2536; + in_rw = 113; + # 10 + $display("ALU_TEST: op=%b in_r=%b in_rw=%b", op, in_r, in_rw); + if (out !== 96 || is_zero !== 0) begin + $error("alu failed"); + $fatal(1); + end + + // OR + op = 4'b0111; + in_r = 2536; + in_rw = 3113; + # 10 + $display("ALU_TEST: op=%b in_r=%b in_rw=%b", op, in_r, in_rw); + if (out !== 3561 || is_zero !== 0) begin + $error("alu failed"); + $fatal(1); + end + + // XOR + op = 4'b1000; + in_r = 2536; + in_rw = 3113; + # 10 + $display("ALU_TEST: op=%b in_r=%b in_rw=%b", op, in_r, in_rw); + if (out !== 1473 || is_zero !== 0) begin + $error("alu failed"); + $fatal(1); + end + + // R_SHL8_RW_OR + op = 4'b01001; + in_r = 213; + in_rw = 123; + # 10 + $display("ALU_TEST: op=%b in_r=%b in_rw=%b", op, in_r, in_rw); + if (out !== 54651 || is_zero !== 0) begin + $error("alu failed"); + $fatal(1); + end + + end +endmodule diff --git a/emulator/com/decoder.v b/emulator/com/decoder.v new file mode 100644 index 0000000..3e9efd4 --- /dev/null +++ b/emulator/com/decoder.v @@ -0,0 +1,22 @@ +// module DECODER_4_2( +// output[3:0] out, +// input[1:0] in); + +// assign out[0] = (~in[1] & ~in[0]); +// assign out[1] = (~in[1] & in[0]); +// assign out[2] = ( in[1] & ~in[0]); +// assign out[3] = ( in[1] & in[0]); +// endmodule + + +// module DECODER_8_3( +// output[7:0] out, +// input[2:0] in); + +// wire [3:0] _out; +// DECODER_4_2 d(_out[3:0], in[1:0]); + +// wire not_in2 = ~in[2]; +// assign out[3:0] = _out[3:0] & {not_in2, not_in2, not_in2, not_in2}; +// assign out[7:4] = _out[3:0] & {in[2], in[2], in[2], in[2]}; +// endmodule diff --git a/emulator/com/decoder_test.v b/emulator/com/decoder_test.v new file mode 100644 index 0000000..f62d5fa --- /dev/null +++ b/emulator/com/decoder_test.v @@ -0,0 +1,61 @@ +// `include "emulator/lib/decoder.v" + +module decoder_4_2_test; +// reg [1:0] in; +// wire [3:0] out; + +// DECODER_4_2 dut(.out(out), .in(in)); + +// initial begin +// in = 2'b00; +// # 10 +// $display("DECODER_TEST: in=%b out=%b", in, out); +// if (out != 4'b0001) begin +// $error("decoder failed"); +// end +// in = 2'b01; +// # 10 +// $display("DECODER_TEST: in=%b out=%b", in, out); +// if (out != 4'b0010) begin +// $error("decoder failed"); +// end +// in = 2'b10; +// # 10 +// $display("DECODER_TEST: in=%b out=%b", in, out); +// if (out != 4'b0100) begin +// $error("decoder failed"); +// end +// in = 2'b11; +// # 10 +// $display("DECODER_TEST: in=%b out=%b", in, out); +// if (out != 4'b1000) begin +// $error("decoder failed"); +// end + +// end +endmodule + + +// module decoder_8_3_test; +// reg [2:0] in; +// wire [7:0] out; + +// DECODER_8_3 dut(.out(out), .in(in)); + +// initial begin +// in = 3'b010; +// # 10 +// $display("DECODER_TEST: in=%b out=%b", in, out); +// if (out != 8'b00000100) begin +// $error("decoder failed"); +// $fatal(1); +// end +// in = 3'b101; +// # 10 +// $display("DECODER_TEST: in=%b out=%b", in, out); +// if (out != 8'b00100000) begin +// $error("decoder failed"); +// $fatal(1); +// end +// end +// endmodule diff --git a/emulator/com/flipflop.v b/emulator/com/flipflop.v new file mode 100644 index 0000000..b989fdc --- /dev/null +++ b/emulator/com/flipflop.v @@ -0,0 +1,30 @@ +// module __flipflop #(parameter BITS = 32)( +// output[BITS-1:0] out, +// input clk, +// input[BITS-1:0] in); + +// reg[BITS-1:0] mem; +// always @(posedge clk) begin +// mem[BITS-1:0] <= in[BITS-1:0]; +// end +// assign out[BITS-1:0] = mem[BITS-1:0]; +// endmodule + +// module flipflop32( +// output[31:0] out, +// input clk, +// input[31:0] in); + +// __flipflop #(.BITS(32)) ff(.out(out), .clk(clk), .in(in)); + +// endmodule + +// module flipflop16( +// output[15:0] out, +// input clk, +// input[15:0] in); + +// __flipflop #(.BITS(16)) ff(.out(out), .clk(clk), .in(in)); + +// endmodule + diff --git a/emulator/com/flipflop_test.v b/emulator/com/flipflop_test.v new file mode 100644 index 0000000..c3b0c95 --- /dev/null +++ b/emulator/com/flipflop_test.v @@ -0,0 +1,58 @@ +// `include "emulator/lib/flipflop.v" + +module flipflop_test; +// reg[31:0] in; +// reg clk; +// wire[31:0] out; + +// flipflop32 dut(.out(out), .in(in), .clk(clk)); + +// initial begin +// clk = 0; +// in = 32'b00110110110101010100101101101000; +// # 10 +// clk = 1; +// # 10 +// $display("FLIPFLOP: in=%b out=%b clk=%b", in, out, clk); +// if (out !== 32'b00110110110101010100101101101000) begin +// $error("flipflop failed"); +// $fatal(1); +// end + +// clk = 0; +// # 10 +// in = 32'b01100011111101011011010100000100; +// # 10 +// $display("FLIPFLOP: in=%b out=%b clk=%b", in, out, clk); +// if (out !== 32'b00110110110101010100101101101000) begin +// $error("flipflop failed"); +// $fatal(1); +// end + +// in = 32'b10101100011011010010001010011001; +// # 10 +// $display("FLIPFLOP: in=%b out=%b clk=%b", in, out, clk); +// if (out !== 32'b00110110110101010100101101101000) begin +// $error("flipflop failed"); +// $fatal(1); +// end + +// clk = 1; +// # 10 +// $display("FLIPFLOP: in=%b out=%b clk=%b", in, out, clk); +// if (out !== 32'b10101100011011010010001010011001) begin +// $error("flipflop failed"); +// $fatal(1); +// end + +// clk = 0; +// # 10 +// in = 32'b10101011001010001101001000011011; +// # 10 +// $display("FLIPFLOP: in=%b out=%b clk=%b", in, out, clk); +// if (out !== 32'b10101100011011010010001010011001) begin +// $error("flipflop failed"); +// $fatal(1); +// end +// end +endmodule diff --git a/emulator/com/latch.v b/emulator/com/latch.v new file mode 100644 index 0000000..caf3ab5 --- /dev/null +++ b/emulator/com/latch.v @@ -0,0 +1,13 @@ +// module latch_d(output out, input in, input enable); +// // we want latch to always be on and returing +// // while write when d is active. + +// reg mem; + +// always @(in, enable) begin +// if (enable) begin +// mem <= in; +// end +// end +// assign out = mem; +// endmodule diff --git a/emulator/com/latch_test.v b/emulator/com/latch_test.v new file mode 100644 index 0000000..cecf344 --- /dev/null +++ b/emulator/com/latch_test.v @@ -0,0 +1,73 @@ +// `include "emulator/lib/latch.v" + +module latch_d_test; +// reg I, ENABLE; +// wire O; + +// latch_d dut(.out(O), .in(I), .enable(ENABLE)); + +// initial begin +// I = 0; +// ENABLE = 1; +// # 10 +// $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); +// if (O !== 0) begin +// $error("latch failed"); +// $fatal(1); +// end + +// I = 1; +// ENABLE = 1; +// # 10 +// $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); +// if (O !== 1) begin +// $error("latch failed"); +// $fatal(1); +// end + +// I = 1; +// ENABLE = 0; +// # 10 +// $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); +// if (O !== 1) begin +// $error("latch failed"); +// $fatal(1); +// end + +// I = 0; +// ENABLE = 0; +// # 10 +// $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); +// if (O !== 1) begin +// $error("latch failed"); +// $fatal(1); +// end + +// I = 1; +// ENABLE = 0; +// # 10 +// $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); +// if (O !== 1) begin +// $error("latch failed"); +// $fatal(1); +// end + +// I = 0; +// ENABLE = 0; +// # 10 +// $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); +// if (O !== 1) begin +// $error("latch failed"); +// $fatal(1); +// end + +// I = 0; +// ENABLE = 1; +// # 10 +// $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); +// if (O !== 0) begin +// $error("latch failed"); +// $fatal(1); +// end +// end +endmodule diff --git a/emulator/com/mux.v b/emulator/com/mux.v new file mode 100644 index 0000000..3231256 --- /dev/null +++ b/emulator/com/mux.v @@ -0,0 +1,28 @@ +module MUX_1_16b( + output reg [15:0] value, + input [15:0] A0, A1, + input S); + + always @(*) begin + if (S) begin + value = A1; + end else begin + value = A0; + end + end +endmodule + +module MUX_2_16b( + output reg [15:0] value, + input [15:0] A0, A1, A2, A3, + input [1:0] S); + + always @(*) begin + case (S) + 2'b00: value = A0; + 2'b01: value = A1; + 2'b10: value = A2; + 2'b11: value = A3; + endcase + end +endmodule diff --git a/emulator/com/mux_test.v b/emulator/com/mux_test.v new file mode 100644 index 0000000..0dd72b4 --- /dev/null +++ b/emulator/com/mux_test.v @@ -0,0 +1,69 @@ +`include "emulator/com/mux.v" + +module mux_1_test; + reg[15:0] A0 = 16'b0110010101100101; + reg[15:0] A1 = 16'b1010110010101100; + reg S; + wire[15:0] out; + + MUX_1_16b dut(.value(out), .A0(A0), .A1(A1), .S(S)); + + initial begin + S = 0; + # 10 + $display("MUX_TEST: A0=%b A1=%b S=%b OUT=%b", A0, A1, S, out); + if (out !== A0) begin + $error("mux failed"); + $fatal(1); + end + S = 1; + # 10 + $display("MUX_TEST: A0=%b A1=%b S=%b OUT=%b", A0, A1, S, out); + if (out !== A1) begin + $error("mux failed"); + $fatal(1); + end + end +endmodule + +module mux_2_test; + reg[15:0] A0 = 16'b0110010101100101; + reg[15:0] A1 = 16'b1010110010101100; + reg[15:0] A2 = 16'b1010001001010101; + reg[15:0] A3 = 16'b0101010101010100; + reg[1:0] S; + wire[15:0] out; + + MUX_2_16b dut(.value(out), .A0(A0), .A1(A1), .A2(A2), .A3(A3), .S(S)); + + initial begin + S = 2'b00; + # 10 + $display("MUX_TEST: A0=%b A1=%b A1=%b A1=%b S=%b OUT=%b", A0, A1, S, out); + if (out !== A0) begin + $error("mux failed"); + $fatal(1); + end + S = 2'b01; + # 10 + $display("MUX_TEST: A0=%b A1=%b S=%b OUT=%b", A0, A1, S, out); + if (out !== A1) begin + $error("mux failed"); + $fatal(1); + end + S = 2'b10; + # 10 + $display("MUX_TEST: A0=%b A1=%b S=%b OUT=%b", A0, A1, S, out); + if (out !== A2) begin + $error("mux failed"); + $fatal(1); + end + S = 2'b11; + # 10 + $display("MUX_TEST: A0=%b A1=%b S=%b OUT=%b", A0, A1, S, out); + if (out !== A3) begin + $error("mux failed"); + $fatal(1); + end + end +endmodule diff --git a/emulator/module/mblock/rom.v b/emulator/com/rom.v similarity index 55% rename from emulator/module/mblock/rom.v rename to emulator/com/rom.v index 5fe74c4..d8a85af 100644 --- a/emulator/module/mblock/rom.v +++ b/emulator/com/rom.v @@ -1,17 +1,19 @@ module _ROM_32bit_16aline( output[31:0] out, input[15:0] address); - // 4 * 64KB ROM - parameter filename = "/dev/null"; - reg[31:0] buffer[0:65535]; + reg[31:0] buffer[0:1024]; initial begin $readmemb(filename, buffer); $display("ROM: %h", buffer[0]); end + assign out = buffer[address>>2]; - assign out = buffer[address]; + // assign out[7:0] = buffer[address+3]; + // assign out[15:8] = buffer[address+2]; + // assign out[23:16] = buffer[address+1]; + // assign out[31:24] = buffer[address+0]; endmodule @@ -20,7 +22,7 @@ module ROM_BOOT( input[15:0] address); // 4 * 64KB ROM - _ROM_32bit_16aline #(.filename("emulator/module/mblock/rom_boot.bin")) + _ROM_32bit_16aline #(.filename("emulator/com/rom_boot.bin")) dut(.out(out), .address(address)); endmodule diff --git a/emulator/module/mblock/rom_boot.bin b/emulator/com/rom_boot.bin similarity index 100% rename from emulator/module/mblock/rom_boot.bin rename to emulator/com/rom_boot.bin diff --git a/emulator/module/mblock/rom_test.bin b/emulator/com/rom_test.bin similarity index 100% rename from emulator/module/mblock/rom_test.bin rename to emulator/com/rom_test.bin diff --git a/emulator/module/mblock/rom_test.v b/emulator/com/rom_test.v similarity index 88% rename from emulator/module/mblock/rom_test.v rename to emulator/com/rom_test.v index 3629dab..13c9e27 100644 --- a/emulator/module/mblock/rom_test.v +++ b/emulator/com/rom_test.v @@ -1,10 +1,10 @@ -`include "emulator/module/mblock/rom.v" +`include "emulator/com/rom.v" module rom_test; reg[15:0] address; wire[31:0] out; - _ROM_32bit_16aline #(.filename("emulator/module/mblock/rom_test.bin")) + _ROM_32bit_16aline #(.filename("emulator/com/rom_test.bin")) dut(.out(out), .address(address)); @@ -16,21 +16,21 @@ module rom_test; $error("rom failed"); $fatal(1); end - address = 1; + address = 1*4; # 10 $display("ROM_TEST: address=%b out=%b", address, out); if (out !== 32'b11111100101011001101000010101001) begin $error("rom failed"); $fatal(1); end - address = 3; + address = 3*4; # 10 $display("ROM_TEST: address=%b out=%b", address, out); if (out !== 32'b11111010111111110100000111111110) begin $error("rom failed"); $fatal(1); end - address = 7; + address = 7*4; # 10 $display("ROM_TEST: address=%b out=%b", address, out); if (out !== 32'b10011111011110101000001000101001) begin diff --git a/emulator/com/stage0.v b/emulator/com/stage0.v new file mode 100644 index 0000000..986c0fd --- /dev/null +++ b/emulator/com/stage0.v @@ -0,0 +1,26 @@ +`include "emulator/com/mux.v" + +module STAGE0( + output[31:0] instruction_binary, + output[15:0] ram_address, + output[15:0] brom_address, + input [31:0] ram_value, + input [31:0] brom_value, + input [15:0] pc, + input execute_from_ram); + + assign ram_address = pc; + assign brom_address = pc; + + MUX_1_16b insh( + .value(instruction_binary[31:16]), + .A0(brom_value[31:16]), + .A1(ram_value[31:16]), + .S(execute_from_ram)); + MUX_1_16b insl( + .value(instruction_binary[15:0]), + .A0(brom_value[15:0]), + .A1(ram_value[15:0]), + .S(execute_from_ram)); + +endmodule diff --git a/emulator/com/stage0_test.v b/emulator/com/stage0_test.v new file mode 100644 index 0000000..24b7bff --- /dev/null +++ b/emulator/com/stage0_test.v @@ -0,0 +1,64 @@ +`include "emulator/com/stage0.v" +`include "emulator/seq/ram.v" +`include "emulator/com/rom.v" + +module stage0_test; + wire[15:0] rom_address; + wire[31:0] rom_value; + ROM_BOOT dut1(.out(rom_value), .address(rom_address)); + + reg clk; + reg ram_is_write; + wire[15:0] ram_address; + reg[31:0] ram_in; + wire[31:0] ram_value; + RAM_32bit_16aline dut2( + .out(ram_value), + .in(ram_in), + .address(ram_address), + .is_write(ram_is_write), + .clk(clk)); + + wire[31:0] instruction_binary; + reg[15:0] pc; + reg execute_from_ram; + + STAGE0 dut( + .instruction_binary(instruction_binary), + .ram_address(ram_address), + .brom_address(rom_address), + .ram_value(ram_value), + .brom_value(rom_value), + .pc(pc), + .execute_from_ram(execute_from_ram)); + + localparam [31:0] INPUT1 = 32'b11100101111110000100101010110001; + + initial begin + pc = 16'b0000000000000100; + ram_is_write = 1; + ram_in = INPUT1; + clk = 1; + # 10 + clk = 0; + # 10 + execute_from_ram = 0; + # 10 + $display("STAGE0_TEST: pc=%b out=%b", pc, instruction_binary); + if (instruction_binary !== 32'b11111100101011001101000010101001) begin + $error("stage0 failed"); + $fatal(1); + end + # 10 + execute_from_ram = 1; + # 10 + $display("STAGE0_TEST: pc=%b out=%b", pc, instruction_binary); + if (instruction_binary !== INPUT1) begin + $error("stage0 failed"); + $fatal(1); + end + + end + + +endmodule diff --git a/emulator/com/stage1.v b/emulator/com/stage1.v new file mode 100644 index 0000000..229cdb1 --- /dev/null +++ b/emulator/com/stage1.v @@ -0,0 +1,36 @@ +`include "emulator/com/mux.v" + +module STAGE1( + output[31:0] vr_value, + output[7:0] input_devices_address, + output[15:0] ram_address, + input[1:0] mblock_s1, + input[7:0] vr_source, + input[31:0] input_devices_value, + input[31:0] ram_value); + + wire[31:0] _const_value; + + assign input_devices_address = vr_source; + assign _const_value[7:0] = vr_source; + assign _const_value[31:8] = 24'b000000000000000000000000; + assign ram_address[7:0] = vr_source; + assign ram_address[15:8] = 8'b00000000; + + MUX_2_16b m1( + .value(vr_value[31:16]), + .A0(ram_value[31:16]), + .A1(16'bxxxxxxxxxxxxxxxx), + .A2(input_devices_value[31:16]), + .A3(_const_value[31:16]), + .S(mblock_s1)); + + MUX_2_16b m2( + .value(vr_value[15:0]), + .A0(ram_value[15:0]), + .A1(16'bxxxxxxxxxxxxxxxx), + .A2(input_devices_value[15:0]), + .A3(_const_value[15:0]), + .S(mblock_s1)); + +endmodule diff --git a/emulator/com/stage1_test.v b/emulator/com/stage1_test.v new file mode 100644 index 0000000..7543a65 --- /dev/null +++ b/emulator/com/stage1_test.v @@ -0,0 +1,54 @@ +`include "emulator/com/stage1.v" + +module stage1_test; + wire[31:0] vr_value; + wire[7:0] input_devices_address; + wire[15:0] ram_address; + + reg[1:0] mblock_s1; + reg[7:0] vr_source; + reg[31:0] input_devices_value; + reg[31:0] ram_value; + + STAGE1 dut( + .vr_value(vr_value), + .input_devices_address(input_devices_address), + .ram_address(ram_address), + .mblock_s1(mblock_s1), + .vr_source(vr_source), + .input_devices_value(input_devices_value), + .ram_value(ram_value)); + + initial begin + ram_value = 55; + input_devices_value = 22; + vr_source = 33; + # 10 + mblock_s1 = 0; + # 10 + $display("STAGE1_TEST: vr_value=%b ram_address=%b", vr_value, ram_address); + if (vr_value !== 55 || ram_address !== 33) begin + $error("stage1 failed"); + $fatal(1); + end + # 10 + mblock_s1 = 2; + # 10 + $display("STAGE1_TEST: vr_value=%b input_devices_address=%b", vr_value, input_devices_address); + if (vr_value !== 22 || input_devices_address !== 33) begin + $error("stage1 failed"); + $fatal(1); + end + # 10 + mblock_s1 = 3; + # 10 + $display("STAGE1_TEST: vr_value=%b const=%b", vr_value, vr_source); + if (vr_value !== 33) begin + $error("stage1 failed"); + $fatal(1); + end + + end + + +endmodule diff --git a/emulator/lib/adder.v b/emulator/lib/adder.v deleted file mode 100644 index f1502ba..0000000 --- a/emulator/lib/adder.v +++ /dev/null @@ -1,7 +0,0 @@ -module ADDER( - output[15:0] out, - input[15:0] in0, - input[15:0] in1); - - assign out = in0+in1; -endmodule diff --git a/emulator/lib/adder_test.v b/emulator/lib/adder_test.v deleted file mode 100644 index 269d87c..0000000 --- a/emulator/lib/adder_test.v +++ /dev/null @@ -1,22 +0,0 @@ -`include "emulator/lib/adder.v" - -module adder_test; - reg[15:0] in0, in1; - wire[15:0] out; - - ADDER dut( - .out(out), - .in0(in0), - .in1(in1)); - - initial begin - in0 = 2536; - in1 = 113; - # 10 - $display("ADDER_TEST: in0=%b in1=%b", in0, in1); - if (out !== 2649) begin - $error("latch failed"); - $fatal(1); - end - end -endmodule diff --git a/emulator/lib/alu.v b/emulator/lib/alu.v deleted file mode 100644 index 782ceb8..0000000 --- a/emulator/lib/alu.v +++ /dev/null @@ -1,25 +0,0 @@ -module ALU ( - output[31:0] out, - output is_zero, - input[2:0] op, - input[31:0] in0, - input[31:0] in1); - - reg[31:0] mem; - - always @(op, in0, in1) begin - case(op) - 3'b000: mem <= in0+in1; - 3'b001: mem <= in0-in1; - 3'b010: mem <= (in0<>in1); - 3'b100: mem <= (in0); - 3'b101: mem <= (in0&in1); - 3'b110: mem <= (in0|in1); - - endcase - end - assign out[31:0] = mem[31:0]; - assign is_zero = (mem == 0); - -endmodule diff --git a/emulator/lib/alu_test.v b/emulator/lib/alu_test.v deleted file mode 100644 index 7e34a65..0000000 --- a/emulator/lib/alu_test.v +++ /dev/null @@ -1,106 +0,0 @@ -`include "emulator/lib/alu.v" - -module alu_test; - reg[31:0] in0, in1; - reg[2:0] op; - wire[31:0] out; - wire is_zero; - - ALU dut( - .out(out), - .is_zero(is_zero), - .op(op), - .in0(in0), - .in1(in1)); - - initial begin - // ADD - op = 3'b000; - in0 = 2536; - in1 = 113; - # 10 - $display("ALU_TEST: op=%b in0=%b in1=%b", op, in0, in1); - if (out !== 2649 || is_zero !== 0) begin - $error("alu failed"); - $fatal(1); - end - - // SUB - op = 3'b001; - in0 = 2536; - in1 = 113; - # 10 - $display("ALU_TEST: op=%b in0=%b in1=%b", op, in0, in1); - if (out !== 2423 || is_zero !== 0) begin - $error("alu failed"); - $fatal(1); - end - - // LSR - op = 3'b010; - in0 = 2536; - in1 = 2; - # 10 - $display("ALU_TEST: op=%b in0=%b in1=%b", op, in0, in1); - if (out !== 10144 || is_zero !== 0) begin - $error("alu failed"); - $fatal(1); - end - - // RSR - op = 3'b011; - in0 = 2536; - in1 = 4; - # 10 - $display("ALU_TEST: op=%b in0=%b in1=%b", op, in0, in1); - if (out !== 158 || is_zero !== 0) begin - $error("alu failed"); - $fatal(1); - end - - // Fist Operand - op = 3'b100; - in0 = 2536; - in1 = 4; - # 10 - $display("ALU_TEST: op=%b in0=%b in1=%b", op, in0, in1); - if (out !== 2536 || is_zero !== 0) begin - $error("alu failed"); - $fatal(1); - end - - // CMP as alias of SUB - op = 3'b001; - in0 = 2536; - in1 = 2536; - # 10 - $display("ALU_TEST: op=%b in0=%b in1=%b", op, in0, in1); - if (out !== 0 || is_zero !== 1) begin - $error("alu failed"); - $fatal(1); - end - - // AND - op = 3'b101; - in0 = 2536; - in1 = 113; - # 10 - $display("ALU_TEST: op=%b in0=%b in1=%b", op, in0, in1); - if (out !== 96 || is_zero !== 0) begin - $error("alu failed"); - $fatal(1); - end - - // OR - op = 3'b110; - in0 = 2536; - in1 = 3113; - # 10 - $display("ALU_TEST: op=%b in0=%b in1=%b", op, in0, in1); - if (out !== 3561 || is_zero !== 0) begin - $error("alu failed"); - $fatal(1); - end - - end -endmodule diff --git a/emulator/lib/decoder.v b/emulator/lib/decoder.v deleted file mode 100644 index b01db42..0000000 --- a/emulator/lib/decoder.v +++ /dev/null @@ -1,22 +0,0 @@ -module DECODER_4_2( - output[3:0] out, - input[1:0] in); - - assign out[0] = (~in[1] & ~in[0]); - assign out[1] = (~in[1] & in[0]); - assign out[2] = ( in[1] & ~in[0]); - assign out[3] = ( in[1] & in[0]); -endmodule - - -module DECODER_8_3( - output[7:0] out, - input[2:0] in); - - wire [3:0] _out; - DECODER_4_2 d(_out[3:0], in[1:0]); - - wire not_in2 = ~in[2]; - assign out[3:0] = _out[3:0] & {not_in2, not_in2, not_in2, not_in2}; - assign out[7:4] = _out[3:0] & {in[2], in[2], in[2], in[2]}; -endmodule diff --git a/emulator/lib/decoder_test.v b/emulator/lib/decoder_test.v deleted file mode 100644 index eca58cb..0000000 --- a/emulator/lib/decoder_test.v +++ /dev/null @@ -1,61 +0,0 @@ -`include "emulator/lib/decoder.v" - -module decoder_4_2_test; - reg [1:0] in; - wire [3:0] out; - - DECODER_4_2 dut(.out(out), .in(in)); - - initial begin - in = 2'b00; - # 10 - $display("DECODER_TEST: in=%b out=%b", in, out); - if (out != 4'b0001) begin - $error("decoder failed"); - end - in = 2'b01; - # 10 - $display("DECODER_TEST: in=%b out=%b", in, out); - if (out != 4'b0010) begin - $error("decoder failed"); - end - in = 2'b10; - # 10 - $display("DECODER_TEST: in=%b out=%b", in, out); - if (out != 4'b0100) begin - $error("decoder failed"); - end - in = 2'b11; - # 10 - $display("DECODER_TEST: in=%b out=%b", in, out); - if (out != 4'b1000) begin - $error("decoder failed"); - end - - end -endmodule - - -module decoder_8_3_test; - reg [2:0] in; - wire [7:0] out; - - DECODER_8_3 dut(.out(out), .in(in)); - - initial begin - in = 3'b010; - # 10 - $display("DECODER_TEST: in=%b out=%b", in, out); - if (out != 8'b00000100) begin - $error("decoder failed"); - $fatal(1); - end - in = 3'b101; - # 10 - $display("DECODER_TEST: in=%b out=%b", in, out); - if (out != 8'b00100000) begin - $error("decoder failed"); - $fatal(1); - end - end -endmodule diff --git a/emulator/lib/flipflop.v b/emulator/lib/flipflop.v deleted file mode 100644 index e311b20..0000000 --- a/emulator/lib/flipflop.v +++ /dev/null @@ -1,30 +0,0 @@ -module __flipflop #(parameter BITS = 32)( - output[BITS-1:0] out, - input clk, - input[BITS-1:0] in); - - reg[BITS-1:0] mem; - always @(posedge clk) begin - mem[BITS-1:0] <= in[BITS-1:0]; - end - assign out[BITS-1:0] = mem[BITS-1:0]; -endmodule - -module flipflop32( - output[31:0] out, - input clk, - input[31:0] in); - - __flipflop #(.BITS(32)) ff(.out(out), .clk(clk), .in(in)); - -endmodule - -module flipflop16( - output[15:0] out, - input clk, - input[15:0] in); - - __flipflop #(.BITS(16)) ff(.out(out), .clk(clk), .in(in)); - -endmodule - diff --git a/emulator/lib/flipflop_test.v b/emulator/lib/flipflop_test.v deleted file mode 100644 index 9c93434..0000000 --- a/emulator/lib/flipflop_test.v +++ /dev/null @@ -1,58 +0,0 @@ -`include "emulator/lib/flipflop.v" - -module flipflop_test; - reg[31:0] in; - reg clk; - wire[31:0] out; - - flipflop32 dut(.out(out), .in(in), .clk(clk)); - - initial begin - clk = 0; - in = 32'b00110110110101010100101101101000; - # 10 - clk = 1; - # 10 - $display("FLIPFLOP: in=%b out=%b clk=%b", in, out, clk); - if (out !== 32'b00110110110101010100101101101000) begin - $error("flipflop failed"); - $fatal(1); - end - - clk = 0; - # 10 - in = 32'b01100011111101011011010100000100; - # 10 - $display("FLIPFLOP: in=%b out=%b clk=%b", in, out, clk); - if (out !== 32'b00110110110101010100101101101000) begin - $error("flipflop failed"); - $fatal(1); - end - - in = 32'b10101100011011010010001010011001; - # 10 - $display("FLIPFLOP: in=%b out=%b clk=%b", in, out, clk); - if (out !== 32'b00110110110101010100101101101000) begin - $error("flipflop failed"); - $fatal(1); - end - - clk = 1; - # 10 - $display("FLIPFLOP: in=%b out=%b clk=%b", in, out, clk); - if (out !== 32'b10101100011011010010001010011001) begin - $error("flipflop failed"); - $fatal(1); - end - - clk = 0; - # 10 - in = 32'b10101011001010001101001000011011; - # 10 - $display("FLIPFLOP: in=%b out=%b clk=%b", in, out, clk); - if (out !== 32'b10101100011011010010001010011001) begin - $error("flipflop failed"); - $fatal(1); - end - end -endmodule diff --git a/emulator/lib/latch.v b/emulator/lib/latch.v deleted file mode 100644 index 0479815..0000000 --- a/emulator/lib/latch.v +++ /dev/null @@ -1,13 +0,0 @@ -module latch_d(output out, input in, input enable); - // we want latch to always be on and returing - // while write when d is active. - - reg mem; - - always @(in, enable) begin - if (enable) begin - mem <= in; - end - end - assign out = mem; -endmodule diff --git a/emulator/lib/latch_test.v b/emulator/lib/latch_test.v deleted file mode 100644 index c9fb2e1..0000000 --- a/emulator/lib/latch_test.v +++ /dev/null @@ -1,73 +0,0 @@ -`include "emulator/lib/latch.v" - -module latch_d_test; - reg I, ENABLE; - wire O; - - latch_d dut(.out(O), .in(I), .enable(ENABLE)); - - initial begin - I = 0; - ENABLE = 1; - # 10 - $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); - if (O !== 0) begin - $error("latch failed"); - $fatal(1); - end - - I = 1; - ENABLE = 1; - # 10 - $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); - if (O !== 1) begin - $error("latch failed"); - $fatal(1); - end - - I = 1; - ENABLE = 0; - # 10 - $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); - if (O !== 1) begin - $error("latch failed"); - $fatal(1); - end - - I = 0; - ENABLE = 0; - # 10 - $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); - if (O !== 1) begin - $error("latch failed"); - $fatal(1); - end - - I = 1; - ENABLE = 0; - # 10 - $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); - if (O !== 1) begin - $error("latch failed"); - $fatal(1); - end - - I = 0; - ENABLE = 0; - # 10 - $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); - if (O !== 1) begin - $error("latch failed"); - $fatal(1); - end - - I = 0; - ENABLE = 1; - # 10 - $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); - if (O !== 0) begin - $error("latch failed"); - $fatal(1); - end - end -endmodule diff --git a/emulator/lib/mux.v b/emulator/lib/mux.v deleted file mode 100644 index acf17b4..0000000 --- a/emulator/lib/mux.v +++ /dev/null @@ -1,55 +0,0 @@ -// MUX 8-bit IO with 1-bit selection -// B is returned when S is active. -module MUX_8_1( - output [7:0] value, - input[7:0] A,B, - input S); - - wire Snot; - not (Snot, S); - - wire [7:0] x; - wire [7:0] y; - and (x[0], A[0], Snot); - and (x[1], A[1], Snot); - and (x[2], A[2], Snot); - and (x[3], A[3], Snot); - and (x[4], A[4], Snot); - and (x[5], A[5], Snot); - and (x[6], A[6], Snot); - and (x[7], A[7], Snot); - - - and (y[0], B[0], S); - and (y[1], B[1], S); - and (y[2], B[2], S); - and (y[3], B[3], S); - and (y[4], B[4], S); - and (y[5], B[5], S); - and (y[6], B[6], S); - and (y[7], B[7], S); - - or (value[0], x[0], y[0]); - or (value[1], x[1], y[1]); - or (value[2], x[2], y[2]); - or (value[3], x[3], y[3]); - or (value[4], x[4], y[4]); - or (value[5], x[5], y[5]); - or (value[6], x[6], y[6]); - or (value[7], x[7], y[7]); - -endmodule - -module MUX_8_2( - output[7:0] value, - input[7:0] A,B,C,D, - input[1:0] S); - - wire[7:0] val_a, val_b; - - MUX_8_1 m1(.value(val_a), .A(A), .B(B), .S(S[0])); - MUX_8_1 m2(.value(val_b), .A(C), .B(D), .S(S[0])); - MUX_8_1 m3(.value(value), .A(val_a), .B(val_b), .S(S[1])); - -endmodule - diff --git a/emulator/lib/mux_test.v b/emulator/lib/mux_test.v deleted file mode 100644 index afa5c09..0000000 --- a/emulator/lib/mux_test.v +++ /dev/null @@ -1,70 +0,0 @@ -`include "emulator/lib/mux.v" - -module mux_8_1_test; - reg[7:0] A = 8'b01100101; - reg[7:0] B = 8'b10101100; - reg S; - wire[7:0] out; - - MUX_8_1 dut(.value(out), .A(A), .B(B), .S(S)); - - initial begin - S = 0; - # 10 - $display("MUX_TEST: A=%b B=%b S=%b OUT=%b", A, B, S, out); - if (out !== A) begin - $error("mux failed"); - $fatal(1); - end - S = 1; - # 10 - $display("MUX_TEST: A=%b B=%b S=%b OUT=%b", A, B, S, out); - if (out !== B) begin - $error("mux failed"); - $fatal(1); - end - end -endmodule - - -module mux_8_2_test; - reg[7:0] A = 8'b11101110; - reg[7:0] B = 8'b11100110; - reg[7:0] C = 8'b11100100; - reg[7:0] D = 8'b00110111; - reg[1:0] S; - wire[7:0] out; - - MUX_8_2 dut(.value(out), .A(A), .B(B), .C(C), .D(D), .S(S)); - - initial begin - S = 0; - # 10 - $display("MUX_TEST: A=%b B=%b S=%b OUT=%b", A, B, S, out); - if (out !== A) begin - $error("mux failed"); - $fatal(1); - end - S = 1; - # 10 - $display("MUX_TEST: A=%b B=%b S=%b OUT=%b", A, B, S, out); - if (out !== B) begin - $error("mux failed"); - $fatal(1); - end - S = 2; - # 10 - $display("MUX_TEST: A=%b B=%b S=%b OUT=%b", A, B, S, out); - if (out !== C) begin - $error("mux failed"); - $fatal(1); - end - S = 3; - # 10 - $display("MUX_TEST: A=%b B=%b S=%b OUT=%b", A, B, S, out); - if (out !== D) begin - $error("mux failed"); - $fatal(1); - end - end -endmodule diff --git a/emulator/module/boot_control.v b/emulator/module/boot_control.v index 7b376ec..7e18a8c 100644 --- a/emulator/module/boot_control.v +++ b/emulator/module/boot_control.v @@ -1,12 +1,17 @@ -module BOOT_CONTROL(output is_powered_on); - // As we don't have a button to control boot. - // We say boot will automatically get pressed after - // 100 time units. - reg _is_powered_on; - initial begin - assign _is_powered_on = 0; - # 100 - assign _is_powered_on = 1; +`define BOOTSEQUENCE_ORG 'h44 + +module BOOT_CONTROL( + output reg is_powered_on, + output reg [15:0] pc_next, + output reg [1:0] flags, + input reset, + input clk); + + always @(negedge clk) begin + if(reset) begin + flags <= 2'b00; + pc_next <= 'h44;// BOOTSEQUENCE_ORG; + is_powered_on <= 1; + end end - assign is_powered_on = _is_powered_on; endmodule \ No newline at end of file diff --git a/emulator/module/boot_control_test.v b/emulator/module/boot_control_test.v index a9872b9..874771d 100644 --- a/emulator/module/boot_control_test.v +++ b/emulator/module/boot_control_test.v @@ -1,28 +1,35 @@ `include "emulator/module/boot_control.v" module boot_control_test; - wire is_powered_on; - BOOT_CONTROL dut(.is_powered_on(is_powered_on)); + // reg reset; - initial begin - # 5 - $display("BOOT_CONTROL: is_powered_on=%b", is_powered_on); - if (is_powered_on !== 0) begin - $error("BOOT_CONTROL failed"); - $fatal(1); - end - # 80 - $display("BOOT_CONTROL: is_powered_on=%b", is_powered_on); - if (is_powered_on !== 0) begin - $error("BOOT_CONTROL failed"); - $fatal(1); - end - # 20 - $display("BOOT_CONTROL: is_powered_on=%b", is_powered_on); - if (is_powered_on !== 1) begin - $error("BOOT_CONTROL failed"); - $fatal(1); - end - end + // reg is_powered_on; + // reg[15:0] pc_next; + // reg[1:0] flags; + // reg clk; + + // BOOT_CONTROL dut( + // .is_powered_on(is_powered_on), + // .pc_next(pc_next), + // .flags(flags), + // .reset(reset), + // .clk(clk)); + + // initial begin + // # 5 + // clk = 1; + // # 1 + // reset = 1; + // # 1 + // clk = 0; + // # 1 + // reset = 0; + // $display("BOOT_CONTROL: is_powered_on=%b, pc_next=%b, flags: %b", + // is_powered_on, pc_next, flags); + // if (is_powered_on !== 0 || pc_next !== 'h80 || flags !== 0) begin + // $error("BOOT_CONTROL failed"); + // $fatal(1); + // end + // end endmodule diff --git a/emulator/module/clock.v b/emulator/module/clock.v index 26bb7a5..1a877a9 100644 --- a/emulator/module/clock.v +++ b/emulator/module/clock.v @@ -1,54 +1,58 @@ module CLOCK( - output[0:3] clk, - output[0:3] is_stage); + output[0:3] clk); // stages: // The architecture splits instructions execution in 4 stages. // stage0: fetch and expand instruction at program_counter. - // stage1: fetch value0 (usually operand0) from desidered source. - // stage2: fetch value1 (usually operand1) from desidered source. - // stage3: write value2 (result) to desidered source and update - // program_counter if and when desired. + // stage1: fetch vr_value from desidered source. + // stage2: fetch vrw_value from desidered source. + // stage3: write vw_value (result) to desidered source or pc. // hw_clk (internal): - // clock signal + // clock signal which controls clk[0:3] // clk[0],clk[1],clk[2],clk[3]: - // clk splitted into 4. Each clk{i} posedge represents flipflop write - // of stage{i}. - // e.g. stage1 is active b/w clk0 and clk1 posedge. + // clk splitted into 4 + // The order of edges and active state. + // - clk[0] up + // - clk[0] down + // - clk[1] up + // - clk[1] down + // - clk[2] up + // - clk[2] down + // - clk[3] up + // - clk[3] down + reg hw_clk; + reg[0:3] _clk; + integer _count; - // TODO: make clock more realistic. - reg[0:3] hw_clk; - reg[0:3] _is_stage; initial begin - forever begin - #10 - _is_stage[0]=0; - hw_clk[0]=1; - _is_stage[1]=1; - #10 - hw_clk[0]=0; - #10 - _is_stage[1]=0; - hw_clk[1]=1; - _is_stage[2]=1; - #10 - hw_clk[1]=0; - #10 - _is_stage[2]=0; - hw_clk[2]=1; - _is_stage[3]=1; - #10 - hw_clk[2]=0; - #10 - _is_stage[3]=0; - hw_clk[3]=1; - _is_stage[0]=1; - #10 - hw_clk[3]=0; + hw_clk = 0; + _count = 0; + forever begin + #10 hw_clk = ~hw_clk; + end + end + + always @(posedge hw_clk) begin + _count <= _count + 1; + if (_count == 0) begin + assign _clk[0] = 1; + end + if (_count == 1) begin + assign _clk[1] = 1; + end + if (_count == 2) begin + assign _clk[2] = 1; end + if (_count == 3) begin + assign _clk[3] = 1; + _count <= 0; + end + end + + always @(negedge hw_clk) begin + assign _clk[0:3] = 4'b0000; end - assign clk[0:3] = hw_clk[0:3]; - assign is_stage[0:3] = _is_stage[0:3]; + assign clk[0:3] = _clk[0:3]; endmodule diff --git a/emulator/module/clock_test.v b/emulator/module/clock_test.v index 6b54f31..e42d06e 100644 --- a/emulator/module/clock_test.v +++ b/emulator/module/clock_test.v @@ -2,39 +2,31 @@ module clock_test; wire[0:3] clk; - wire[0:3] is_stage; - CLOCK dut( - .clk(clk[0:3]), - .is_stage(is_stage[0:3])); + CLOCK dut(.clk(clk[0:3])); initial begin - # 75 - $display("CLK: clk=%b is_stage=%b", clk, is_stage); - if (clk !== 4'b0001 || is_stage !== 4'b1000) begin + # 80 + # 15 + $display("CLK: clk=%b", clk); + if (clk !== 4'b1000) begin $error("clock failed"); $fatal(1); end # 20 - $display("CLK: clk=%b is_stage=%b", clk, is_stage); - if (clk !== 4'b1000 || is_stage !== 4'b0100) begin + $display("CLK: clk=%b", clk); + if (clk !== 4'b0100) begin $error("clock failed"); $fatal(1); end # 20 - $display("CLK: clk=%b is_stage=%b", clk, is_stage); - if (clk !== 4'b0100 || is_stage !== 4'b0010) begin + $display("CLK: clk=%b", clk); + if (clk !== 4'b0010) begin $error("clock failed"); $fatal(1); end # 20 - $display("CLK: clk=%b is_stage=%b", clk, is_stage); - if (clk !== 4'b0010 || is_stage !== 4'b0001) begin - $error("clock failed"); - $fatal(1); - end - # 20 - $display("CLK: clk=%b is_stage=%b", clk, is_stage); - if (clk !== 4'b0001 || is_stage !== 4'b1000) begin + $display("CLK: clk=%b", clk); + if (clk !== 4'b0001) begin $error("clock failed"); $fatal(1); end diff --git a/emulator/module/mblock/mblock.v b/emulator/module/mblock/mblock.v index d94ec13..75c8c89 100644 --- a/emulator/module/mblock/mblock.v +++ b/emulator/module/mblock/mblock.v @@ -1,35 +1,35 @@ -`include "emulator/module/mblock/mconst.v" -`include "emulator/module/mblock/ram.v" -`include "emulator/module/mblock/rom.v" -`include "emulator/lib//mux.v" +// `include "emulator/module/mblock/mconst.v" +// `include "emulator/module/mblock/ram.v" +// `include "emulator/module/mblock/rom.v" +// `include "emulator/lib//mux.v" -module MBLOCK(output[31:0] out, - input[1:0] selector, - input[31:0] in, - input[15:0] address, - input is_write); +// module MBLOCK(output[31:0] out, +// input[1:0] selector, +// input[31:0] in, +// input[15:0] address, +// input is_write); - // TODO: How can be careful about accidental write occurance - // due to race between how the values are propogated? +// // TODO: How can be careful about accidental write occurance +// // due to race between how the values are propogated? - wire[31:0] out0, out1, out2, out3; +// wire[31:0] out0, out1, out2, out3; - ROM_BOOT romb(.out(out0), - .address(address)); +// ROM_BOOT romb(.out(out0), +// .address(address)); - RAM_32bit_16aline ram(.out(out1), - .in(in), - .address(address), - .is_write(is_write & ~selector[1] & selector[0])); +// RAM_32bit_16aline ram(.out(out1), +// .in(in), +// .address(address), +// .is_write(is_write & ~selector[1] & selector[0])); - // selector 10 is reserved for IO +// // selector 10 is reserved for IO - MCONST mconst(.out(out3), - .in(address)); +// MCONST mconst(.out(out3), +// .in(address)); - MUX_8_2 m0(.value(out[ 7: 0]), .A(out0[ 7: 0]), .B(out1[ 7: 0]), .D(out3[ 7: 0]), .S(selector[1:0])); - MUX_8_2 m1(.value(out[15: 8]), .A(out0[15: 8]), .B(out1[15: 8]), .D(out3[15: 8]), .S(selector[1:0])); - MUX_8_2 m2(.value(out[23:16]), .A(out0[23:16]), .B(out1[23:16]), .D(out3[23:16]), .S(selector[1:0])); - MUX_8_2 m3(.value(out[31:24]), .A(out0[31:24]), .B(out1[31:24]), .D(out3[31:24]), .S(selector[1:0])); +// MUX_8_2 m0(.value(out[ 7: 0]), .A(out0[ 7: 0]), .B(out1[ 7: 0]), .D(out3[ 7: 0]), .S(selector[1:0])); +// MUX_8_2 m1(.value(out[15: 8]), .A(out0[15: 8]), .B(out1[15: 8]), .D(out3[15: 8]), .S(selector[1:0])); +// MUX_8_2 m2(.value(out[23:16]), .A(out0[23:16]), .B(out1[23:16]), .D(out3[23:16]), .S(selector[1:0])); +// MUX_8_2 m3(.value(out[31:24]), .A(out0[31:24]), .B(out1[31:24]), .D(out3[31:24]), .S(selector[1:0])); -endmodule +// endmodule diff --git a/emulator/module/mblock/mblock_test.v b/emulator/module/mblock/mblock_test.v index 0b81c30..70cc975 100644 --- a/emulator/module/mblock/mblock_test.v +++ b/emulator/module/mblock/mblock_test.v @@ -1,68 +1,68 @@ `include "emulator/module/mblock/mblock.v" module BLOCK_32bit_16aline_test; - wire[31:0] out; - reg[15:0] address; - reg[1:0] selector; - reg[31:0] in; - reg is_write; + // wire[31:0] out; + // reg[15:0] address; + // reg[1:0] selector; + // reg[31:0] in; + // reg is_write; - localparam [31:0] INPUT16z = 16'bzzzzzzzzzzzzzzzz; - localparam [31:0] INPUT32z = 32'bzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz; - localparam [31:0] INPUT1 = 32'b11100101111110000100101010110001; - localparam [31:0] INPUT2 = 32'b01011100100011000110101000000001; + // localparam [31:0] INPUT16z = 16'bzzzzzzzzzzzzzzzz; + // localparam [31:0] INPUT32z = 32'bzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz; + // localparam [31:0] INPUT1 = 32'b11100101111110000100101010110001; + // localparam [31:0] INPUT2 = 32'b01011100100011000110101000000001; - MBLOCK dut(.out(out), - .selector(selector), - .in(in), - .address(address), - .is_write(is_write)); + // MBLOCK dut(.out(out), + // .selector(selector), + // .in(in), + // .address(address), + // .is_write(is_write)); - initial begin - selector = 2'b01; // RAM write - address = 16'b1011100000111010; - in = INPUT1; - # 10 - is_write = 1; - # 10 - $display("MBLOCK: RAM_TEST: address=%b is_write=%b in=%b out=%b", address, is_write, in, out); - if (out !== INPUT1) begin - $error("mblock failed"); - $fatal(1); - end + // initial begin + // selector = 2'b01; // RAM write + // address = 16'b1011100000111010; + // in = INPUT1; + // # 10 + // is_write = 1; + // # 10 + // $display("MBLOCK: RAM_TEST: address=%b is_write=%b in=%b out=%b", address, is_write, in, out); + // if (out !== INPUT1) begin + // $error("mblock failed"); + // $fatal(1); + // end - selector = 2'b00; // ROM_BOOT - address = 16'b0000000000000001; - is_write = 1'bz; - in = INPUT32z; - # 10 - $display("MBLOCK: ROM_TEST: address=%b is_write=%b in=%b out=%b", address, is_write, in, out); - if (out !== 32'b11111100101011001101000010101001) begin - $error("mblock failed"); - $fatal(1); - end + // selector = 2'b00; // ROM_BOOT + // address = 16'b0000000000000001; + // is_write = 1'bz; + // in = INPUT32z; + // # 10 + // $display("MBLOCK: ROM_TEST: address=%b is_write=%b in=%b out=%b", address, is_write, in, out); + // if (out !== 32'b11111100101011001101000010101001) begin + // $error("mblock failed"); + // $fatal(1); + // end - selector = 2'b11; // MCONST - address = 16'b0001100100111101; - is_write = 1'bz; - in = INPUT32z; - # 10 - $display("MBLOCK: MCONST: address=%b is_write=%b in=%b out=%b", address, is_write, in, out); - if (out !== 32'b00000000000000000001100100111101) begin - $error("mblock failed"); - $fatal(1); - end + // selector = 2'b11; // MCONST + // address = 16'b0001100100111101; + // is_write = 1'bz; + // in = INPUT32z; + // # 10 + // $display("MBLOCK: MCONST: address=%b is_write=%b in=%b out=%b", address, is_write, in, out); + // if (out !== 32'b00000000000000000001100100111101) begin + // $error("mblock failed"); + // $fatal(1); + // end - selector = 2'b01; // RAM read - address = 16'b1011100000111010; - is_write = 0; - # 10 - in = INPUT32z; - # 10 - $display("MBLOCK: RAM_TEST: address=%b is_write=%b in=%b out=%b", address, is_write, in, out); - if (out !== INPUT1) begin - $error("mblock failed"); - $fatal(1); - end - end + // selector = 2'b01; // RAM read + // address = 16'b1011100000111010; + // is_write = 0; + // # 10 + // in = INPUT32z; + // # 10 + // $display("MBLOCK: RAM_TEST: address=%b is_write=%b in=%b out=%b", address, is_write, in, out); + // if (out !== INPUT1) begin + // $error("mblock failed"); + // $fatal(1); + // end + // end endmodule diff --git a/emulator/module/mblock/mconst.v b/emulator/module/mblock/mconst.v index f6e8242..d54664d 100644 --- a/emulator/module/mblock/mconst.v +++ b/emulator/module/mblock/mconst.v @@ -1,9 +1,9 @@ -module MCONST( - output[31:0] out, - input[15:0] in); - // returns constant value +// module MCONST( +// output[31:0] out, +// input[15:0] in); +// // returns constant value - assign out[31:16] = 16'b0000000000000000; - assign out[15:0] = in[15:0]; +// assign out[31:16] = 16'b0000000000000000; +// assign out[15:0] = in[15:0]; -endmodule +// endmodule diff --git a/emulator/module/mblock/mconst_test.v b/emulator/module/mblock/mconst_test.v index b3d6570..6aaf80e 100644 --- a/emulator/module/mblock/mconst_test.v +++ b/emulator/module/mblock/mconst_test.v @@ -1,26 +1,26 @@ -`include "emulator/module/mblock/mconst.v" +// `include "emulator/module/mblock/mconst.v" module MCONST_test; - reg[31:0] in; - wire[31:0] out; +// reg[31:0] in; +// wire[31:0] out; - MCONST dut(.out(out), - .in(in)); +// MCONST dut(.out(out), +// .in(in)); - initial begin - in = 16'b0010111100010010; - # 10 - $display("MCONST_TEST: in=%b out=%b", in, out); - if (out !== 32'b00000000000000000010111100010010) begin - $error("mconst failed"); - $fatal(1); - end - in = 16'b1001011000011000; - # 10 - $display("MCONST_TEST: in=%b out=%b", in, out); - if (out !== 32'b00000000000000001001011000011000) begin - $error("mconst failed"); - $fatal(1); - end - end +// initial begin +// in = 16'b0010111100010010; +// # 10 +// $display("MCONST_TEST: in=%b out=%b", in, out); +// if (out !== 32'b00000000000000000010111100010010) begin +// $error("mconst failed"); +// $fatal(1); +// end +// in = 16'b1001011000011000; +// # 10 +// $display("MCONST_TEST: in=%b out=%b", in, out); +// if (out !== 32'b00000000000000001001011000011000) begin +// $error("mconst failed"); +// $fatal(1); +// end +// end endmodule diff --git a/emulator/module/mblock/ram.v b/emulator/module/mblock/ram.v deleted file mode 100644 index 31be343..0000000 --- a/emulator/module/mblock/ram.v +++ /dev/null @@ -1,15 +0,0 @@ -module RAM_32bit_16aline(output[31:0] out, - input[31:0] in, - input[15:0] address, - input is_write); - // 4 * 64KB RAM - - reg[31:0] mem [65535:0]; - always @(address, in, is_write) begin - if (is_write) begin - mem[address] <= in; - end - end - assign out = mem[address]; - -endmodule diff --git a/emulator/module/mblock_mux.v b/emulator/module/mblock_mux.v index a0dec38..1154d18 100644 --- a/emulator/module/mblock_mux.v +++ b/emulator/module/mblock_mux.v @@ -1,56 +1,56 @@ -module MBLOCK_MUX(output[31:0] mblock_address, - output[1:0] mblock_selector, +// module MBLOCK_MUX(output[31:0] mblock_address, +// output[1:0] mblock_selector, - input execute_from_brom, - input[0:3] is_stage, - input[15:0] address0, // program_counter - input[15:0] address1, // v0_source - input[15:0] address2, // v1_source - input[15:0] address3, // v2_source - input[3:0] is_write, - ); +// input execute_from_brom, +// input[0:3] is_stage, +// input[15:0] address0, // program_counter +// input[15:0] address1, // v0_source +// input[15:0] address2, // v1_source +// input[15:0] address3, // v2_source +// input[3:0] is_write, +// ); - // TODO Starts - // TODO: We should support I/O and const in mblock_selector - // during stage0, before stage0 posedge - // mblock_selector[0] = execute_from_brom; - // mblock_selector[1] = 0; - // after stage0 posedge - // mblock_selector = will come from instruction_op - // after stage1 posedge - // mblock_selector = will come from instruction_op - // after stage2 posedge - // mblock_selector = will come from instruction_op - // Challenge: How will we will fit, 3 mux_selector, ALU_OP and - // instructions classes all within 1 byte... - // TODO Ends +// // TODO Starts +// // TODO: We should support I/O and const in mblock_selector +// // during stage0, before stage0 posedge +// // mblock_selector[0] = execute_from_brom; +// // mblock_selector[1] = 0; +// // after stage0 posedge +// // mblock_selector = will come from instruction_op +// // after stage1 posedge +// // mblock_selector = will come from instruction_op +// // after stage2 posedge +// // mblock_selector = will come from instruction_op +// // Challenge: How will we will fit, 3 mux_selector, ALU_OP and +// // instructions classes all within 1 byte... +// // TODO Ends - always @(is_stage, is_write, address0, address1, address2, address3) - begin - if (is_stage == 2'b00) - begin - // Active RAM or BROM based upon $execute_from_brom. - assign mblock_selector[1:0] = {0, execute_from_brom}; - end - else if (is_stage == 2'b01) - begin - // TODO: mblock_selector compute from instruction_op - end - else if (is_stage == 2'b10) - begin - // TODO: mblock_selector compute from instruction_op - end - else - begin - // TODO: mblock_selector compute from instruction_op - end - else +// always @(is_stage, is_write, address0, address1, address2, address3) +// begin +// if (is_stage == 2'b00) +// begin +// // Active RAM or BROM based upon $execute_from_brom. +// assign mblock_selector[1:0] = {0, execute_from_brom}; +// end +// else if (is_stage == 2'b01) +// begin +// // TODO: mblock_selector compute from instruction_op +// end +// else if (is_stage == 2'b10) +// begin +// // TODO: mblock_selector compute from instruction_op +// end +// else +// begin +// // TODO: mblock_selector compute from instruction_op +// end +// else - end +// end - MUX_8_2 m0(.value(mblock_address[ 7: 0]), .A(address0[ 7: 0]), .B(address1[ 7: 0]), ,C(address2[ 7: 0]), .D(address3[ 7: 0]), .S(mblock_selector[1:0])); - MUX_8_2 m1(.value(mblock_address[15: 8]), .A(address0[15: 8]), .B(address1[15: 8]), ,C(address2[15: 8]), .D(address3[15: 8]), .S(mblock_selector[1:0])); - MUX_8_2 m2(.value(mblock_address[23:16]), .A(address0[23:16]), .B(address1[23:16]), ,C(address2[23:16]), .D(address3[23:16]), .S(mblock_selector[1:0])); - MUX_8_2 m3(.value(mblock_address[31:24]), .A(address0[31:24]), .B(address1[31:24]), ,C(address2[31:24]), .D(address3[31:24]), .S(mblock_selector[1:0])); +// MUX_8_2 m0(.value(mblock_address[ 7: 0]), .A(address0[ 7: 0]), .B(address1[ 7: 0]), ,C(address2[ 7: 0]), .D(address3[ 7: 0]), .S(mblock_selector[1:0])); +// MUX_8_2 m1(.value(mblock_address[15: 8]), .A(address0[15: 8]), .B(address1[15: 8]), ,C(address2[15: 8]), .D(address3[15: 8]), .S(mblock_selector[1:0])); +// MUX_8_2 m2(.value(mblock_address[23:16]), .A(address0[23:16]), .B(address1[23:16]), ,C(address2[23:16]), .D(address3[23:16]), .S(mblock_selector[1:0])); +// MUX_8_2 m3(.value(mblock_address[31:24]), .A(address0[31:24]), .B(address1[31:24]), ,C(address2[31:24]), .D(address3[31:24]), .S(mblock_selector[1:0])); -endmodule +// endmodule diff --git a/emulator/module/stage0_ins_resolver.v b/emulator/module/stage0_ins_resolver.v deleted file mode 100644 index 083c61b..0000000 --- a/emulator/module/stage0_ins_resolver.v +++ /dev/null @@ -1,14 +0,0 @@ -module INS_RESOLVER(output[7:0] v0, v1, v2, op, - input[32:0] full_ins, - input clk); - - wire[31:0] mem_ins; - flipflop32 f(.out(mem_ins[31:0]), .in(full_ins[31:0]), .clk(clk)); - - assign v0[7:0] = full_ins[ 7: 0]; - assign v1[7:0] = full_ins[15: 8]; - // TODO: v2_source can be drived from v1 - assign v2[7:0] = full_ins[23:16]; - assign op[7:0] = full_ins[31:24]; - -endmodule diff --git a/emulator/seq/ram.v b/emulator/seq/ram.v new file mode 100644 index 0000000..8839124 --- /dev/null +++ b/emulator/seq/ram.v @@ -0,0 +1,18 @@ +module RAM_32bit_16aline( + output[31:0] out, + input[31:0] in, + input[15:0] address, + input is_write, + input clk); + // 64KB RAM + + reg[31:0] mem [65535:0]; + always @(negedge clk) begin + // Write are triggered at negedge + if (is_write) begin + mem[address] <= in; + end + end + assign out = mem[address]; + +endmodule diff --git a/emulator/module/mblock/ram_test.v b/emulator/seq/ram_test.v similarity index 88% rename from emulator/module/mblock/ram_test.v rename to emulator/seq/ram_test.v index d4cfb5b..f1648cb 100644 --- a/emulator/module/mblock/ram_test.v +++ b/emulator/seq/ram_test.v @@ -1,8 +1,9 @@ -`include "emulator/module/mblock/ram.v" +`include "emulator/seq/ram.v" module RAM_32bit_16aline_test; reg[15:0] address; reg is_write; + reg clk; reg[31:0] in; wire[31:0] out; @@ -12,12 +13,16 @@ module RAM_32bit_16aline_test; RAM_32bit_16aline dut(.out(out), .in(in), .address(address), - .is_write(is_write)); + .is_write(is_write), + .clk(clk)); initial begin address = 16'b1100001110111100; is_write = 1; in = INPUT1; + clk = 1; + # 10 + clk = 0; # 10 $display("RAM_TEST: address=%b is_write=%b in=%b out=%b", address, is_write, in, out); if (out !== INPUT1) begin @@ -30,6 +35,9 @@ module RAM_32bit_16aline_test; # 10 in = INPUT2; # 10 + clk = 1; + # 10 + clk = 0; $display("RAM_TEST: address=%b is_write=%b in=%b out=%b", address, is_write, in, out); if (out !== INPUT1) begin $error("ram failed"); @@ -41,6 +49,10 @@ module RAM_32bit_16aline_test; # 10 is_write = 1; # 10 + clk = 1; + # 10 + clk = 0; + # 10 $display("RAM_TEST: address=%b is_write=%b in=%b out=%b", address, is_write, in, out); if (out !== INPUT2) begin $error("ram failed"); @@ -48,7 +60,6 @@ module RAM_32bit_16aline_test; end is_write = 0; - # 10 address = 16'b1100001110111100; # 10 $display("RAM_TEST: address=%b is_write=%b in=%b out=%b", address, is_write, in, out); diff --git a/emulator/seq/register.v b/emulator/seq/register.v new file mode 100644 index 0000000..bb93efc --- /dev/null +++ b/emulator/seq/register.v @@ -0,0 +1,23 @@ +module REGISTER_up_16b( + output [15:0] out, + input [15:0] in, + input clk); + + reg [15:0] _data; + always @(posedge clk) begin + _data = in; + end + assign out = _data; +endmodule + +module REGISTER_down_16b( + output [15:0] out, + input [15:0] in, + input clk); + + reg [15:0] _data; + always @(negedge clk) begin + _data = in; + end + assign out = _data; +endmodule diff --git a/emulator/seq/register_test.v b/emulator/seq/register_test.v new file mode 100644 index 0000000..d0ca82f --- /dev/null +++ b/emulator/seq/register_test.v @@ -0,0 +1,63 @@ +`include "emulator/seq/register.v" + +module register_up_test; + reg[15:0] in = 16'b0110010101100101; + reg clk; + wire[15:0] out; + + REGISTER_up_16b dut(.out(out), .in(in), .clk(clk)); + + initial begin + clk = 0; + # 10 + clk = 1; + # 1 + clk = 0; + # 1 + in = 16'b1010110010101100; + # 1 + $display("REGISTER_UP_TEST: in=%b out=%b clk=%b", in, out, clk); + if (out !== 16'b0110010101100101) begin // old value + $error("register failed"); + $fatal(1); + end + clk = 1; + # 10 + $display("REGISTER_UP_TEST: in=%b out=%b clk=%b", in, out, clk); + if (out !== 16'b1010110010101100) begin + $error("register failed"); + $fatal(1); + end + end +endmodule + +module register_down_test; + reg[15:0] in = 16'b0110010101100101; + reg clk; + wire[15:0] out; + + REGISTER_down_16b dut(.out(out), .in(in), .clk(clk)); + + initial begin + clk = 1; + # 10 + clk = 0; + # 1 + clk = 1; + # 1 + in = 16'b1010110010101100; + # 1 + $display("REGISTER_DOWN_TEST: in=%b out=%b clk=%b", in, out, clk); + if (out !== 16'b0110010101100101) begin // old value + $error("register failed"); + $fatal(1); + end + clk = 0; + # 10 + $display("REGISTER_DOWN_TEST: in=%b out=%b clk=%b", in, out, clk); + if (out !== 16'b1010110010101100) begin + $error("register failed"); + $fatal(1); + end + end +endmodule diff --git a/output/programs/3_led_switch.bin b/output/programs/3_led_switch.bin deleted file mode 100644 index 334da93..0000000 --- a/output/programs/3_led_switch.bin +++ /dev/null @@ -1,4 +0,0 @@ -00001100 00000000 00000000 00000000 -00100100 00000010 00000100 00000101 -00000100 00000100 00000110 00000100 -00110101 00001001 01000000 00000000 diff --git a/output/programs/3_led_switch_resolved.asm b/output/programs/3_led_switch_resolved.asm deleted file mode 100644 index f9b0e42..0000000 --- a/output/programs/3_led_switch_resolved.asm +++ /dev/null @@ -1,4 +0,0 @@ -PROGRAM_ORG equ 64 -040: IN [4], 5 -044: OUT 6, [4] -048: JMP 64, 0 diff --git a/output/programs/boot_sequence.bin b/output/programs/boot_sequence.bin deleted file mode 100644 index 9d8f26a..0000000 --- a/output/programs/boot_sequence.bin +++ /dev/null @@ -1,17 +0,0 @@ -01000000 00000000 00000000 00000000 -00110100 00000010 00000000 00000000 -00000100 00000100 00000010 00000000 -00100100 00000010 00000000 00000010 -01110011 00000010 00000000 00000010 -00110100 00000010 00000100 00000100 -00110100 00000010 00001000 10000000 -01110001 00000000 00000000 00000000 -00110101 00001011 01110000 00000000 -00000100 00000100 00000010 00000100 -00100100 00000010 00001100 00000010 -01000100 00000110 00001000 00001100 -01110000 00000010 00001000 00000100 -01110000 00000010 00000100 00000100 -01110001 00000010 00000000 00000001 -00110101 00001001 01001100 00000000 -00110101 00001001 10000000 00000000 diff --git a/output/programs/boot_sequence_resolved.asm b/output/programs/boot_sequence_resolved.asm deleted file mode 100644 index c53cfc2..0000000 --- a/output/programs/boot_sequence_resolved.asm +++ /dev/null @@ -1,17 +0,0 @@ -PROGRAM_ORG equ 52 -034: MOVC [0], 0 -038: OUT 2, [0] -03c: IN [0], 2 -040: SHRC [0], 2 -044: MOVC [4], 4 -048: MOVC [8], 128 -04c: CMPC [0], 0 -050: JZ 112, 0 -054: OUT 2, [4] -058: IN [12], 2 -05c: STORE [[8]], [12] -060: ADDC [8], 4 -064: ADDC [4], 4 -068: SUBC [0], 1 -06c: JMP 76, 0 -070: JMP 128, 0 diff --git a/output/programs/ping_pong.bin b/output/programs/ping_pong.bin deleted file mode 100644 index 195cf60..0000000 --- a/output/programs/ping_pong.bin +++ /dev/null @@ -1,198 +0,0 @@ -00010100 00000011 00000000 00000000 -00110100 00000010 00100000 11111111 -01110010 00000010 00100000 00001000 -01110111 00000010 00100000 11110000 -00110101 00001001 11000000 00000000 -00000010 00000000 00000000 00000000 -00000010 00000000 00000000 00000000 -00000111 00000000 00000000 00000000 -00000010 00000000 00000000 00000000 -11111111 11111111 00000000 00000000 -00000000 00000000 00000000 00000000 -00000110 00000000 00000000 00000000 -00000000 00000000 00000000 00000000 -00000001 00000000 00000000 00000000 -11111111 01111111 00000000 00000000 -11111110 11111111 00000000 00000000 -11111111 11111111 00000000 00000000 -01110000 00000011 00101000 00010000 -01110001 00000010 00100000 00000100 -01000100 00000110 00100000 00101000 -00110101 00001001 10101000 00000001 -01110000 00000011 00101000 00010000 -01110001 00000010 00100000 00000100 -01000100 00000110 00100000 00101000 -00110101 00001001 00111000 00000001 -01110000 00000011 00101000 00010000 -01110001 00000010 00100000 00000100 -01000100 00000110 00100000 00101000 -00110101 00001001 00111100 00000010 -00110101 00001001 11000000 00000000 -01110000 00000011 00101000 00010000 -01110001 00000010 00100000 00000100 -01000100 00000110 00100000 00101000 -00110101 00001001 00011000 00000001 -01110000 00000011 00101000 00010000 -01110001 00000010 00100000 00000100 -01000100 00000110 00100000 00101000 -00110101 00001001 10101000 00000001 -00110101 00001001 11110100 00000000 -01110001 00000000 10101100 00000000 -00110101 00001101 00101000 00000001 -01111000 00000010 10110000 00000001 -00110100 00000010 10101100 00001111 -01110001 00000010 10101100 00000001 -10000101 00000010 00101000 00100000 -01110000 00000010 00100000 00000100 -11110101 00001000 00101000 00000000 -00100100 00000010 00000000 00000001 -00110100 00000010 00000100 00000001 -01000110 00000010 00000100 00000000 -00110101 00001011 01010100 00000001 -01110001 00000000 10010000 00000000 -00110101 00001011 01010100 00000001 -01110001 00000010 10010000 00000001 -00110100 00000010 00000100 00000010 -01000110 00000010 00000100 00000000 -00110101 00001011 01101100 00000001 -01110001 00000000 10010000 00000101 -00110101 00001011 01101100 00000001 -01110000 00000010 10010000 00000001 -00110100 00000010 00000100 00000100 -01000110 00000010 00000100 00000000 -00110101 00001011 10000100 00000001 -01110001 00000000 10010100 00000000 -00110101 00001011 10000100 00000001 -01110001 00000010 10010100 00000001 -00110100 00000010 00000100 00001000 -01000110 00000010 00000100 00000000 -00110101 00001011 10011100 00000001 -01110001 00000000 10010100 00000101 -00110101 00001011 10011100 00000001 -01110000 00000010 10010100 00000001 -10000101 00000010 00101000 00100000 -01110000 00000010 00100000 00000100 -11110101 00001000 00101000 00000000 -01110001 00000000 10110000 00000000 -00110101 00001011 11111000 00000001 -00000100 00000010 00000000 10110100 -00110100 00000010 00000100 00000111 -01000010 00000010 00000100 10010000 -00000100 00000100 00000110 00000000 -00000100 00000100 00000111 00000100 -00110100 00000010 00000100 00000000 -00000100 00000010 00000000 10111100 -00000100 00000100 00000111 00000100 -00000100 00000100 00000110 00000000 -00000100 00000010 00000000 10111000 -00110100 00000010 00000100 00000111 -01000010 00000010 00000100 10010100 -00000100 00000100 00000110 00000000 -00000100 00000100 00000111 00000100 -00110100 00000010 00000100 00000000 -00000100 00000010 00000000 10111100 -00000100 00000100 00000111 00000100 -00000100 00000100 00000110 00000000 -00000100 00000010 00000000 10011000 -00110100 00000010 00000100 10000000 -01110010 00000010 00000100 00001000 -01000011 00000010 00000100 00000000 -01001000 00000010 00000100 10100000 -00000100 00000010 00000000 10011100 -00110100 00000010 00001000 00000001 -01000010 00000010 00001000 00000000 -00000100 00000100 00000110 00000100 -00000100 00000100 00000111 00001000 -00110100 00000010 00001000 00000000 -00000100 00000010 00000100 10111100 -00000100 00000100 00000111 00001000 -00000100 00000100 00000110 00000100 -10000101 00000010 00101000 00100000 -01110000 00000010 00100000 00000100 -11110101 00001000 00101000 00000000 -01110001 00000000 10100100 00000000 -00110101 00001101 01011000 00000010 -00110100 00000010 10100100 00000011 -01110000 00000011 00101000 00010000 -01110001 00000010 00100000 00000100 -01000100 00000110 00100000 00101000 -00110101 00001001 01101000 00000010 -01110001 00000010 10100100 00000001 -10000101 00000010 00101000 00100000 -01110000 00000010 00100000 00000100 -11110101 00001000 00101000 00000000 -01110001 00000000 10011000 00001110 -00110101 00001011 11001100 00000010 -01110001 00000000 10011000 00000001 -00110101 00001011 11110000 00000010 -01110001 00000000 10011100 00000111 -00110101 00001011 10000000 00000011 -01110001 00000000 10011100 00000000 -00110101 00001011 10000000 00000011 -00000100 00000010 00000000 10101000 -01110110 00000010 00000000 00000001 -00110101 00001011 10011100 00000010 -01110000 00000010 10011000 00000001 -00110101 00001001 10100000 00000010 -01110001 00000010 10011000 00000001 -00000100 00000010 00000000 10101000 -01110110 00000010 00000000 00000100 -00110101 00001011 10110000 00000010 -01110001 00000010 10011100 00000001 -00000100 00000010 00000000 10101000 -01110110 00000010 00000000 00001000 -00110101 00001011 11000000 00000010 -01110000 00000010 10011100 00000001 -10000101 00000010 00101000 00100000 -01110000 00000010 00100000 00000100 -11110101 00001000 00101000 00000000 -01110001 00000010 00100000 00000100 -01000100 00000110 00100000 10010100 -01110000 00000011 00101000 00010000 -01110001 00000010 00100000 00000100 -01000100 00000110 00100000 00101000 -00110101 00001001 00010100 00000011 -10000101 00000010 00011100 00100000 -01110000 00000010 00100000 00000100 -00110101 00001001 01111000 00000010 -01110001 00000010 00100000 00000100 -01000100 00000110 00100000 10010000 -01110000 00000011 00101000 00010000 -01110001 00000010 00100000 00000100 -01000100 00000110 00100000 00101000 -00110101 00001001 00010100 00000011 -10000101 00000010 00011100 00100000 -01110000 00000010 00100000 00000100 -00110101 00001001 01111000 00000010 -00000100 00000010 00100100 00100000 -01110000 00000010 00100100 00000100 -10000101 00000010 00000100 00100100 -01111000 00000010 10101000 00000011 -00110100 00000010 00000000 00001100 -01111000 00000010 00000000 11111111 -01000110 00000010 10101000 00000000 -01000001 00000000 10011100 00000100 -00110101 00001011 01010100 00000011 -01110000 00000010 00000100 00000001 -01000001 00000000 10011100 00000100 -00110101 00001011 01110100 00000011 -01110000 00000010 00000100 00000001 -01000001 00000000 10011100 00000100 -00110101 00001011 01100100 00000011 -00110101 00001001 11110100 00000000 -01110111 00000010 10101000 00000100 -10000101 00000010 00101000 00100000 -01110000 00000010 00100000 00000100 -11110101 00001000 00101000 00000000 -01110111 00000010 10101000 00001000 -10000101 00000010 00101000 00100000 -01110000 00000010 00100000 00000100 -11110101 00001000 00101000 00000000 -10000101 00000010 00101000 00100000 -01110000 00000010 00100000 00000100 -11110101 00001000 00101000 00000000 -00000100 00000010 00000000 10101000 -01110110 00000010 00000000 00001100 -00110101 00001011 10001000 00000010 -01111000 00000010 10101000 00001100 -00110101 00001001 10001000 00000010 diff --git a/output/programs/ping_pong_resolved.asm b/output/programs/ping_pong_resolved.asm deleted file mode 100644 index b8f0c8f..0000000 --- a/output/programs/ping_pong_resolved.asm +++ /dev/null @@ -1,234 +0,0 @@ -PROGRAM_ORG equ 128 -080: MOVC [32], 255 -084: SHLC [32], 8 -088: ORC [32], 240 -08c: JMP 192, 0 -090: 02 -091: 00 -092: 00 -093: 00 -094: 02 -095: 00 -096: 00 -097: 00 -098: 07 -099: 00 -09a: 00 -09b: 00 -09c: 02 -09d: 00 -09e: 00 -09f: 00 -0a0: 255 -0a1: 255 -0a2: 00 -0a3: 00 -0a4: 00 -0a5: 00 -0a6: 00 -0a7: 00 -0a8: 06 -0a9: 00 -0aa: 00 -0ab: 00 -0ac: 00 -0ad: 00 -0ae: 00 -0af: 00 -0b0: 01 -0b1: 00 -0b2: 00 -0b3: 00 -0b4: 255 -0b5: 127 -0b6: 00 -0b7: 00 -0b8: 254 -0b9: 255 -0ba: 00 -0bb: 00 -0bc: 255 -0bd: 255 -0be: 00 -0bf: 00 -0c0: PCPLUS [40], 16 -0c4: SUBC [32], 4 -0c8: STORE [[32]], [40] -0cc: JMP 168, 1 -0d0: PCPLUS [40], 16 -0d4: SUBC [32], 4 -0d8: STORE [[32]], [40] -0dc: JMP 56, 1 -0e0: PCPLUS [40], 16 -0e4: SUBC [32], 4 -0e8: STORE [[32]], [40] -0ec: JMP 60, 2 -0f0: JMP 192, 0 -0f4: PCPLUS [40], 16 -0f8: SUBC [32], 4 -0fc: STORE [[32]], [40] -100: JMP 24, 1 -104: PCPLUS [40], 16 -108: SUBC [32], 4 -10c: STORE [[32]], [40] -110: JMP 168, 1 -114: JMP 244, 0 -118: CMPC [172], 0 -11c: JNZ 40, 1 -120: XORC [176], 1 -124: MOVC [172], 15 -128: SUBC [172], 1 -12c: LOAD [40], [[32]] -130: ADDC [32], 4 -134: JMPM [40], [0] -138: IN [0], 1 -13c: MOVC [4], 1 -140: AND [4], [0] -144: JZ 84, 1 -148: CMPC [144], 0 -14c: JZ 84, 1 -150: SUBC [144], 1 -154: MOVC [4], 2 -158: AND [4], [0] -15c: JZ 108, 1 -160: CMPC [144], 5 -164: JZ 108, 1 -168: ADDC [144], 1 -16c: MOVC [4], 4 -170: AND [4], [0] -174: JZ 132, 1 -178: CMPC [148], 0 -17c: JZ 132, 1 -180: SUBC [148], 1 -184: MOVC [4], 8 -188: AND [4], [0] -18c: JZ 156, 1 -190: CMPC [148], 5 -194: JZ 156, 1 -198: ADDC [148], 1 -19c: LOAD [40], [[32]] -1a0: ADDC [32], 4 -1a4: JMPM [40], [0] -1a8: CMPC [176], 0 -1ac: JZ 248, 1 -1b0: MOV [0], [180] -1b4: MOVC [4], 7 -1b8: SHL [4], [144] -1bc: OUT 6, [0] -1c0: OUT 7, [4] -1c4: MOVC [4], 0 -1c8: MOV [0], [188] -1cc: OUT 7, [4] -1d0: OUT 6, [0] -1d4: MOV [0], [184] -1d8: MOVC [4], 7 -1dc: SHL [4], [148] -1e0: OUT 6, [0] -1e4: OUT 7, [4] -1e8: MOVC [4], 0 -1ec: MOV [0], [188] -1f0: OUT 7, [4] -1f4: OUT 6, [0] -1f8: MOV [0], [152] -1fc: MOVC [4], 128 -200: SHLC [4], 8 -204: SHR [4], [0] -208: XOR [4], [160] -20c: MOV [0], [156] -210: MOVC [8], 1 -214: SHL [8], [0] -218: OUT 6, [4] -21c: OUT 7, [8] -220: MOVC [8], 0 -224: MOV [4], [188] -228: OUT 7, [8] -22c: OUT 6, [4] -230: LOAD [40], [[32]] -234: ADDC [32], 4 -238: JMPM [40], [0] -23c: CMPC [164], 0 -240: JNZ 88, 2 -244: MOVC [164], 3 -248: PCPLUS [40], 16 -24c: SUBC [32], 4 -250: STORE [[32]], [40] -254: JMP 104, 2 -258: SUBC [164], 1 -25c: LOAD [40], [[32]] -260: ADDC [32], 4 -264: JMPM [40], [0] -268: CMPC [152], 14 -26c: JZ 204, 2 -270: CMPC [152], 1 -274: JZ 240, 2 -278: CMPC [156], 7 -27c: JZ 128, 3 -280: CMPC [156], 0 -284: JZ 128, 3 -288: MOV [0], [168] -28c: ANDC [0], 1 -290: JZ 156, 2 -294: ADDC [152], 1 -298: JMP 160, 2 -29c: SUBC [152], 1 -2a0: MOV [0], [168] -2a4: ANDC [0], 4 -2a8: JZ 176, 2 -2ac: SUBC [156], 1 -2b0: MOV [0], [168] -2b4: ANDC [0], 8 -2b8: JZ 192, 2 -2bc: ADDC [156], 1 -2c0: LOAD [40], [[32]] -2c4: ADDC [32], 4 -2c8: JMPM [40], [0] -2cc: SUBC [32], 4 -2d0: STORE [[32]], [148] -2d4: PCPLUS [40], 16 -2d8: SUBC [32], 4 -2dc: STORE [[32]], [40] -2e0: JMP 20, 3 -2e4: LOAD [28], [[32]] -2e8: ADDC [32], 4 -2ec: JMP 120, 2 -2f0: SUBC [32], 4 -2f4: STORE [[32]], [144] -2f8: PCPLUS [40], 16 -2fc: SUBC [32], 4 -300: STORE [[32]], [40] -304: JMP 20, 3 -308: LOAD [28], [[32]] -30c: ADDC [32], 4 -310: JMP 120, 2 -314: MOV [36], [32] -318: ADDC [36], 4 -31c: LOAD [4], [[36]] -320: XORC [168], 3 -324: MOVC [0], 12 -328: XORC [0], 255 -32c: AND [168], [0] -330: CMP [156], [4] -334: JZ 84, 3 -338: ADDC [4], 1 -33c: CMP [156], [4] -340: JZ 116, 3 -344: ADDC [4], 1 -348: CMP [156], [4] -34c: JZ 100, 3 -350: JMP 244, 0 -354: ORC [168], 4 -358: LOAD [40], [[32]] -35c: ADDC [32], 4 -360: JMPM [40], [0] -364: ORC [168], 8 -368: LOAD [40], [[32]] -36c: ADDC [32], 4 -370: JMPM [40], [0] -374: LOAD [40], [[32]] -378: ADDC [32], 4 -37c: JMPM [40], [0] -380: MOV [0], [168] -384: ANDC [0], 12 -388: JZ 136, 2 -38c: XORC [168], 12 -390: JMP 136, 2 diff --git a/planner/memory.py b/planner/memory.py index b1706d6..fef0af4 100644 --- a/planner/memory.py +++ b/planner/memory.py @@ -17,8 +17,8 @@ def get_register_address(index): # free # boot sequence -BOOTSEQUENCE_LOAD = 0x30 -BOOTSEQUENCE_ORG = 0x34 # as we have 4-byte rom size header at top +BOOTSEQUENCE_LOAD = 0x40 +BOOTSEQUENCE_ORG = 0x44 # as we have 4-byte rom size header at top # user program DEFAULT_PROGRAM_ORG = 0x80 diff --git a/planner/sim/bin_parser.py b/planner/sim/bin_parser.py index 6ca5e05..ab8025d 100644 --- a/planner/sim/bin_parser.py +++ b/planner/sim/bin_parser.py @@ -12,7 +12,9 @@ def binary_array_num(arr: List[int]): return sum([x<<(8*i) for i, x in enumerate(arr)]) +FLAGS_BITS = 2 FLAGS_BIT_VW_ZERO = 0 +FLAGS_BIT_EXECUTE_FROM_RAM = 1 class BinRunner: def __init__(self, clock: devices.Clock, ram: devices.RAM, brom: devices.ROM): @@ -29,7 +31,7 @@ def __init__(self, clock: devices.Clock, ram: devices.RAM, brom: devices.ROM): # self.is_powered_on = False # self.step() self.is_powered_on = True - self.flags = [0] + self.flags = [0]*FLAGS_BITS # self.step() self.stage = 0 @@ -132,6 +134,7 @@ def m_fetch_and_store_stage3( return if sel == instruction.MBlockSelector_stage3.PC_NEXT: self.reg_pc_next = vw_value + self.flags[FLAGS_BIT_EXECUTE_FROM_RAM] = 1 return if sel == instruction.MBlockSelector_stage3.PC_NEXT_IF_ZERO: # check previous vw_value flags @@ -146,6 +149,7 @@ def m_fetch_and_store_stage3( if sel == instruction.MBlockSelector_stage3.HLT: self.is_powered_on = False return + raise Exception(f"unsupported selector: {sel}") def m_alu(self, rw: int, r: int, op: instruction.ALU): @@ -156,9 +160,6 @@ def m_alu(self, rw: int, r: int, op: instruction.ALU): def is_power_on(self): return self.is_powered_on - def is_boot_sequence(self): - return self.pc >= memory.BOOTSEQUENCE_ORG and self.pc < memory.DEFAULT_PROGRAM_ORG - def print_bootsequence_completed(self): if hasattr(self, "_print_bootsequence_completed"): return @@ -172,13 +173,12 @@ def trigger_stage0(self): logging.debug("[stage0] PC: 0x%x, flags: %s", self.pc, self.flags) # Read instruction - if self.is_boot_sequence(): + if self.flags[FLAGS_BIT_EXECUTE_FROM_RAM] == 0: brom_address = self.pc-memory.BOOTSEQUENCE_LOAD self.brom.address_line.update(brom_address) ins_binary = self.brom.value_line.get() else: self.print_bootsequence_completed() - self.ram.is_write.update(0) self.ram.address_line.update(self.pc) ins_binary = self.ram.value_out_line.get() ins_binary_array = util.to_little_32binaryarray(ins_binary) @@ -249,6 +249,6 @@ def trigger_stage3(self): self.reg_vrw_source, self.reg_mblock_s3) + # TODO: Move it to stage2 self.flags[FLAGS_BIT_VW_ZERO] = 1 if (self.reg_vw_value==0) else 0 - diff --git a/planner/sim/devices.py b/planner/sim/devices.py index 39ef8d8..0333298 100644 --- a/planner/sim/devices.py +++ b/planner/sim/devices.py @@ -4,6 +4,7 @@ import time import random import logging +import atexit class Device: def __init__(self, bits = 8): @@ -247,7 +248,7 @@ def display(self, only_if_changed=True): if self.use_print: print(new_display) -RAM_SIZE = 0x10000 # 64KB +RAM_SIZE = 0x400 # 4KB class RAM(object): def __init__(self): @@ -262,10 +263,19 @@ def __init__(self): self.is_write = IntegerOutput("ram_is_write", bits=1) self.value_in_line = IntegerOutput("ram_value_in", bits=self.value_bits) self.value_out_line = LatchInput("ram_value_out", bits=self.value_bits) + self._debug_address_used = set() + + def _debug_on_exit(): + print("RAM used: %d byte(s)" % len(self._debug_address_used)) + atexit.register(_debug_on_exit) def _on_address_change(_, __): address = self.address_line.get() value=util.from_littlearray_32binary(self.read_ram(address, 4)) + self._debug_address_used.add(value) + self._debug_address_used.add(value+1) + self._debug_address_used.add(value+2) + self._debug_address_used.add(value+3) self.value_out_line.update(value) self.address_line.add_change_handler(_on_address_change) diff --git a/programs/boot_sequence.asm b/programs/boot_sequence.asm index fcce3a0..8a4b663 100644 --- a/programs/boot_sequence.asm +++ b/programs/boot_sequence.asm @@ -7,7 +7,7 @@ PROM_ADDRESS_LINE equ 2 # input(2) = PROGRAM_ROM value PROM_VALUE_LINE equ 2 -PROGRAM_ORG equ 0x34 +PROGRAM_ORG equ 0x44 RAM_PROGRAM_ORG equ 0x80 ROM_INPUT_VALUE equ 0x0 @@ -25,15 +25,18 @@ section .text movc R1, 4 movc R2, RAM_PROGRAM_ORG copy_more: - cmpc R0, 0 - jz copy_completed out PROM_ADDRESS_LINE, R1 in R3, PROM_VALUE_LINE store [R2], R3 addc R2, 4 addc R1, 4 subc R0, 1 - jmp copy_more + jnz copy_more copy_completed: + # setup default stack + movc ESP, 0x03 + shlc ESP, 8 + orc ESP, 0xFC + # jmp enables FLAGS_BIT_EXECUTE_FROM_RAM jmp RAM_PROGRAM_ORG diff --git a/programs/ping_pong.asm b/programs/ping_pong.asm index 1269cb7..cb22f7c 100644 --- a/programs/ping_pong.asm +++ b/programs/ping_pong.asm @@ -49,9 +49,6 @@ BALL_MINY equ 0 section .text main: - movc ESP, 0xFF - shlc ESP, 8 - orc ESP, 0xF0 jmp game section .data From f0255cb99773da00eab38c9e176b8a7a20316fdb Mon Sep 17 00:00:00 2001 From: Gagan Kumar Date: Sat, 4 Jan 2025 11:56:27 -0800 Subject: [PATCH 2/8] Verilog added upto stage2 and unit tests --- emulator/chipset.v | 78 +++++++++++++----------------- emulator/com/stage2.v | 63 ++++++++++++++++++++++++ emulator/com/stage2_test.v | 98 ++++++++++++++++++++++++++++++++++++++ emulator/com/stage3.v | 0 planner/instruction.py | 12 ++--- planner/sim/bin_parser.py | 4 +- 6 files changed, 202 insertions(+), 53 deletions(-) create mode 100644 emulator/com/stage2.v create mode 100644 emulator/com/stage2_test.v create mode 100644 emulator/com/stage3.v diff --git a/emulator/chipset.v b/emulator/chipset.v index 31f0b23..25c6357 100644 --- a/emulator/chipset.v +++ b/emulator/chipset.v @@ -1,5 +1,7 @@ `include "emulator/module/clock.v" `include "emulator/seq/register.v" +`include "emulator/com/stage0.v" +`include "emulator/com/stage1.v" module CHIPSET( @@ -37,10 +39,14 @@ module CHIPSET( wire[15:0] ram_address_stage0; + wire[15:0] ram_address_stage1; // TODO: Updated ram_address assign ram_address = ram_address_stage0; - + // Input Devices + wire[7:0] input_devices_address; + reg[31:0] input_devices_value; + // TODO: add devices modules // Boot Sequence // @@ -64,21 +70,10 @@ module CHIPSET( .clk(clk[3]), ); - - // Following circuit is continous within each stages - // with exception of RAM write which relies on clock; - // wire[15:0] program_counter; - // wire[1:0] mblock_selector; - // wire[15:0] mblock_address; - // wire[31:0] mblock_input; - // wire[31:0] mblock_output; - // wire mblock_write; - - // STAGE0 - wire[31:0] instruction_binary; - STAGE0 instruction_resolver( - .instruction_binary(instruction_binary), + wire[31:0] _instruction_binary; + STAGE0 stage0( + .instruction_binary(_instruction_binary), .ram_address(ram_address_stage0), .brom_address(brom_address), .ram_value(ram_value), @@ -87,42 +82,35 @@ module CHIPSET( .execute_from_ram(execute_from_ram)); // STAGE1 - wire[31:0] instruction_binary_cached; + wire[31:0] instruction_binary; REGISTER_up_16b r_ins_bin( - .out(instruction_binary_cached), - .in(instruction_binary), + .out(instruction_binary), + .in(_instruction_binary), .clk(clk[1])); - wire[3:0] mblock_alu_op = instruction_binary_cached[3:0]; - wire[3:0] mblock_s1 = instruction_binary_cached[5:4]; - wire[1:0] mblock_s2 = instruction_binary_cached[8:6]; - wire[2:0] mblock_s3 = instruction_binary_cached[11:9]; - wire[7:0] vrw_source = instruction_binary_cached[23:16]; - wire[7:0] vr_source = instruction_binary_cached[31:24]; - - - - // STAGE1 - - // TODO: Breakdown instruction_op into sub-operations - - // TODO: Ensure MBLOCK supplies expectations. - // MBLOCK_MUX is expected to fetch MBLOCK based on v0_source and - // instruction_op breakdowns and redirect the value into v0. - - // @stage1 posedge following should freeze. - wire[31:0] vr_value; -; - FETCH_AND_STORE stage1( - .vr_value(vr_value), - .is_powered_on(is_powered_on), - .pc_next(pc_next), - .pc(pc), - .vr_source(vr_source), + wire[3:0] mblock_alu_op = instruction_binary[3:0]; + wire[3:0] mblock_s1 = instruction_binary[5:4]; + wire[1:0] mblock_s2 = instruction_binary[8:6]; + wire[2:0] mblock_s3 = instruction_binary[11:9]; + wire[7:0] vrw_source = instruction_binary[23:16]; + wire[7:0] vr_source = instruction_binary[31:24]; + + wire[31:0] _vr_value; + STAGE1 stage1( + .vr_value(_vr_value), + .input_devices_address(input_devices_address), + .ram_address(ram_address), .mblock_s1(mblock_s1), - .clk(clk[1])); + .vr_source(vr_source), + .input_devices_value(input_devices_value), + .ram_value(ram_value)); // STAGE2 + wire[31:0] vr_value; + REGISTER_up_16b r_ins_bin( + .out(_vr_value), + .in(_instruction_binary), + .clk(clk[2])); // TODO: Ensure MBLOCK supplies expectations. // MBLOCK_MUX is expected to fetch MBLOCK based on v0_source and diff --git a/emulator/com/stage2.v b/emulator/com/stage2.v new file mode 100644 index 0000000..2c4d772 --- /dev/null +++ b/emulator/com/stage2.v @@ -0,0 +1,63 @@ +`include "emulator/com/mux.v" +`include "emulator/com/alu.v" + +module STAGE2( + output[31:0] vrw_value, + output[31:0] vw_value, + output[15:0] ram_address, + output alu_is_zero, + input[2:0] mblock_s2, + input[7:0] vr_source, + input[31:0] vr_value, + input[7:0] vrw_source, + input[3:0] alu_op, + input[15:0] pc, + input[31:0] ram_value); + + wire[15:0] _iv; + wire[31:0] _m_vrw_value; + + MUX_2_16b m1( + .value(_iv[15:0]), + .A0({8'b00000000, vrw_source[7:0]}), + .A1(vr_value[15:0]), + .A2({vr_source[7:0], vrw_source[7:0]}), + .A3(16'bxxxxxxxxxxxxxxxx), + .S(mblock_s2[1:0])); + + assign ram_address = _iv; + + MUX_1_16b m2a( + .value(_m_vrw_value[31:16]), + .A0(ram_value[31:16]), + .A1(16'b0000000000000000), + .S(mblock_s2[2])); + MUX_1_16b m2b( + .value(_m_vrw_value[15:0]), + .A0(ram_value[15:0]), + .A1(_iv[15:0]), + .S(mblock_s2[2])); + + wire want_pc = ( + mblock_s2[0] & mblock_s2[1] & mblock_s2[2] + ); + + MUX_1_16b m3a( + .value(vrw_value[31:16]), + .A0(_m_vrw_value[31:16]), + .A1(16'b0000000000000000), + .S(want_pc)); + MUX_1_16b m3b( + .value(vrw_value[15:0]), + .A0(_m_vrw_value[15:0]), + .A1(pc[15:0]), + .S(want_pc)); + + ALU alu( + .out(vw_value), + .is_zero(alu_is_zero), + .op(alu_op), + .in_r(vr_value), + .in_rw(vrw_value)); + +endmodule diff --git a/emulator/com/stage2_test.v b/emulator/com/stage2_test.v new file mode 100644 index 0000000..11f6004 --- /dev/null +++ b/emulator/com/stage2_test.v @@ -0,0 +1,98 @@ +`include "emulator/com/stage2.v" + +module stage2_test; + wire[31:0] vrw_value; + wire[31:0] vw_value; + wire[15:0] ram_address; + wire alu_is_zero; + + reg[2:0] mblock_s2; + reg[7:0] vr_source; + reg[31:0] vr_value; + reg[7:0] vrw_source; + reg[3:0] alu_op; + reg[15:0] pc; + reg[31:0] ram_value; + + STAGE2 dut( + .vrw_value(vrw_value), + .vw_value(vw_value), + .ram_address(ram_address), + .alu_is_zero(alu_is_zero), + .mblock_s2(mblock_s2), + .vr_source(vr_source), + .vr_value(vr_value), + .vrw_source(vrw_source), + .alu_op(alu_op), + .pc(pc), + .ram_value(ram_value)); + + initial begin + vr_source = 10; + vr_value = 1000; + vrw_source = 20; + alu_op = 0; // add + pc = 84; + ram_value = 99; + # 10 + mblock_s2 = 0; + # 10 + $display("STAGE2_TEST: vrw_value=%b vw_value=%b alu_is_zero=%b ram_address=%b", vrw_value, vw_value, alu_is_zero, ram_address); + if (vrw_value !== 99 || ram_address !== 20 || vw_value != 1099 || alu_is_zero != 0) begin + $error("stage2 failed"); + $fatal(1); + end + # 10 + mblock_s2 = 1; + # 10 + $display("STAGE2_TEST: vrw_value=%b vw_value=%b alu_is_zero=%b ram_address=%b", vrw_value, vw_value, alu_is_zero, ram_address); + if (vrw_value !== 99 || ram_address !== 1000 || vw_value != 1099 || alu_is_zero != 0) begin + $error("stage2 failed"); + $fatal(1); + end + # 10 + mblock_s2 = 2; + # 10 + $display("STAGE2_TEST: vrw_value=%b vw_value=%b alu_is_zero=%b ram_address=%b", vrw_value, vw_value, alu_is_zero, ram_address); + if (vrw_value !== 99 || ram_address !== ((10<<8)|20) || vw_value != 1099 || alu_is_zero != 0) begin + $error("stage2 failed"); + $fatal(1); + end + # 10 + mblock_s2 = 4; + # 10 + $display("STAGE2_TEST: vrw_value=%b vw_value=%b alu_is_zero=%b", vrw_value, vw_value, alu_is_zero); + if (vrw_value !== 20 || vw_value != 1020 || alu_is_zero != 0) begin + $error("stage2 failed"); + $fatal(1); + end + # 10 + mblock_s2 = 6; + # 10 + $display("STAGE2_TEST: vrw_value=%b vw_value=%b alu_is_zero=%b ram_address=%b", vrw_value, vw_value, alu_is_zero, ram_address); + if (vrw_value !== ((10<<8)|20) || vw_value != (((10<<8)|20)+1000) || alu_is_zero != 0) begin + $error("stage2 failed"); + $fatal(1); + end + # 10 + mblock_s2 = 7; + # 10 + $display("STAGE2_TEST: vrw_value=%b vw_value=%b alu_is_zero=%b ram_address=%b", vrw_value, vw_value, alu_is_zero, ram_address); + if (vrw_value !== 84 || vw_value != 1084 || alu_is_zero != 0) begin + $error("stage2 failed"); + $fatal(1); + end + # 10 + mblock_s2 = 0; + alu_op = 1; // sub + ram_value = 1000; + # 10 + $display("STAGE2_TEST: vrw_value=%b vw_value=%b alu_is_zero=%b ram_address=%b", vrw_value, vw_value, alu_is_zero, ram_address); + if (vrw_value !== 1000 || ram_address !== 20 || vw_value != 0 || alu_is_zero != 1) begin + $error("stage2 failed"); + $fatal(1); + end + end + + +endmodule diff --git a/emulator/com/stage3.v b/emulator/com/stage3.v new file mode 100644 index 0000000..e69de29 diff --git a/planner/instruction.py b/planner/instruction.py index efc33a1..c830232 100644 --- a/planner/instruction.py +++ b/planner/instruction.py @@ -51,14 +51,14 @@ class MBlockSelector_stage2(Enum): ''' bits: [read_ram(vrw_source) else read_ram(vr_value)] ''' - VRW_SOURCE_CONST = 0 - VRW_SOURCE_RAM = 1 - VR_VALUE_RAM = 2 + VRW_SOURCE_CONST = 4 + VRW_SOURCE_RAM = 0 + VR_VALUE_RAM = 1 # vr_source<<8 | vrw_source # Pretty specific operation for passing 16-bit constant or address - VR_SOURCE_SHL8_VRW_SOURCE_RAM = 3 - VR_SOURCE_SHL8_VRW_SOURCE_CONST = 4 - PC = 5 + VR_SOURCE_SHL8_VRW_SOURCE_RAM = 2 + VR_SOURCE_SHL8_VRW_SOURCE_CONST = 6 + PC = 7 # last one for reverse lookup DONT_CARE = 0 diff --git a/planner/sim/bin_parser.py b/planner/sim/bin_parser.py index ab8025d..5b706ef 100644 --- a/planner/sim/bin_parser.py +++ b/planner/sim/bin_parser.py @@ -104,10 +104,10 @@ def m_fetch_and_store_stage2( return binary_array_num(self.read_ram(vr_value, 4)) # reading from 32-bit address if sel == instruction.MBlockSelector_stage2.VRW_SOURCE_RAM: return binary_array_num(self.read_ram(vrw_source, 4)) # reading from 8-bit address - if sel == instruction.MBlockSelector_stage2.VRW_SOURCE_CONST: - return vrw_source if sel == instruction.MBlockSelector_stage2.VR_SOURCE_SHL8_VRW_SOURCE_RAM: return binary_array_num(self.read_ram((vr_source<<8) | vrw_source, 4)) # reading from 16-bit address + if sel == instruction.MBlockSelector_stage2.VRW_SOURCE_CONST: + return vrw_source if sel == instruction.MBlockSelector_stage2.VR_SOURCE_SHL8_VRW_SOURCE_CONST: return (vr_source<<8) | vrw_source if sel == instruction.MBlockSelector_stage2.PC: From a7b9f82f3f34fa080c177621b016081fa35f850e Mon Sep 17 00:00:00 2001 From: Gagan Kumar Date: Sat, 4 Jan 2025 16:23:38 -0800 Subject: [PATCH 3/8] Added stage3 and input/output devices --- emulator/chipset.v | 5 +- emulator/com/decoder.v | 34 +++----- emulator/com/decoder_test.v | 89 +++++++------------ emulator/com/flipflop.v | 30 ------- emulator/com/flipflop_test.v | 58 ------------- emulator/com/input_devices.v | 15 ++++ emulator/com/input_devices_test.v | 35 ++++++++ emulator/com/latch.v | 13 --- emulator/com/latch_test.v | 73 ---------------- emulator/com/stage2_test.v | 14 +-- emulator/com/stage3.v | 54 ++++++++++++ emulator/com/stage3_test.v | 135 +++++++++++++++++++++++++++++ emulator/seq/output_devices.v | 18 ++++ emulator/seq/output_devices_test.v | 50 +++++++++++ 14 files changed, 358 insertions(+), 265 deletions(-) delete mode 100644 emulator/com/flipflop.v delete mode 100644 emulator/com/flipflop_test.v create mode 100644 emulator/com/input_devices.v create mode 100644 emulator/com/input_devices_test.v delete mode 100644 emulator/com/latch.v delete mode 100644 emulator/com/latch_test.v create mode 100644 emulator/com/stage3_test.v create mode 100644 emulator/seq/output_devices.v create mode 100644 emulator/seq/output_devices_test.v diff --git a/emulator/chipset.v b/emulator/chipset.v index 25c6357..8290a09 100644 --- a/emulator/chipset.v +++ b/emulator/chipset.v @@ -12,7 +12,8 @@ module CHIPSET( ); reg is_powered_on; - reg execute_from_ram; + reg flag_execute_from_ram; + reg flag_last_zero; reg[15:0] pc, pc_next; // Clock @@ -79,7 +80,7 @@ module CHIPSET( .ram_value(ram_value), .brom_value(brom_value), .pc(pc), - .execute_from_ram(execute_from_ram)); + .execute_from_ram(flag_execute_from_ram)); // STAGE1 wire[31:0] instruction_binary; diff --git a/emulator/com/decoder.v b/emulator/com/decoder.v index 3e9efd4..2cca355 100644 --- a/emulator/com/decoder.v +++ b/emulator/com/decoder.v @@ -1,22 +1,12 @@ -// module DECODER_4_2( -// output[3:0] out, -// input[1:0] in); - -// assign out[0] = (~in[1] & ~in[0]); -// assign out[1] = (~in[1] & in[0]); -// assign out[2] = ( in[1] & ~in[0]); -// assign out[3] = ( in[1] & in[0]); -// endmodule - - -// module DECODER_8_3( -// output[7:0] out, -// input[2:0] in); - -// wire [3:0] _out; -// DECODER_4_2 d(_out[3:0], in[1:0]); - -// wire not_in2 = ~in[2]; -// assign out[3:0] = _out[3:0] & {not_in2, not_in2, not_in2, not_in2}; -// assign out[7:4] = _out[3:0] & {in[2], in[2], in[2], in[2]}; -// endmodule +module DECODER_3( + output[7:0] out, + input[2:0] in); + assign out[0] = (in==0); + assign out[1] = (in==1); + assign out[2] = (in==2); + assign out[3] = (in==3); + assign out[4] = (in==4); + assign out[5] = (in==5); + assign out[6] = (in==6); + assign out[7] = (in==7); +endmodule diff --git a/emulator/com/decoder_test.v b/emulator/com/decoder_test.v index f62d5fa..809b617 100644 --- a/emulator/com/decoder_test.v +++ b/emulator/com/decoder_test.v @@ -1,61 +1,30 @@ -// `include "emulator/lib/decoder.v" - -module decoder_4_2_test; -// reg [1:0] in; -// wire [3:0] out; - -// DECODER_4_2 dut(.out(out), .in(in)); - -// initial begin -// in = 2'b00; -// # 10 -// $display("DECODER_TEST: in=%b out=%b", in, out); -// if (out != 4'b0001) begin -// $error("decoder failed"); -// end -// in = 2'b01; -// # 10 -// $display("DECODER_TEST: in=%b out=%b", in, out); -// if (out != 4'b0010) begin -// $error("decoder failed"); -// end -// in = 2'b10; -// # 10 -// $display("DECODER_TEST: in=%b out=%b", in, out); -// if (out != 4'b0100) begin -// $error("decoder failed"); -// end -// in = 2'b11; -// # 10 -// $display("DECODER_TEST: in=%b out=%b", in, out); -// if (out != 4'b1000) begin -// $error("decoder failed"); -// end - -// end +`include "emulator/com/decoder.v" + +module decoder_3_test; + reg [2:0] in; + wire [7:0] out; + + DECODER_3 dut(.out(out), .in(in)); + + initial begin + in = 3'b010; + # 10 + $display("DECODER_TEST: in=%b out=%b", in, out); + if (out !== 8'b00000100) begin + $error("decoder failed"); + end + in = 3'b101; + # 10 + $display("DECODER_TEST: in=%b out=%b", in, out); + if (out !== 8'b00100000) begin + $error("decoder failed"); + end + in = 3'b111; + # 10 + $display("DECODER_TEST: in=%b out=%b", in, out); + if (out !== 8'b10000000) begin + $error("decoder failed"); + end + + end endmodule - - -// module decoder_8_3_test; -// reg [2:0] in; -// wire [7:0] out; - -// DECODER_8_3 dut(.out(out), .in(in)); - -// initial begin -// in = 3'b010; -// # 10 -// $display("DECODER_TEST: in=%b out=%b", in, out); -// if (out != 8'b00000100) begin -// $error("decoder failed"); -// $fatal(1); -// end -// in = 3'b101; -// # 10 -// $display("DECODER_TEST: in=%b out=%b", in, out); -// if (out != 8'b00100000) begin -// $error("decoder failed"); -// $fatal(1); -// end -// end -// endmodule diff --git a/emulator/com/flipflop.v b/emulator/com/flipflop.v deleted file mode 100644 index b989fdc..0000000 --- a/emulator/com/flipflop.v +++ /dev/null @@ -1,30 +0,0 @@ -// module __flipflop #(parameter BITS = 32)( -// output[BITS-1:0] out, -// input clk, -// input[BITS-1:0] in); - -// reg[BITS-1:0] mem; -// always @(posedge clk) begin -// mem[BITS-1:0] <= in[BITS-1:0]; -// end -// assign out[BITS-1:0] = mem[BITS-1:0]; -// endmodule - -// module flipflop32( -// output[31:0] out, -// input clk, -// input[31:0] in); - -// __flipflop #(.BITS(32)) ff(.out(out), .clk(clk), .in(in)); - -// endmodule - -// module flipflop16( -// output[15:0] out, -// input clk, -// input[15:0] in); - -// __flipflop #(.BITS(16)) ff(.out(out), .clk(clk), .in(in)); - -// endmodule - diff --git a/emulator/com/flipflop_test.v b/emulator/com/flipflop_test.v deleted file mode 100644 index c3b0c95..0000000 --- a/emulator/com/flipflop_test.v +++ /dev/null @@ -1,58 +0,0 @@ -// `include "emulator/lib/flipflop.v" - -module flipflop_test; -// reg[31:0] in; -// reg clk; -// wire[31:0] out; - -// flipflop32 dut(.out(out), .in(in), .clk(clk)); - -// initial begin -// clk = 0; -// in = 32'b00110110110101010100101101101000; -// # 10 -// clk = 1; -// # 10 -// $display("FLIPFLOP: in=%b out=%b clk=%b", in, out, clk); -// if (out !== 32'b00110110110101010100101101101000) begin -// $error("flipflop failed"); -// $fatal(1); -// end - -// clk = 0; -// # 10 -// in = 32'b01100011111101011011010100000100; -// # 10 -// $display("FLIPFLOP: in=%b out=%b clk=%b", in, out, clk); -// if (out !== 32'b00110110110101010100101101101000) begin -// $error("flipflop failed"); -// $fatal(1); -// end - -// in = 32'b10101100011011010010001010011001; -// # 10 -// $display("FLIPFLOP: in=%b out=%b clk=%b", in, out, clk); -// if (out !== 32'b00110110110101010100101101101000) begin -// $error("flipflop failed"); -// $fatal(1); -// end - -// clk = 1; -// # 10 -// $display("FLIPFLOP: in=%b out=%b clk=%b", in, out, clk); -// if (out !== 32'b10101100011011010010001010011001) begin -// $error("flipflop failed"); -// $fatal(1); -// end - -// clk = 0; -// # 10 -// in = 32'b10101011001010001101001000011011; -// # 10 -// $display("FLIPFLOP: in=%b out=%b clk=%b", in, out, clk); -// if (out !== 32'b10101100011011010010001010011001) begin -// $error("flipflop failed"); -// $fatal(1); -// end -// end -endmodule diff --git a/emulator/com/input_devices.v b/emulator/com/input_devices.v new file mode 100644 index 0000000..753f963 --- /dev/null +++ b/emulator/com/input_devices.v @@ -0,0 +1,15 @@ +module InputDevices( + output[31:0] value, + input[15:0] address, + input[31:0] device0_values, + input[31:0] device1_values); + + reg[31:0] _value; + always @(address) begin + case (address) + 0: _value = device0_values; + 1: _value = device1_values; + endcase + end + assign value = _value; +endmodule diff --git a/emulator/com/input_devices_test.v b/emulator/com/input_devices_test.v new file mode 100644 index 0000000..c23a40d --- /dev/null +++ b/emulator/com/input_devices_test.v @@ -0,0 +1,35 @@ +`include "emulator/com/input_devices.v" + +module InputDevices_test; + localparam [31:0] INPUT1 = 32'b11100101111110000100101010110001; + localparam [31:0] INPUT2 = 32'b01011100100011000110101000000001; + + reg[31:0] device0_values = INPUT1; + reg[31:0] device1_values = INPUT2; + reg[15:0] address; + + wire[31:0] value; + + InputDevices dut( + .value(value), + .address(address), + .device0_values(device0_values), + .device1_values(device1_values)); + + initial begin + address = 0; + # 10 + $display("INPUT_DEVICES_TEST: address=%b value=%b", address, value); + if (value !== INPUT1) begin + $error("in failed"); + $fatal(1); + end + address = 1; + # 10 + $display("INPUT_DEVICES_TEST: address=%b value=%b", address, value); + if (value !== INPUT2) begin + $error("in failed"); + $fatal(1); + end + end +endmodule diff --git a/emulator/com/latch.v b/emulator/com/latch.v deleted file mode 100644 index caf3ab5..0000000 --- a/emulator/com/latch.v +++ /dev/null @@ -1,13 +0,0 @@ -// module latch_d(output out, input in, input enable); -// // we want latch to always be on and returing -// // while write when d is active. - -// reg mem; - -// always @(in, enable) begin -// if (enable) begin -// mem <= in; -// end -// end -// assign out = mem; -// endmodule diff --git a/emulator/com/latch_test.v b/emulator/com/latch_test.v deleted file mode 100644 index cecf344..0000000 --- a/emulator/com/latch_test.v +++ /dev/null @@ -1,73 +0,0 @@ -// `include "emulator/lib/latch.v" - -module latch_d_test; -// reg I, ENABLE; -// wire O; - -// latch_d dut(.out(O), .in(I), .enable(ENABLE)); - -// initial begin -// I = 0; -// ENABLE = 1; -// # 10 -// $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); -// if (O !== 0) begin -// $error("latch failed"); -// $fatal(1); -// end - -// I = 1; -// ENABLE = 1; -// # 10 -// $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); -// if (O !== 1) begin -// $error("latch failed"); -// $fatal(1); -// end - -// I = 1; -// ENABLE = 0; -// # 10 -// $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); -// if (O !== 1) begin -// $error("latch failed"); -// $fatal(1); -// end - -// I = 0; -// ENABLE = 0; -// # 10 -// $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); -// if (O !== 1) begin -// $error("latch failed"); -// $fatal(1); -// end - -// I = 1; -// ENABLE = 0; -// # 10 -// $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); -// if (O !== 1) begin -// $error("latch failed"); -// $fatal(1); -// end - -// I = 0; -// ENABLE = 0; -// # 10 -// $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); -// if (O !== 1) begin -// $error("latch failed"); -// $fatal(1); -// end - -// I = 0; -// ENABLE = 1; -// # 10 -// $display("LATCH_TEST: I=%b O=%b ENABLE=%b", I, O, ENABLE); -// if (O !== 0) begin -// $error("latch failed"); -// $fatal(1); -// end -// end -endmodule diff --git a/emulator/com/stage2_test.v b/emulator/com/stage2_test.v index 11f6004..d4acc4f 100644 --- a/emulator/com/stage2_test.v +++ b/emulator/com/stage2_test.v @@ -38,7 +38,7 @@ module stage2_test; mblock_s2 = 0; # 10 $display("STAGE2_TEST: vrw_value=%b vw_value=%b alu_is_zero=%b ram_address=%b", vrw_value, vw_value, alu_is_zero, ram_address); - if (vrw_value !== 99 || ram_address !== 20 || vw_value != 1099 || alu_is_zero != 0) begin + if (vrw_value !== 99 || ram_address !== 20 || vw_value !== 1099 || alu_is_zero !== 0) begin $error("stage2 failed"); $fatal(1); end @@ -46,7 +46,7 @@ module stage2_test; mblock_s2 = 1; # 10 $display("STAGE2_TEST: vrw_value=%b vw_value=%b alu_is_zero=%b ram_address=%b", vrw_value, vw_value, alu_is_zero, ram_address); - if (vrw_value !== 99 || ram_address !== 1000 || vw_value != 1099 || alu_is_zero != 0) begin + if (vrw_value !== 99 || ram_address !== 1000 || vw_value !== 1099 || alu_is_zero !== 0) begin $error("stage2 failed"); $fatal(1); end @@ -54,7 +54,7 @@ module stage2_test; mblock_s2 = 2; # 10 $display("STAGE2_TEST: vrw_value=%b vw_value=%b alu_is_zero=%b ram_address=%b", vrw_value, vw_value, alu_is_zero, ram_address); - if (vrw_value !== 99 || ram_address !== ((10<<8)|20) || vw_value != 1099 || alu_is_zero != 0) begin + if (vrw_value !== 99 || ram_address !== ((10<<8)|20) || vw_value !== 1099 || alu_is_zero !== 0) begin $error("stage2 failed"); $fatal(1); end @@ -62,7 +62,7 @@ module stage2_test; mblock_s2 = 4; # 10 $display("STAGE2_TEST: vrw_value=%b vw_value=%b alu_is_zero=%b", vrw_value, vw_value, alu_is_zero); - if (vrw_value !== 20 || vw_value != 1020 || alu_is_zero != 0) begin + if (vrw_value !== 20 || vw_value !== 1020 || alu_is_zero !== 0) begin $error("stage2 failed"); $fatal(1); end @@ -70,7 +70,7 @@ module stage2_test; mblock_s2 = 6; # 10 $display("STAGE2_TEST: vrw_value=%b vw_value=%b alu_is_zero=%b ram_address=%b", vrw_value, vw_value, alu_is_zero, ram_address); - if (vrw_value !== ((10<<8)|20) || vw_value != (((10<<8)|20)+1000) || alu_is_zero != 0) begin + if (vrw_value !== ((10<<8)|20) || vw_value !== (((10<<8)|20)+1000) || alu_is_zero !== 0) begin $error("stage2 failed"); $fatal(1); end @@ -78,7 +78,7 @@ module stage2_test; mblock_s2 = 7; # 10 $display("STAGE2_TEST: vrw_value=%b vw_value=%b alu_is_zero=%b ram_address=%b", vrw_value, vw_value, alu_is_zero, ram_address); - if (vrw_value !== 84 || vw_value != 1084 || alu_is_zero != 0) begin + if (vrw_value !== 84 || vw_value !== 1084 || alu_is_zero !== 0) begin $error("stage2 failed"); $fatal(1); end @@ -88,7 +88,7 @@ module stage2_test; ram_value = 1000; # 10 $display("STAGE2_TEST: vrw_value=%b vw_value=%b alu_is_zero=%b ram_address=%b", vrw_value, vw_value, alu_is_zero, ram_address); - if (vrw_value !== 1000 || ram_address !== 20 || vw_value != 0 || alu_is_zero != 1) begin + if (vrw_value !== 1000 || ram_address !== 20 || vw_value !== 0 || alu_is_zero !== 1) begin $error("stage2 failed"); $fatal(1); end diff --git a/emulator/com/stage3.v b/emulator/com/stage3.v index e69de29..e7171eb 100644 --- a/emulator/com/stage3.v +++ b/emulator/com/stage3.v @@ -0,0 +1,54 @@ +`include "emulator/com/mux.v" +`include "emulator/com/add_4.v" +`include "emulator/com/alu.v" +`include "emulator/com/decoder.v" + +module STAGE3( + output[31:0] input_devices_value, + output[7:0] input_devices_address, + output[15:0] ram_address, + output[31:0] ram_in, + output ram_is_write, + output output_is_write, + output[15:0] pc_next, + output execute_from_ram_new, + output is_powered_on_new, + input[2:0] mblock_s3, + input[31:0] vrw_value, + input[31:0] vw_value, + input[7:0] vrw_source, + input[15:0] pc, + input is_powered_on, + input flag_last_zero); + + wire[7:0] mblock_s3d; + DECODER_3 dut(.out(mblock_s3d), .in(mblock_s3)); + + assign input_devices_value = vw_value; + assign input_devices_address = vrw_source; + + assign ram_in = vw_value; + MUX_1_16b m1( + .value(ram_address[15:0]), + .A0(vrw_value[15:0]), + .A1({8'b00000000, vrw_source[7:0]}), + .S(mblock_s3d[1])); + or(ram_is_write, mblock_s3d[1], mblock_s3d[3]); + assign output_is_write = mblock_s3d[2]; + + wire is_jump = (mblock_s3d[4] | + (mblock_s3d[5] & flag_last_zero) | + (mblock_s3d[6] & (!flag_last_zero))); + wire[15:0] pc_4; + ADD_4_16b add4( + .out(pc_4), + .in(pc)); + MUX_1_16b m2( + .value(pc_next), + .A0(pc_4), + .A1(vw_value[15:0]), + .S(is_jump)); + + assign is_powered_on_new = is_powered_on & (!mblock_s3d[7]); + +endmodule diff --git a/emulator/com/stage3_test.v b/emulator/com/stage3_test.v new file mode 100644 index 0000000..beeb586 --- /dev/null +++ b/emulator/com/stage3_test.v @@ -0,0 +1,135 @@ +`include "emulator/com/stage3.v" + +module stage3_test; + + wire[31:0] input_devices_value; + wire[7:0] input_devices_address; + wire[15:0] ram_address; + wire[31:0] ram_in; + wire ram_is_write; + wire output_is_write; + wire[15:0] pc_next; + wire execute_from_ram_new; + wire is_powered_on_new; + + reg[2:0] mblock_s3; + reg[31:0] vrw_value; + reg[31:0] vw_value; + reg[7:0] vrw_source; + reg[15:0] pc; + reg is_powered_on; + reg flag_last_zero; + + STAGE3 dut( + .input_devices_value(input_devices_value), + .input_devices_address(input_devices_address), + .ram_address(ram_address), + .ram_in(ram_in), + .ram_is_write(ram_is_write), + .output_is_write(output_is_write), + .pc_next(pc_next), + .execute_from_ram_new(execute_from_ram_new), + .is_powered_on_new(is_powered_on_new), + .mblock_s3(mblock_s3), + .vrw_value(vrw_value), + .vw_value(vw_value), + .vrw_source(vrw_source), + .pc(pc), + .is_powered_on(is_powered_on), + .flag_last_zero(flag_last_zero)); + + initial begin + is_powered_on = 1; + pc = 10; + flag_last_zero = 0; + mblock_s3 = 0; + # 10 + $display("STAGE3_TEST: mblock_s3=%b pc_next=%b write_ram=%b write_out=%b radd=%b rin=%b", mblock_s3, pc_next, ram_is_write, output_is_write, ram_address, ram_in); + if (pc_next!==14 || ram_is_write!==0 || output_is_write!==0) begin + $error("stage3 failed"); + $fatal(1); + end + + mblock_s3 = 1; + vw_value = 99; + vrw_source = 15; + # 10 + $display("STAGE3_TEST: mblock_s3=%b pc_next=%b write_ram=%b write_out=%b radd=%b rin=%b", mblock_s3, pc_next, ram_is_write, output_is_write, ram_address, ram_in); + if (pc_next!==14 || ram_address!==15 || ram_in!==99 || ram_is_write!==1 || output_is_write!==0) begin + $error("stage3 failed"); + $fatal(1); + end + + mblock_s3 = 2; + vw_value = 99; + vrw_source = 15; + # 10 + $display("STAGE3_TEST: mblock_s3=%b pc_next=%b write_ram=%b write_out=%b radd=%b rin=%b", mblock_s3, pc_next, ram_is_write, output_is_write, ram_address, ram_in); + if (pc_next!==14 || input_devices_address!==15 || input_devices_value!==99 || ram_is_write!==0 || output_is_write!==1) begin + $error("stage3 failed"); + $fatal(1); + end + + mblock_s3 = 3; + vw_value = 99; + vrw_value = 97; + vrw_source = 15; + # 10 + $display("STAGE3_TEST: mblock_s3=%b pc_next=%b write_ram=%b write_out=%b radd=%b rin=%b", mblock_s3, pc_next, ram_is_write, output_is_write, ram_address, ram_in); + if (pc_next!==14 || ram_address!==97 || ram_in!==99 || ram_is_write!==1 || output_is_write!==0) begin + $error("stage3 failed"); + $fatal(1); + end + + mblock_s3 = 4; + vw_value = 99; + flag_last_zero = 0; + # 10 + $display("STAGE3_TEST: mblock_s3=%b pc_next=%b write_ram=%b write_out=%b", mblock_s3, pc_next, ram_is_write, output_is_write); + if (pc_next!==99 || ram_is_write!==0 || output_is_write!==0) begin + $error("stage3 failed"); + $fatal(1); + end + + mblock_s3 = 5; + flag_last_zero = 1; + # 10 + $display("STAGE3_TEST: mblock_s3=%b pc_next=%b write_ram=%b write_out=%b", mblock_s3, pc_next, ram_is_write, output_is_write); + if (pc_next!==99 || ram_is_write!==0 || output_is_write!==0) begin + $error("stage3 failed"); + $fatal(1); + end + flag_last_zero = 0; + # 10 + $display("STAGE3_TEST: mblock_s3=%b pc_next=%b write_ram=%b write_out=%b", mblock_s3, pc_next, ram_is_write, output_is_write); + if (pc_next!==14 || ram_is_write!==0 || output_is_write!==0) begin + $error("stage3 failed"); + $fatal(1); + end + + mblock_s3 = 6; + flag_last_zero = 0; + # 10 + $display("STAGE3_TEST: mblock_s3=%b pc_next=%b write_ram=%b write_out=%b", mblock_s3, pc_next, ram_is_write, output_is_write); + if (pc_next!==99 || ram_is_write!==0 || output_is_write!==0) begin + $error("stage3 failed"); + $fatal(1); + end + flag_last_zero = 1; + # 10 + $display("STAGE3_TEST: mblock_s3=%b pc_next=%b write_ram=%b write_out=%b", mblock_s3, pc_next, ram_is_write, output_is_write); + if (pc_next!==14 || ram_is_write!==0 || output_is_write!==0) begin + $error("stage3 failed"); + $fatal(1); + end + + mblock_s3 = 7; + # 10 + $display("STAGE3_TEST: mblock_s3=%b", mblock_s3); + if (is_powered_on_new !== 0) begin + $error("stage3 failed"); + $fatal(1); + end + + end +endmodule diff --git a/emulator/seq/output_devices.v b/emulator/seq/output_devices.v new file mode 100644 index 0000000..132af5a --- /dev/null +++ b/emulator/seq/output_devices.v @@ -0,0 +1,18 @@ +module OutputDevices( + output[31:0] device0_values, + output[31:0] device1_values, + input[15:0] address, + input[31:0] value, + input is_write, + input clk); + + reg[31:0] _data [65535:0]; + always @(negedge clk) begin + // Write are triggered at negedge + if (is_write) begin + _data[address] <= value; + end + end + assign device0_values = _data[0]; + assign device1_values = _data[1]; +endmodule diff --git a/emulator/seq/output_devices_test.v b/emulator/seq/output_devices_test.v new file mode 100644 index 0000000..8ae7a7a --- /dev/null +++ b/emulator/seq/output_devices_test.v @@ -0,0 +1,50 @@ +`include "emulator/seq/output_devices.v" + +module OutputDevices_test; + wire[31:0] device0_values; + wire[31:0] device1_values; + + reg[15:0] address; + reg is_write; + reg clk; + reg[31:0] value; + + OutputDevices dut( + .device0_values(device0_values), + .device1_values(device1_values), + .address(address), + .value(value), + .is_write(is_write), + .clk(clk)); + + + localparam [31:0] INPUT1 = 32'b11100101111110000100101010110001; + localparam [31:0] INPUT2 = 32'b01011100100011000110101000000001; + + initial begin + address = 0; + is_write = 1; + value = INPUT1; + clk = 1; + # 10 + clk = 0; + # 10 + address = 1; + is_write = 1; + value = INPUT2; + clk = 1; + # 10 + clk = 0; + # 10 + address = 0; + is_write = 0; + clk = 1; + # 10 + clk = 0; + $display("OUTPUT_DEVICES_TEST: address=%b is_write=%b value=%b", address, is_write, value); + if (device0_values !== INPUT1 || device1_values !== INPUT2) begin + $error("out failed"); + $fatal(1); + end + end +endmodule From 5c4ca004fc439ba7137cb0a10af8f4cba55ec6de Mon Sep 17 00:00:00 2001 From: Gagan Kumar Date: Sat, 4 Jan 2025 23:19:03 -0800 Subject: [PATCH 4/8] Verilog basic chipset ready --- Makefile | 2 +- emulator/Makefile.mk | 4 +- emulator/chipset.v | 229 +++++++++++++++++++-------- emulator/chipset_test.v | 30 +++- emulator/com/input_devices.v | 2 +- emulator/com/input_devices_test.v | 2 +- emulator/com/mux.v | 4 + emulator/com/rom.v | 18 ++- emulator/com/rom_boot.bin | 28 ++-- emulator/com/rom_test.bin | 20 +-- emulator/com/rom_test.v | 24 +-- emulator/com/stage0_test.v | 6 +- emulator/com/stage3.v | 27 ++-- emulator/com/stage3_test.v | 30 +++- emulator/module/boot_control.v | 17 -- emulator/module/boot_control_test.v | 35 ---- emulator/module/clock_test.v | 36 ----- emulator/module/mblock/mblock.v | 35 ---- emulator/module/mblock/mblock_test.v | 68 -------- emulator/module/mblock/mconst.v | 9 -- emulator/module/mblock/mconst_test.v | 26 --- emulator/module/mblock_mux.v | 56 ------- emulator/module/pc_next.v | 37 ----- emulator/module/stage1or2_store.v | 7 - emulator/{module => seq}/clock.v | 9 +- emulator/seq/clock_test.v | 37 +++++ emulator/seq/output_devices.v | 4 +- emulator/seq/output_devices_test.v | 2 +- 28 files changed, 327 insertions(+), 477 deletions(-) delete mode 100644 emulator/module/boot_control.v delete mode 100644 emulator/module/boot_control_test.v delete mode 100644 emulator/module/clock_test.v delete mode 100644 emulator/module/mblock/mblock.v delete mode 100644 emulator/module/mblock/mblock_test.v delete mode 100644 emulator/module/mblock/mconst.v delete mode 100644 emulator/module/mblock/mconst_test.v delete mode 100644 emulator/module/mblock_mux.v delete mode 100644 emulator/module/pc_next.v delete mode 100644 emulator/module/stage1or2_store.v rename emulator/{module => seq}/clock.v (85%) create mode 100644 emulator/seq/clock_test.v diff --git a/Makefile b/Makefile index 700b339..787a9c9 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ OUTPUT_DIR=output .PHONY: clean test all run_ping_pong all_programs_binary all_programs_resolved -all: all_programs_binary all_programs_resolved +all: all_programs_binary all_programs_resolved verilog_modules clean: rm -rf $(BUILD_DIR) diff --git a/emulator/Makefile.mk b/emulator/Makefile.mk index 1b65703..696cb5b 100644 --- a/emulator/Makefile.mk +++ b/emulator/Makefile.mk @@ -1,11 +1,13 @@ BUILD_EMULATOR = $(BUILD_DIR)/emulator SRC_EMULATOR = $(SRC_DIR)/emulator -.PHONY: test_verilog_modules +.PHONY: verilog_modules test_verilog_modules $(BUILD_EMULATOR)/%_test: $(SRC_EMULATOR)/%_test.v mkdir -p $(dir $@) iverilog -o $@ $^ +verilog_modules: $(patsubst $(SRC_EMULATOR)/%_test.v, $(BUILD_EMULATOR)/%_test, $(shell find $(SRC_EMULATOR) -name '*_test.v')) + test_verilog_modules: $(patsubst $(SRC_EMULATOR)/%_test.v, $(BUILD_EMULATOR)/%_test, $(shell find $(SRC_EMULATOR) -name '*_test.v')) $(foreach test_name, $^, echo "Executing $(test_name)" && ./$(test_name)) diff --git a/emulator/chipset.v b/emulator/chipset.v index 8290a09..cc7a3c8 100644 --- a/emulator/chipset.v +++ b/emulator/chipset.v @@ -1,25 +1,31 @@ -`include "emulator/module/clock.v" -`include "emulator/seq/register.v" +`include "emulator/com/mux.v" `include "emulator/com/stage0.v" `include "emulator/com/stage1.v" - +`include "emulator/com/stage2.v" +`include "emulator/com/stage3.v" +`include "emulator/com/input_devices.v" +`include "emulator/com/rom.v" +`include "emulator/seq/clock.v" +`include "emulator/seq/register.v" +`include "emulator/seq/output_devices.v" +`include "emulator/seq/ram.v" module CHIPSET( - input reset, - input[31:0] ram_value, - output[31:0] ram_address, - output ram_is_write, - ); - - reg is_powered_on; - reg flag_execute_from_ram; - reg flag_last_zero; - reg[15:0] pc, pc_next; + output is_powered_on, + output[15:0] pc, + output flag_execute_from_ram, + input reset_button); + // wire is_powered_on; + // wire flag_execute_from_ram; + wire flag_last_zero; + // wire[15:0] pc; // Clock wire[0:3] clk; + wire[1:0] clk_stage; CLOCK clock( - .clk(clk[0:3])); + .clk(clk[0:3]), + .clk_stage(clk_stage)); // BROM wire[15:0] brom_address; @@ -27,9 +33,9 @@ module CHIPSET( ROM_BOOT brom(.out(brom_value), .address(brom_address)); // RAM - reg ram_is_write; + wire ram_is_write; wire[15:0] ram_address; - reg[31:0] ram_in; + wire[31:0] ram_in; wire[31:0] ram_value; RAM_32bit_16aline ram( .out(ram_value), @@ -38,39 +44,45 @@ module CHIPSET( .is_write(ram_is_write), .clk(clk[3])); - wire[15:0] ram_address_stage0; wire[15:0] ram_address_stage1; + wire[15:0] ram_address_stage2; + wire[15:0] ram_address_stage3; + MUX_2_16b ram_address_selector( + .value(ram_address), + .A0(ram_address_stage0), + .A1(ram_address_stage1), + .A2(ram_address_stage2), + .A3(ram_address_stage3), + .S(clk_stage)); + // TODO: Updated ram_address assign ram_address = ram_address_stage0; // Input Devices wire[7:0] input_devices_address; - reg[31:0] input_devices_value; - // TODO: add devices modules - - // Boot Sequence - // - // When the device have power supply but `is_powered_on` is off. The pc_eval - // forces `program_counter_next` to be 0 and `execute_from_brom` to True. - // If we keep the `is_powered_on` button in off stage for at-least 4 cycles - // then at "stage3 posedge" program_counter should get updated to 0. - // After that for every "stage0 posedge" till is_powered_on is off, - // program_counter:0 along with execute_from_brom:True will be used to pull - // up and execute first instruction from BROM. - // - // Assumption: No stateful IO devices are connected. - // TODO: Implement `execute_from_brom` update implementation. - - // Operates on clk[3] down - BOOT_CONTROL boot_control( - .is_powered_on(is_powered_on), - .pc_next(pc_next), - .flags(flags), - .reset(reset), - .clk(clk[3]), + wire[31:0] input_devices_value; + + InputDevices idevices( + .value(input_devices_value), + .address(input_devices_address) + // .device0_values(2), + // .device1_values(3) ); + // Output Devices + wire[31:0] output_devices_value; + wire[7:0] output_devices_address; + wire output_is_write; + + OutputDevices odevices( + // .device0_values(device0_values), + // .device1_values(device1_values), + .address(output_devices_address), + .value(output_devices_value), + .is_write(output_is_write), + .clk(clk[3])); + // STAGE0 wire[31:0] _instruction_binary; STAGE0 stage0( @@ -84,14 +96,18 @@ module CHIPSET( // STAGE1 wire[31:0] instruction_binary; - REGISTER_up_16b r_ins_bin( - .out(instruction_binary), - .in(_instruction_binary), + REGISTER_up_16b stage1_r0( + .out(instruction_binary[31:16]), + .in(_instruction_binary[31:16]), + .clk(clk[1])); + REGISTER_up_16b stage1_r1( + .out(instruction_binary[15:0]), + .in(_instruction_binary[15:0]), .clk(clk[1])); wire[3:0] mblock_alu_op = instruction_binary[3:0]; - wire[3:0] mblock_s1 = instruction_binary[5:4]; - wire[1:0] mblock_s2 = instruction_binary[8:6]; + wire[1:0] mblock_s1 = instruction_binary[5:4]; + wire[2:0] mblock_s2 = instruction_binary[8:6]; wire[2:0] mblock_s3 = instruction_binary[11:9]; wire[7:0] vrw_source = instruction_binary[23:16]; wire[7:0] vr_source = instruction_binary[31:24]; @@ -108,40 +124,113 @@ module CHIPSET( // STAGE2 wire[31:0] vr_value; - REGISTER_up_16b r_ins_bin( - .out(_vr_value), - .in(_instruction_binary), + REGISTER_up_16b stage2_r0( + .out(vr_value[31:16]), + .in(_vr_value[31:16]), + .clk(clk[2])); + REGISTER_up_16b stage2_r1( + .out(vr_value[15:0]), + .in(_vr_value[15:0]), .clk(clk[2])); - // TODO: Ensure MBLOCK supplies expectations. - // MBLOCK_MUX is expected to fetch MBLOCK based on v0_source and - // instruction_op breakdowns and redirect the value into v0. - - // @stage2 posedge following should freeze. - wire[31:0] vrw_value; - FETCH_AND_STORE stage2( + wire[31:0] _vrw_value; + wire[31:0] _vw_value; + wire _alu_is_zero; + STAGE2 stage2( .vrw_value(vrw_value), - .is_powered_on(is_powered_on), + .vw_value(vw_value), + .ram_address(ram_address_stage2), + .alu_is_zero(alu_is_zero), + .mblock_s2(mblock_s2), .vr_source(vr_source), .vr_value(vr_value), - .vrw_source(vr_source), - .mblock_s2(mblock_s2), - .clk(clk2)); + .vrw_source(vrw_source), + .alu_op(mblock_alu_op), + .pc(pc), + .ram_value(ram_value)); + // STAGE3 + wire[31:0] vrw_value; wire[31:0] vw_value; - ALU alu( - .out(vw_value), - .is_zero(flags[FLAGS_BIT_VW_ZERO]), - .vr_value(vr_value), - .vrw_value(vrw_value), - .op(mblock_alu_op)); + wire alu_is_zero; + REGISTER_up_16b stage3_r0a( + .out(vrw_value[31:16]), + .in(_vrw_value[31:16]), + .clk(clk[3])); + REGISTER_up_16b stage3_r0b( + .out(vrw_value[15:0]), + .in(_vrw_value[15:0]), + .clk(clk[3])); + REGISTER_up_16b stage3_r1a( + .out(vw_value[31:16]), + .in(_vw_value[31:16]), + .clk(clk[3])); + REGISTER_up_16b stage3_r1b( + .out(vw_value[15:0]), + .in(_vw_value[15:0]), + .clk(clk[3])); + wire[14:0] unused0; + REGISTER_up_16b stage3_r2( + .out({unused0, alu_is_zero}), + .in({15'bzzzzzzzzzzzzzzz, _alu_is_zero}), + .clk(clk[3])); - // @stage3 posedge following should freeze. - FETCH_AND_STORE stage2( - .vw_value(vw_value), + + wire execute_from_ram_new; + wire is_powered_on_new; + wire[15:0] pc_next; + + STAGE3 stage3( + .output_devices_value(output_devices_value), + .output_devices_address(output_devices_address), + .ram_address(ram_address_stage3), + .ram_in(ram_in), + .ram_is_write(ram_is_write), + .output_is_write(output_is_write), + .pc_next(pc_next), + .execute_from_ram_new(execute_from_ram_new), + .is_powered_on_new(is_powered_on_new), + .mblock_s3(mblock_s3), .vrw_value(vrw_value), + .vw_value(vw_value), .vrw_source(vrw_source), - .mblock_s3(mblock_s3), - .clk(clk3)); + .pc(pc), + .is_powered_on(is_powered_on), + .flag_last_zero(flag_last_zero), + .execute_from_ram(flag_execute_from_ram), + .reset_button(reset_button)); + + wire[12:0] unused1; + REGISTER_down_16b stage3_r3( + .out({unused1, flag_last_zero, is_powered_on, flag_execute_from_ram}), + .in({13'bzzzzzzzzzzzzz, alu_is_zero, is_powered_on_new, execute_from_ram_new}), + .clk(clk[3])); + + REGISTER_down_16b stage3_r4( + .out(pc), + .in(pc_next), + .clk(clk[3])); + + always @(negedge clk[0]) begin + $display("Stage0: power=%b pc=%b ins=%b eram=%b", + is_powered_on_new, pc, _instruction_binary, flag_execute_from_ram); + end + always @(negedge clk[1]) begin + $display("Stage1: alu=%b s1=%b s2=%b s3=%b vrw_source=%b vr_source=%b", + mblock_alu_op, mblock_s1, mblock_s2, mblock_s3, vrw_source, vr_source); + end + always @(negedge clk[2]) begin + $display("Stage2: vr_value=%b", + vr_value); + end + always @(negedge clk[3]) begin + $display("Stage3: vrw_value=%b, vw_value=%b is_zero=%b", + vrw_value, vw_value, alu_is_zero); + end + always @(posedge clk[0]) begin + $display("StageE: power=%b, f_zero=%b, f_eram=%b pc=%b", + is_powered_on, flag_last_zero, flag_execute_from_ram, pc); + end + endmodule \ No newline at end of file diff --git a/emulator/chipset_test.v b/emulator/chipset_test.v index c0a5449..73d4494 100644 --- a/emulator/chipset_test.v +++ b/emulator/chipset_test.v @@ -1,10 +1,28 @@ -// `include "emulator/chipset.v" +`include "emulator/chipset.v" module chipset_test; - // wire reset; // reset button - // CHIPSET dut(.reset(reset)); + reg reset_button; - // initial begin - // assign reset = 0; // button is never pressed. - // end + wire is_powered_on; + wire flag_execute_from_ram; + wire[15:0] pc; + CHIPSET dut( + .reset_button(reset_button), + .pc(pc), + .is_powered_on(is_powered_on), + .flag_execute_from_ram(flag_execute_from_ram)); + + initial begin + reset_button = 0; + # 80 + reset_button = 1; + # 80 + reset_button = 0; + # 100 + if (reset_button !== 0) begin + $error("chipset failed"); + $fatal(1); + end + $finish(); + end endmodule diff --git a/emulator/com/input_devices.v b/emulator/com/input_devices.v index 753f963..20038e5 100644 --- a/emulator/com/input_devices.v +++ b/emulator/com/input_devices.v @@ -1,6 +1,6 @@ module InputDevices( output[31:0] value, - input[15:0] address, + input[7:0] address, input[31:0] device0_values, input[31:0] device1_values); diff --git a/emulator/com/input_devices_test.v b/emulator/com/input_devices_test.v index c23a40d..d264e9d 100644 --- a/emulator/com/input_devices_test.v +++ b/emulator/com/input_devices_test.v @@ -6,7 +6,7 @@ module InputDevices_test; reg[31:0] device0_values = INPUT1; reg[31:0] device1_values = INPUT2; - reg[15:0] address; + reg[7:0] address; wire[31:0] value; diff --git a/emulator/com/mux.v b/emulator/com/mux.v index 3231256..e52bff3 100644 --- a/emulator/com/mux.v +++ b/emulator/com/mux.v @@ -1,3 +1,6 @@ +`ifndef INCLUDED_MUX +`define INCLUDED_MUX + module MUX_1_16b( output reg [15:0] value, input [15:0] A0, A1, @@ -26,3 +29,4 @@ module MUX_2_16b( endcase end endmodule +`endif \ No newline at end of file diff --git a/emulator/com/rom.v b/emulator/com/rom.v index d8a85af..b902d82 100644 --- a/emulator/com/rom.v +++ b/emulator/com/rom.v @@ -3,17 +3,16 @@ module _ROM_32bit_16aline( input[15:0] address); parameter filename = "/dev/null"; - reg[31:0] buffer[0:1024]; + reg[7:0] buffer[0:1024]; initial begin $readmemb(filename, buffer); $display("ROM: %h", buffer[0]); end - assign out = buffer[address>>2]; - // assign out[7:0] = buffer[address+3]; - // assign out[15:8] = buffer[address+2]; - // assign out[23:16] = buffer[address+1]; - // assign out[31:24] = buffer[address+0]; + assign out[7:0] = buffer[address+0]; + assign out[15:8] = buffer[address+1]; + assign out[23:16] = buffer[address+2]; + assign out[31:24] = buffer[address+3]; endmodule @@ -21,8 +20,11 @@ module ROM_BOOT( output[31:0] out, input[15:0] address); // 4 * 64KB ROM - + reg[15:0] eaddress; + always @(address) begin + eaddress = address - 'h40; + end _ROM_32bit_16aline #(.filename("emulator/com/rom_boot.bin")) dut(.out(out), - .address(address)); + .address(eaddress)); endmodule diff --git a/emulator/com/rom_boot.bin b/emulator/com/rom_boot.bin index cfa321f..4260dcb 100644 --- a/emulator/com/rom_boot.bin +++ b/emulator/com/rom_boot.bin @@ -1,10 +1,18 @@ -10000010101111110111100001010111 -11111100101011001101000010101001 -00000001001101101111110110011101 -11111010111111110100000111111110 -00010110010001100011011100001001 -00111110100111011000101110111011 -10000011101110100011100000011000 -10011111011110101000001000101001 -00110101001001011000000100011101 -01110000101110000000100100011101 +01000100 00000000 00000000 00000000 +00110100 00000010 00000000 00000000 +00000100 00000100 00000010 00000000 +00100100 00000010 00000000 00000010 +00110011 00000010 00000000 00000010 +00110100 00000010 00000100 00000100 +00110100 00000010 00001000 10000000 +00000100 00000100 00000010 00000100 +00100100 00000010 00001100 00000010 +00000100 00000110 00001000 00001100 +00110000 00000010 00001000 00000100 +00110000 00000010 00000100 00000100 +00110001 00000010 00000000 00000001 +10110101 00001101 01011100 00000000 +00110100 00000010 00100000 00000011 +00110010 00000010 00100000 00001000 +00110111 00000010 00100000 11111100 +10110101 00001001 10000000 00000000 diff --git a/emulator/com/rom_test.bin b/emulator/com/rom_test.bin index cfa321f..23296fd 100644 --- a/emulator/com/rom_test.bin +++ b/emulator/com/rom_test.bin @@ -1,10 +1,10 @@ -10000010101111110111100001010111 -11111100101011001101000010101001 -00000001001101101111110110011101 -11111010111111110100000111111110 -00010110010001100011011100001001 -00111110100111011000101110111011 -10000011101110100011100000011000 -10011111011110101000001000101001 -00110101001001011000000100011101 -01110000101110000000100100011101 +10000010 10111111 01111000 01010111 +11111100 10101100 11010000 10101001 +00000001 00110110 11111101 10011101 +11111010 11111111 01000001 11111110 +00010110 01000110 00110111 00001001 +00111110 10011101 10001011 10111011 +10000011 10111010 00111000 00011000 +10011111 01111010 10000010 00101001 +00110101 00100101 10000001 00011101 +01110000 10111000 00001001 00011101 diff --git a/emulator/com/rom_test.v b/emulator/com/rom_test.v index 13c9e27..f9a8f7c 100644 --- a/emulator/com/rom_test.v +++ b/emulator/com/rom_test.v @@ -12,28 +12,14 @@ module rom_test; address = 0; # 10 $display("ROM_TEST: address=%b out=%b", address, out); - if (out !== 32'b10000010101111110111100001010111) begin - $error("rom failed"); - $fatal(1); - end - address = 1*4; - # 10 - $display("ROM_TEST: address=%b out=%b", address, out); - if (out !== 32'b11111100101011001101000010101001) begin + if (out !== 32'b01010111011110001011111110000010) begin $error("rom failed"); $fatal(1); end address = 3*4; # 10 $display("ROM_TEST: address=%b out=%b", address, out); - if (out !== 32'b11111010111111110100000111111110) begin - $error("rom failed"); - $fatal(1); - end - address = 7*4; - # 10 - $display("ROM_TEST: address=%b out=%b", address, out); - if (out !== 32'b10011111011110101000001000101001) begin + if (out !== 32'b11111110010000011111111111111010) begin $error("rom failed"); $fatal(1); end @@ -48,10 +34,10 @@ module rom_boot_test; .address(address)); initial begin - address = 0; + address = 'h40; # 10 - $display("ROM_TEST: address=%b out=%b", address, out); - if (out !== 32'b10000010101111110111100001010111) begin + $display("BROM_TEST: address=%b out=%b", address, out); + if (out !== 32'b00000000000000000000000001000100) begin $error("rom failed"); $fatal(1); end diff --git a/emulator/com/stage0_test.v b/emulator/com/stage0_test.v index 24b7bff..47a8401 100644 --- a/emulator/com/stage0_test.v +++ b/emulator/com/stage0_test.v @@ -35,7 +35,7 @@ module stage0_test; localparam [31:0] INPUT1 = 32'b11100101111110000100101010110001; initial begin - pc = 16'b0000000000000100; + pc = 16'b0000000001000100; // 0x44 ram_is_write = 1; ram_in = INPUT1; clk = 1; @@ -44,8 +44,8 @@ module stage0_test; # 10 execute_from_ram = 0; # 10 - $display("STAGE0_TEST: pc=%b out=%b", pc, instruction_binary); - if (instruction_binary !== 32'b11111100101011001101000010101001) begin + $display("STAGE0_TEST: pc=%b out=%b rom_address=%b rom_value=%b", pc, instruction_binary, rom_address, rom_value); + if (instruction_binary !== 32'b00000000000000000000001000110100) begin $error("stage0 failed"); $fatal(1); end diff --git a/emulator/com/stage3.v b/emulator/com/stage3.v index e7171eb..e9afae7 100644 --- a/emulator/com/stage3.v +++ b/emulator/com/stage3.v @@ -1,11 +1,12 @@ `include "emulator/com/mux.v" `include "emulator/com/add_4.v" -`include "emulator/com/alu.v" `include "emulator/com/decoder.v" +`define BOOTSEQUENCE_ORG 16'b0000000001000100 + module STAGE3( - output[31:0] input_devices_value, - output[7:0] input_devices_address, + output[31:0] output_devices_value, + output[7:0] output_devices_address, output[15:0] ram_address, output[31:0] ram_in, output ram_is_write, @@ -19,13 +20,15 @@ module STAGE3( input[7:0] vrw_source, input[15:0] pc, input is_powered_on, - input flag_last_zero); + input flag_last_zero, + input execute_from_ram, + input reset_button); wire[7:0] mblock_s3d; DECODER_3 dut(.out(mblock_s3d), .in(mblock_s3)); - assign input_devices_value = vw_value; - assign input_devices_address = vrw_source; + assign output_devices_value = vw_value; + assign output_devices_address = vrw_source; assign ram_in = vw_value; MUX_1_16b m1( @@ -43,12 +46,18 @@ module STAGE3( ADD_4_16b add4( .out(pc_4), .in(pc)); + wire[15:0] _pc_next; MUX_1_16b m2( - .value(pc_next), + .value(_pc_next), .A0(pc_4), .A1(vw_value[15:0]), .S(is_jump)); + MUX_1_16b m3( + .value(pc_next), + .A0(_pc_next), + .A1(`BOOTSEQUENCE_ORG), + .S(reset_button)); - assign is_powered_on_new = is_powered_on & (!mblock_s3d[7]); - + assign is_powered_on_new = (is_powered_on & (!mblock_s3d[7])) | reset_button; + assign execute_from_ram_new = execute_from_ram & (!reset_button); endmodule diff --git a/emulator/com/stage3_test.v b/emulator/com/stage3_test.v index beeb586..2fe2258 100644 --- a/emulator/com/stage3_test.v +++ b/emulator/com/stage3_test.v @@ -1,9 +1,8 @@ `include "emulator/com/stage3.v" module stage3_test; - - wire[31:0] input_devices_value; - wire[7:0] input_devices_address; + wire[31:0] output_devices_value; + wire[7:0] output_devices_address; wire[15:0] ram_address; wire[31:0] ram_in; wire ram_is_write; @@ -19,10 +18,12 @@ module stage3_test; reg[15:0] pc; reg is_powered_on; reg flag_last_zero; + reg execute_from_ram; + reg reset_button; STAGE3 dut( - .input_devices_value(input_devices_value), - .input_devices_address(input_devices_address), + .output_devices_value(output_devices_value), + .output_devices_address(output_devices_address), .ram_address(ram_address), .ram_in(ram_in), .ram_is_write(ram_is_write), @@ -36,10 +37,14 @@ module stage3_test; .vrw_source(vrw_source), .pc(pc), .is_powered_on(is_powered_on), - .flag_last_zero(flag_last_zero)); + .flag_last_zero(flag_last_zero), + .execute_from_ram(execute_from_ram), + .reset_button(reset_button)); initial begin + reset_button = 0; is_powered_on = 1; + execute_from_ram = 1; pc = 10; flag_last_zero = 0; mblock_s3 = 0; @@ -65,7 +70,7 @@ module stage3_test; vrw_source = 15; # 10 $display("STAGE3_TEST: mblock_s3=%b pc_next=%b write_ram=%b write_out=%b radd=%b rin=%b", mblock_s3, pc_next, ram_is_write, output_is_write, ram_address, ram_in); - if (pc_next!==14 || input_devices_address!==15 || input_devices_value!==99 || ram_is_write!==0 || output_is_write!==1) begin + if (pc_next!==14 || output_devices_address!==15 || output_devices_value!==99 || ram_is_write!==0 || output_is_write!==1) begin $error("stage3 failed"); $fatal(1); end @@ -126,10 +131,19 @@ module stage3_test; mblock_s3 = 7; # 10 $display("STAGE3_TEST: mblock_s3=%b", mblock_s3); - if (is_powered_on_new !== 0) begin + if (is_powered_on_new !== 0 || execute_from_ram_new !== 1) begin $error("stage3 failed"); $fatal(1); end + mblock_s3 = 0; + reset_button = 1; + is_powered_on = 0; + # 10 + $display("STAGE3_TEST: mblock_s3=%b pc_next=%b", mblock_s3, pc_next); + if (pc_next !== 'h44 || is_powered_on_new !== 1 || execute_from_ram_new !== 0) begin + $error("stage3 failed"); + $fatal(1); + end end endmodule diff --git a/emulator/module/boot_control.v b/emulator/module/boot_control.v deleted file mode 100644 index 7e18a8c..0000000 --- a/emulator/module/boot_control.v +++ /dev/null @@ -1,17 +0,0 @@ -`define BOOTSEQUENCE_ORG 'h44 - -module BOOT_CONTROL( - output reg is_powered_on, - output reg [15:0] pc_next, - output reg [1:0] flags, - input reset, - input clk); - - always @(negedge clk) begin - if(reset) begin - flags <= 2'b00; - pc_next <= 'h44;// BOOTSEQUENCE_ORG; - is_powered_on <= 1; - end - end -endmodule \ No newline at end of file diff --git a/emulator/module/boot_control_test.v b/emulator/module/boot_control_test.v deleted file mode 100644 index 874771d..0000000 --- a/emulator/module/boot_control_test.v +++ /dev/null @@ -1,35 +0,0 @@ -`include "emulator/module/boot_control.v" - -module boot_control_test; - // reg reset; - - // reg is_powered_on; - // reg[15:0] pc_next; - // reg[1:0] flags; - // reg clk; - - // BOOT_CONTROL dut( - // .is_powered_on(is_powered_on), - // .pc_next(pc_next), - // .flags(flags), - // .reset(reset), - // .clk(clk)); - - // initial begin - // # 5 - // clk = 1; - // # 1 - // reset = 1; - // # 1 - // clk = 0; - // # 1 - // reset = 0; - // $display("BOOT_CONTROL: is_powered_on=%b, pc_next=%b, flags: %b", - // is_powered_on, pc_next, flags); - // if (is_powered_on !== 0 || pc_next !== 'h80 || flags !== 0) begin - // $error("BOOT_CONTROL failed"); - // $fatal(1); - // end - // end -endmodule - diff --git a/emulator/module/clock_test.v b/emulator/module/clock_test.v deleted file mode 100644 index e42d06e..0000000 --- a/emulator/module/clock_test.v +++ /dev/null @@ -1,36 +0,0 @@ -`include "emulator/module/clock.v" - -module clock_test; - wire[0:3] clk; - CLOCK dut(.clk(clk[0:3])); - - initial begin - # 80 - # 15 - $display("CLK: clk=%b", clk); - if (clk !== 4'b1000) begin - $error("clock failed"); - $fatal(1); - end - # 20 - $display("CLK: clk=%b", clk); - if (clk !== 4'b0100) begin - $error("clock failed"); - $fatal(1); - end - # 20 - $display("CLK: clk=%b", clk); - if (clk !== 4'b0010) begin - $error("clock failed"); - $fatal(1); - end - # 20 - $display("CLK: clk=%b", clk); - if (clk !== 4'b0001) begin - $error("clock failed"); - $fatal(1); - end - $finish(); - end -endmodule - diff --git a/emulator/module/mblock/mblock.v b/emulator/module/mblock/mblock.v deleted file mode 100644 index 75c8c89..0000000 --- a/emulator/module/mblock/mblock.v +++ /dev/null @@ -1,35 +0,0 @@ -// `include "emulator/module/mblock/mconst.v" -// `include "emulator/module/mblock/ram.v" -// `include "emulator/module/mblock/rom.v" -// `include "emulator/lib//mux.v" - -// module MBLOCK(output[31:0] out, -// input[1:0] selector, -// input[31:0] in, -// input[15:0] address, -// input is_write); - -// // TODO: How can be careful about accidental write occurance -// // due to race between how the values are propogated? - -// wire[31:0] out0, out1, out2, out3; - -// ROM_BOOT romb(.out(out0), -// .address(address)); - -// RAM_32bit_16aline ram(.out(out1), -// .in(in), -// .address(address), -// .is_write(is_write & ~selector[1] & selector[0])); - -// // selector 10 is reserved for IO - -// MCONST mconst(.out(out3), -// .in(address)); - -// MUX_8_2 m0(.value(out[ 7: 0]), .A(out0[ 7: 0]), .B(out1[ 7: 0]), .D(out3[ 7: 0]), .S(selector[1:0])); -// MUX_8_2 m1(.value(out[15: 8]), .A(out0[15: 8]), .B(out1[15: 8]), .D(out3[15: 8]), .S(selector[1:0])); -// MUX_8_2 m2(.value(out[23:16]), .A(out0[23:16]), .B(out1[23:16]), .D(out3[23:16]), .S(selector[1:0])); -// MUX_8_2 m3(.value(out[31:24]), .A(out0[31:24]), .B(out1[31:24]), .D(out3[31:24]), .S(selector[1:0])); - -// endmodule diff --git a/emulator/module/mblock/mblock_test.v b/emulator/module/mblock/mblock_test.v deleted file mode 100644 index 70cc975..0000000 --- a/emulator/module/mblock/mblock_test.v +++ /dev/null @@ -1,68 +0,0 @@ -`include "emulator/module/mblock/mblock.v" - -module BLOCK_32bit_16aline_test; - // wire[31:0] out; - // reg[15:0] address; - // reg[1:0] selector; - // reg[31:0] in; - // reg is_write; - - // localparam [31:0] INPUT16z = 16'bzzzzzzzzzzzzzzzz; - // localparam [31:0] INPUT32z = 32'bzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz; - // localparam [31:0] INPUT1 = 32'b11100101111110000100101010110001; - // localparam [31:0] INPUT2 = 32'b01011100100011000110101000000001; - - // MBLOCK dut(.out(out), - // .selector(selector), - // .in(in), - // .address(address), - // .is_write(is_write)); - - // initial begin - // selector = 2'b01; // RAM write - // address = 16'b1011100000111010; - // in = INPUT1; - // # 10 - // is_write = 1; - // # 10 - // $display("MBLOCK: RAM_TEST: address=%b is_write=%b in=%b out=%b", address, is_write, in, out); - // if (out !== INPUT1) begin - // $error("mblock failed"); - // $fatal(1); - // end - - // selector = 2'b00; // ROM_BOOT - // address = 16'b0000000000000001; - // is_write = 1'bz; - // in = INPUT32z; - // # 10 - // $display("MBLOCK: ROM_TEST: address=%b is_write=%b in=%b out=%b", address, is_write, in, out); - // if (out !== 32'b11111100101011001101000010101001) begin - // $error("mblock failed"); - // $fatal(1); - // end - - // selector = 2'b11; // MCONST - // address = 16'b0001100100111101; - // is_write = 1'bz; - // in = INPUT32z; - // # 10 - // $display("MBLOCK: MCONST: address=%b is_write=%b in=%b out=%b", address, is_write, in, out); - // if (out !== 32'b00000000000000000001100100111101) begin - // $error("mblock failed"); - // $fatal(1); - // end - - // selector = 2'b01; // RAM read - // address = 16'b1011100000111010; - // is_write = 0; - // # 10 - // in = INPUT32z; - // # 10 - // $display("MBLOCK: RAM_TEST: address=%b is_write=%b in=%b out=%b", address, is_write, in, out); - // if (out !== INPUT1) begin - // $error("mblock failed"); - // $fatal(1); - // end - // end -endmodule diff --git a/emulator/module/mblock/mconst.v b/emulator/module/mblock/mconst.v deleted file mode 100644 index d54664d..0000000 --- a/emulator/module/mblock/mconst.v +++ /dev/null @@ -1,9 +0,0 @@ -// module MCONST( -// output[31:0] out, -// input[15:0] in); -// // returns constant value - -// assign out[31:16] = 16'b0000000000000000; -// assign out[15:0] = in[15:0]; - -// endmodule diff --git a/emulator/module/mblock/mconst_test.v b/emulator/module/mblock/mconst_test.v deleted file mode 100644 index 6aaf80e..0000000 --- a/emulator/module/mblock/mconst_test.v +++ /dev/null @@ -1,26 +0,0 @@ -// `include "emulator/module/mblock/mconst.v" - -module MCONST_test; -// reg[31:0] in; -// wire[31:0] out; - -// MCONST dut(.out(out), -// .in(in)); - -// initial begin -// in = 16'b0010111100010010; -// # 10 -// $display("MCONST_TEST: in=%b out=%b", in, out); -// if (out !== 32'b00000000000000000010111100010010) begin -// $error("mconst failed"); -// $fatal(1); -// end -// in = 16'b1001011000011000; -// # 10 -// $display("MCONST_TEST: in=%b out=%b", in, out); -// if (out !== 32'b00000000000000001001011000011000) begin -// $error("mconst failed"); -// $fatal(1); -// end -// end -endmodule diff --git a/emulator/module/mblock_mux.v b/emulator/module/mblock_mux.v deleted file mode 100644 index 1154d18..0000000 --- a/emulator/module/mblock_mux.v +++ /dev/null @@ -1,56 +0,0 @@ -// module MBLOCK_MUX(output[31:0] mblock_address, -// output[1:0] mblock_selector, - -// input execute_from_brom, -// input[0:3] is_stage, -// input[15:0] address0, // program_counter -// input[15:0] address1, // v0_source -// input[15:0] address2, // v1_source -// input[15:0] address3, // v2_source -// input[3:0] is_write, -// ); - -// // TODO Starts -// // TODO: We should support I/O and const in mblock_selector -// // during stage0, before stage0 posedge -// // mblock_selector[0] = execute_from_brom; -// // mblock_selector[1] = 0; -// // after stage0 posedge -// // mblock_selector = will come from instruction_op -// // after stage1 posedge -// // mblock_selector = will come from instruction_op -// // after stage2 posedge -// // mblock_selector = will come from instruction_op -// // Challenge: How will we will fit, 3 mux_selector, ALU_OP and -// // instructions classes all within 1 byte... -// // TODO Ends - -// always @(is_stage, is_write, address0, address1, address2, address3) -// begin -// if (is_stage == 2'b00) -// begin -// // Active RAM or BROM based upon $execute_from_brom. -// assign mblock_selector[1:0] = {0, execute_from_brom}; -// end -// else if (is_stage == 2'b01) -// begin -// // TODO: mblock_selector compute from instruction_op -// end -// else if (is_stage == 2'b10) -// begin -// // TODO: mblock_selector compute from instruction_op -// end -// else -// begin -// // TODO: mblock_selector compute from instruction_op -// end -// else - -// end - -// MUX_8_2 m0(.value(mblock_address[ 7: 0]), .A(address0[ 7: 0]), .B(address1[ 7: 0]), ,C(address2[ 7: 0]), .D(address3[ 7: 0]), .S(mblock_selector[1:0])); -// MUX_8_2 m1(.value(mblock_address[15: 8]), .A(address0[15: 8]), .B(address1[15: 8]), ,C(address2[15: 8]), .D(address3[15: 8]), .S(mblock_selector[1:0])); -// MUX_8_2 m2(.value(mblock_address[23:16]), .A(address0[23:16]), .B(address1[23:16]), ,C(address2[23:16]), .D(address3[23:16]), .S(mblock_selector[1:0])); -// MUX_8_2 m3(.value(mblock_address[31:24]), .A(address0[31:24]), .B(address1[31:24]), ,C(address2[31:24]), .D(address3[31:24]), .S(mblock_selector[1:0])); - -// endmodule diff --git a/emulator/module/pc_next.v b/emulator/module/pc_next.v deleted file mode 100644 index 97f60fc..0000000 --- a/emulator/module/pc_next.v +++ /dev/null @@ -1,37 +0,0 @@ -module PC_NEXT( - inout [15:0] program_counter, - input is_powered_on, - input clk); - - // TODO: we should support jmp like instructions. - - wire[15:0] program_counter_plus_one; - wire[15:0] program_counter_next; - - ADDER pc_adder( - .out(program_counter_plus_one), - .in0(program_counter), - .in1(1)); - - AND(program_counter_next[00], program_counter_plus_one[00], is_powered_on); - AND(program_counter_next[01], program_counter_plus_one[01], is_powered_on); - AND(program_counter_next[02], program_counter_plus_one[02], is_powered_on); - AND(program_counter_next[03], program_counter_plus_one[03], is_powered_on); - AND(program_counter_next[04], program_counter_plus_one[04], is_powered_on); - AND(program_counter_next[05], program_counter_plus_one[05], is_powered_on); - AND(program_counter_next[06], program_counter_plus_one[06], is_powered_on); - AND(program_counter_next[07], program_counter_plus_one[07], is_powered_on); - AND(program_counter_next[08], program_counter_plus_one[08], is_powered_on); - AND(program_counter_next[09], program_counter_plus_one[09], is_powered_on); - AND(program_counter_next[10], program_counter_plus_one[10], is_powered_on); - AND(program_counter_next[11], program_counter_plus_one[11], is_powered_on); - AND(program_counter_next[12], program_counter_plus_one[12], is_powered_on); - AND(program_counter_next[13], program_counter_plus_one[13], is_powered_on); - AND(program_counter_next[14], program_counter_plus_one[14], is_powered_on); - AND(program_counter_next[15], program_counter_plus_one[15], is_powered_on); - - flipflop16 pc( - .out(program_counter), - .in(program_counter_next), - .clk(clk)); -endmodule diff --git a/emulator/module/stage1or2_store.v b/emulator/module/stage1or2_store.v deleted file mode 100644 index f36ea0e..0000000 --- a/emulator/module/stage1or2_store.v +++ /dev/null @@ -1,7 +0,0 @@ -module FETCH_AND_STORE(output[31:0] value, - input[31:0] in, - input clk); - - flipflop32 f(.out(value[31:0]), .in(in[31:0]), .clk(clk)); - -endmodule diff --git a/emulator/module/clock.v b/emulator/seq/clock.v similarity index 85% rename from emulator/module/clock.v rename to emulator/seq/clock.v index 1a877a9..44c1d1e 100644 --- a/emulator/module/clock.v +++ b/emulator/seq/clock.v @@ -1,5 +1,6 @@ module CLOCK( - output[0:3] clk); + output[0:3] clk, + output[1:0] clk_stage); // stages: // The architecture splits instructions execution in 4 stages. @@ -23,6 +24,7 @@ module CLOCK( reg hw_clk; reg[0:3] _clk; + reg[1:0] _clk_stage; integer _count; initial begin @@ -37,15 +39,19 @@ module CLOCK( _count <= _count + 1; if (_count == 0) begin assign _clk[0] = 1; + assign _clk_stage = 0; end if (_count == 1) begin assign _clk[1] = 1; + assign _clk_stage = 1; end if (_count == 2) begin assign _clk[2] = 1; + assign _clk_stage = 2; end if (_count == 3) begin assign _clk[3] = 1; + assign _clk_stage = 3; _count <= 0; end end @@ -55,4 +61,5 @@ module CLOCK( end assign clk[0:3] = _clk[0:3]; + assign clk_stage = _clk_stage; endmodule diff --git a/emulator/seq/clock_test.v b/emulator/seq/clock_test.v new file mode 100644 index 0000000..319e766 --- /dev/null +++ b/emulator/seq/clock_test.v @@ -0,0 +1,37 @@ +`include "emulator/seq/clock.v" + +module clock_test; + wire[0:3] clk; + wire[1:0] clk_stage; + CLOCK dut(.clk(clk[0:3]), .clk_stage(clk_stage)); + + initial begin + # 80 + # 15 + $display("CLK: clk=%b, clk_stage=%b", clk, clk_stage); + if (clk !== 4'b1000 || clk_stage !== 0) begin + $error("clock failed"); + $fatal(1); + end + # 20 + $display("CLK: clk=%b, clk_stage=%b", clk, clk_stage); + if (clk !== 4'b0100 || clk_stage !== 1) begin + $error("clock failed"); + $fatal(1); + end + # 20 + $display("CLK: clk=%b, clk_stage=%b", clk, clk_stage); + if (clk !== 4'b0010 || clk_stage !== 2) begin + $error("clock failed"); + $fatal(1); + end + # 20 + $display("CLK: clk=%b, clk_stage=%b", clk, clk_stage); + if (clk !== 4'b0001 || clk_stage !== 3) begin + $error("clock failed"); + $fatal(1); + end + $finish(); + end +endmodule + diff --git a/emulator/seq/output_devices.v b/emulator/seq/output_devices.v index 132af5a..02d7f39 100644 --- a/emulator/seq/output_devices.v +++ b/emulator/seq/output_devices.v @@ -1,12 +1,12 @@ module OutputDevices( output[31:0] device0_values, output[31:0] device1_values, - input[15:0] address, + input[7:0] address, input[31:0] value, input is_write, input clk); - reg[31:0] _data [65535:0]; + reg[31:0] _data [255:0]; always @(negedge clk) begin // Write are triggered at negedge if (is_write) begin diff --git a/emulator/seq/output_devices_test.v b/emulator/seq/output_devices_test.v index 8ae7a7a..20dd67e 100644 --- a/emulator/seq/output_devices_test.v +++ b/emulator/seq/output_devices_test.v @@ -4,7 +4,7 @@ module OutputDevices_test; wire[31:0] device0_values; wire[31:0] device1_values; - reg[15:0] address; + reg[7:0] address; reg is_write; reg clk; reg[31:0] value; From 6a45bedbabe888b9ff332bec747d804d320b5a2c Mon Sep 17 00:00:00 2001 From: Gagan Kumar Date: Sun, 5 Jan 2025 21:37:42 -0800 Subject: [PATCH 5/8] Verilog jmp to program from bootsequence complete --- emulator/chipset.v | 101 +++++---- emulator/chipset_test.v | 2 +- emulator/com/alu.v | 6 +- emulator/com/alu_test.v | 12 +- emulator/com/input_devices.v | 15 -- emulator/com/input_devices_test.v | 35 ---- emulator/com/mux.v | 4 +- emulator/com/rom.v | 20 +- emulator/com/stage1.v | 4 +- emulator/com/stage1_test.v | 8 +- emulator/com/stage3.v | 6 +- emulator/com/stage3_test.v | 6 +- emulator/seq/io_devices.v | 33 +++ emulator/seq/io_devices_test.v | 44 ++++ emulator/seq/output_devices.v | 18 -- emulator/seq/output_devices_test.v | 50 ----- emulator/seq/ram.v | 3 +- output/programs/3_led_switch.bin | 4 + output/programs/3_led_switch_resolved.asm | 4 + output/programs/boot_sequence.bin | 18 ++ output/programs/boot_sequence_resolved.asm | 18 ++ output/programs/ping_pong.bin | 195 +++++++++++++++++ output/programs/ping_pong_resolved.asm | 231 +++++++++++++++++++++ planner/memory.py | 1 + 24 files changed, 640 insertions(+), 198 deletions(-) delete mode 100644 emulator/com/input_devices.v delete mode 100644 emulator/com/input_devices_test.v create mode 100644 emulator/seq/io_devices.v create mode 100644 emulator/seq/io_devices_test.v delete mode 100644 emulator/seq/output_devices.v delete mode 100644 emulator/seq/output_devices_test.v create mode 100644 output/programs/3_led_switch.bin create mode 100644 output/programs/3_led_switch_resolved.asm create mode 100644 output/programs/boot_sequence.bin create mode 100644 output/programs/boot_sequence_resolved.asm create mode 100644 output/programs/ping_pong.bin create mode 100644 output/programs/ping_pong_resolved.asm diff --git a/emulator/chipset.v b/emulator/chipset.v index cc7a3c8..df9f104 100644 --- a/emulator/chipset.v +++ b/emulator/chipset.v @@ -3,11 +3,10 @@ `include "emulator/com/stage1.v" `include "emulator/com/stage2.v" `include "emulator/com/stage3.v" -`include "emulator/com/input_devices.v" `include "emulator/com/rom.v" `include "emulator/seq/clock.v" `include "emulator/seq/register.v" -`include "emulator/seq/output_devices.v" +`include "emulator/seq/io_devices.v" `include "emulator/seq/ram.v" module CHIPSET( @@ -30,7 +29,8 @@ module CHIPSET( // BROM wire[15:0] brom_address; wire[31:0] brom_value; - ROM_BOOT brom(.out(brom_value), .address(brom_address)); + ROM_BOOT #(.filename("output/programs/boot_sequence.bin")) + brom(.out(brom_value), .address(brom_address)); // RAM wire ram_is_write; @@ -55,34 +55,33 @@ module CHIPSET( .A2(ram_address_stage2), .A3(ram_address_stage3), .S(clk_stage)); - - // TODO: Updated ram_address - assign ram_address = ram_address_stage0; - - // Input Devices - wire[7:0] input_devices_address; + // always @(ram_address, ram_address_stage0, ram_address_stage1, ram_address_stage2, ram_address_stage3, clk_stage) + // begin + // $display("add:%b, s0:%b, s1:%b, s2:%b, s3:%b, stage:%b", ram_address, ram_address_stage0, ram_address_stage1, ram_address_stage2, ram_address_stage3, clk_stage); + // end + + // IO Devices + wire[7:0] io_device_id_s1; + wire[7:0] io_device_id_s3; + wire[7:0] io_device_id; wire[31:0] input_devices_value; - - InputDevices idevices( - .value(input_devices_value), - .address(input_devices_address) - // .device0_values(2), - // .device1_values(3) - ); - - // Output Devices wire[31:0] output_devices_value; - wire[7:0] output_devices_address; wire output_is_write; - OutputDevices odevices( - // .device0_values(device0_values), - // .device1_values(device1_values), - .address(output_devices_address), - .value(output_devices_value), + IODevices io_devices( + .value_out(input_devices_value), + .device_id(io_device_id), + .value_in(output_devices_value), .is_write(output_is_write), .clk(clk[3])); + wire[7:0] unused2; + MUX_1_16b io_device_id_selector( + .value({unused2, io_device_id}), + .A0({unused2, io_device_id_s1}), + .A1({unused2, io_device_id_s3}), + .S(clk_stage[1])); + // STAGE0 wire[31:0] _instruction_binary; STAGE0 stage0( @@ -115,8 +114,8 @@ module CHIPSET( wire[31:0] _vr_value; STAGE1 stage1( .vr_value(_vr_value), - .input_devices_address(input_devices_address), - .ram_address(ram_address), + .io_device_id(io_device_id_s1), + .ram_address(ram_address_stage1), .mblock_s1(mblock_s1), .vr_source(vr_source), .input_devices_value(input_devices_value), @@ -137,10 +136,10 @@ module CHIPSET( wire[31:0] _vw_value; wire _alu_is_zero; STAGE2 stage2( - .vrw_value(vrw_value), - .vw_value(vw_value), + .vrw_value(_vrw_value), + .vw_value(_vw_value), .ram_address(ram_address_stage2), - .alu_is_zero(alu_is_zero), + .alu_is_zero(_alu_is_zero), .mblock_s2(mblock_s2), .vr_source(vr_source), .vr_value(vr_value), @@ -182,7 +181,7 @@ module CHIPSET( STAGE3 stage3( .output_devices_value(output_devices_value), - .output_devices_address(output_devices_address), + .io_device_id(io_device_id_s3), .ram_address(ram_address_stage3), .ram_in(ram_in), .ram_is_write(ram_is_write), @@ -211,26 +210,24 @@ module CHIPSET( .in(pc_next), .clk(clk[3])); - always @(negedge clk[0]) begin - $display("Stage0: power=%b pc=%b ins=%b eram=%b", - is_powered_on_new, pc, _instruction_binary, flag_execute_from_ram); - end - always @(negedge clk[1]) begin - $display("Stage1: alu=%b s1=%b s2=%b s3=%b vrw_source=%b vr_source=%b", - mblock_alu_op, mblock_s1, mblock_s2, mblock_s3, vrw_source, vr_source); - end - always @(negedge clk[2]) begin - $display("Stage2: vr_value=%b", - vr_value); - end - always @(negedge clk[3]) begin - $display("Stage3: vrw_value=%b, vw_value=%b is_zero=%b", - vrw_value, vw_value, alu_is_zero); - end - always @(posedge clk[0]) begin - $display("StageE: power=%b, f_zero=%b, f_eram=%b pc=%b", - is_powered_on, flag_last_zero, flag_execute_from_ram, pc); - end - - + // always @(negedge clk[0]) begin + // $display("Stage0: power=%b pc=%x ins=%b eram=%b", + // is_powered_on_new, pc, _instruction_binary, flag_execute_from_ram); + // end + // always @(negedge clk[1]) begin + // $display("Stage1: alu=%b s1=%b s2=%b s3=%b vrw_source=%x vr_source=%x", + // mblock_alu_op, mblock_s1, mblock_s2, mblock_s3, vrw_source, vr_source); + // end + // always @(negedge clk[2]) begin + // $display("Stage2: vr_value=%x", + // vr_value); + // end + // always @(negedge clk[3]) begin + // $display("Stage3: vrw_value=%x, vw_value=%x is_zero=%b", + // vrw_value, vw_value, alu_is_zero); + // end + // always @(posedge clk[0]) begin + // $display("StageE: power=%b, f_zero=%b, f_eram=%b pc=%x write_ram=%b wrire_io=%b", + // is_powered_on, flag_last_zero, flag_execute_from_ram, pc, ram_is_write, output_is_write); + // end endmodule \ No newline at end of file diff --git a/emulator/chipset_test.v b/emulator/chipset_test.v index 73d4494..172febd 100644 --- a/emulator/chipset_test.v +++ b/emulator/chipset_test.v @@ -18,7 +18,7 @@ module chipset_test; reset_button = 1; # 80 reset_button = 0; - # 100 + # 200000 if (reset_button !== 0) begin $error("chipset failed"); $fatal(1); diff --git a/emulator/com/alu.v b/emulator/com/alu.v index 8f4bb7f..760c132 100644 --- a/emulator/com/alu.v +++ b/emulator/com/alu.v @@ -13,9 +13,9 @@ module ALU ( always @(op, in_r, in_rw) begin case(op) 4'b0000: mem = in_r+in_rw; - 4'b0001: mem = in_r-in_rw; - 4'b0010: mem = (in_r<>in_rw); + 4'b0001: mem = in_rw-in_r; + 4'b0010: mem = (in_rw<>in_r); 4'b0100: mem = (in_r); 4'b0101: mem = (in_rw); 4'b0110: mem = (in_r&in_rw); diff --git a/emulator/com/alu_test.v b/emulator/com/alu_test.v index 245ab11..5e2985a 100644 --- a/emulator/com/alu_test.v +++ b/emulator/com/alu_test.v @@ -27,8 +27,8 @@ module alu_test; // SUB op = 4'b0001; - in_r = 2536; - in_rw = 113; + in_r = 113; + in_rw = 2536; # 10 $display("ALU_TEST: op=%b in_r=%b in_rw=%b", op, in_r, in_rw); if (out !== 2423 || is_zero !== 0) begin @@ -38,8 +38,8 @@ module alu_test; // LSR op = 4'b0010; - in_r = 2536; - in_rw = 2; + in_r = 2; + in_rw = 2536; # 10 $display("ALU_TEST: op=%b in_r=%b in_rw=%b", op, in_r, in_rw); if (out !== 10144 || is_zero !== 0) begin @@ -49,8 +49,8 @@ module alu_test; // RSR op = 4'b0011; - in_r = 2536; - in_rw = 4; + in_r = 4; + in_rw = 2536; # 10 $display("ALU_TEST: op=%b in_r=%b in_rw=%b", op, in_r, in_rw); if (out !== 158 || is_zero !== 0) begin diff --git a/emulator/com/input_devices.v b/emulator/com/input_devices.v deleted file mode 100644 index 20038e5..0000000 --- a/emulator/com/input_devices.v +++ /dev/null @@ -1,15 +0,0 @@ -module InputDevices( - output[31:0] value, - input[7:0] address, - input[31:0] device0_values, - input[31:0] device1_values); - - reg[31:0] _value; - always @(address) begin - case (address) - 0: _value = device0_values; - 1: _value = device1_values; - endcase - end - assign value = _value; -endmodule diff --git a/emulator/com/input_devices_test.v b/emulator/com/input_devices_test.v deleted file mode 100644 index d264e9d..0000000 --- a/emulator/com/input_devices_test.v +++ /dev/null @@ -1,35 +0,0 @@ -`include "emulator/com/input_devices.v" - -module InputDevices_test; - localparam [31:0] INPUT1 = 32'b11100101111110000100101010110001; - localparam [31:0] INPUT2 = 32'b01011100100011000110101000000001; - - reg[31:0] device0_values = INPUT1; - reg[31:0] device1_values = INPUT2; - reg[7:0] address; - - wire[31:0] value; - - InputDevices dut( - .value(value), - .address(address), - .device0_values(device0_values), - .device1_values(device1_values)); - - initial begin - address = 0; - # 10 - $display("INPUT_DEVICES_TEST: address=%b value=%b", address, value); - if (value !== INPUT1) begin - $error("in failed"); - $fatal(1); - end - address = 1; - # 10 - $display("INPUT_DEVICES_TEST: address=%b value=%b", address, value); - if (value !== INPUT2) begin - $error("in failed"); - $fatal(1); - end - end -endmodule diff --git a/emulator/com/mux.v b/emulator/com/mux.v index e52bff3..88367b7 100644 --- a/emulator/com/mux.v +++ b/emulator/com/mux.v @@ -6,7 +6,7 @@ module MUX_1_16b( input [15:0] A0, A1, input S); - always @(*) begin + always @(S, A0, A1) begin if (S) begin value = A1; end else begin @@ -20,7 +20,7 @@ module MUX_2_16b( input [15:0] A0, A1, A2, A3, input [1:0] S); - always @(*) begin + always @(S, A0, A1, A2, A3) begin case (S) 2'b00: value = A0; 2'b01: value = A1; diff --git a/emulator/com/rom.v b/emulator/com/rom.v index b902d82..f95ae4f 100644 --- a/emulator/com/rom.v +++ b/emulator/com/rom.v @@ -1,3 +1,6 @@ +`ifndef INCLUDED_ROM +`define INCLUDED_ROM + module _ROM_32bit_16aline( output[31:0] out, input[15:0] address); @@ -19,12 +22,23 @@ endmodule module ROM_BOOT( output[31:0] out, input[15:0] address); - // 4 * 64KB ROM + parameter filename = "emulator/com/rom_boot.bin"; reg[15:0] eaddress; always @(address) begin eaddress = address - 'h40; end - _ROM_32bit_16aline #(.filename("emulator/com/rom_boot.bin")) - dut(.out(out), + _ROM_32bit_16aline #(.filename(filename)) + _rom(.out(out), .address(eaddress)); endmodule + +module ROM_PINGPONG( + output[31:0] out, + input[15:0] address); + parameter filename = "output/programs/ping_pong.bin"; + _ROM_32bit_16aline #(.filename(filename)) + _rom(.out(out), + .address(address)); +endmodule + +`endif \ No newline at end of file diff --git a/emulator/com/stage1.v b/emulator/com/stage1.v index 229cdb1..85ac145 100644 --- a/emulator/com/stage1.v +++ b/emulator/com/stage1.v @@ -2,7 +2,7 @@ module STAGE1( output[31:0] vr_value, - output[7:0] input_devices_address, + output[7:0] io_device_id, output[15:0] ram_address, input[1:0] mblock_s1, input[7:0] vr_source, @@ -11,7 +11,7 @@ module STAGE1( wire[31:0] _const_value; - assign input_devices_address = vr_source; + assign io_device_id = vr_source; assign _const_value[7:0] = vr_source; assign _const_value[31:8] = 24'b000000000000000000000000; assign ram_address[7:0] = vr_source; diff --git a/emulator/com/stage1_test.v b/emulator/com/stage1_test.v index 7543a65..72e183c 100644 --- a/emulator/com/stage1_test.v +++ b/emulator/com/stage1_test.v @@ -2,7 +2,7 @@ module stage1_test; wire[31:0] vr_value; - wire[7:0] input_devices_address; + wire[7:0] io_device_id; wire[15:0] ram_address; reg[1:0] mblock_s1; @@ -12,7 +12,7 @@ module stage1_test; STAGE1 dut( .vr_value(vr_value), - .input_devices_address(input_devices_address), + .io_device_id(io_device_id), .ram_address(ram_address), .mblock_s1(mblock_s1), .vr_source(vr_source), @@ -34,8 +34,8 @@ module stage1_test; # 10 mblock_s1 = 2; # 10 - $display("STAGE1_TEST: vr_value=%b input_devices_address=%b", vr_value, input_devices_address); - if (vr_value !== 22 || input_devices_address !== 33) begin + $display("STAGE1_TEST: vr_value=%b io_device_id=%b", vr_value, io_device_id); + if (vr_value !== 22 || io_device_id !== 33) begin $error("stage1 failed"); $fatal(1); end diff --git a/emulator/com/stage3.v b/emulator/com/stage3.v index e9afae7..79bf853 100644 --- a/emulator/com/stage3.v +++ b/emulator/com/stage3.v @@ -6,7 +6,7 @@ module STAGE3( output[31:0] output_devices_value, - output[7:0] output_devices_address, + output[7:0] io_device_id, output[15:0] ram_address, output[31:0] ram_in, output ram_is_write, @@ -28,7 +28,7 @@ module STAGE3( DECODER_3 dut(.out(mblock_s3d), .in(mblock_s3)); assign output_devices_value = vw_value; - assign output_devices_address = vrw_source; + assign io_device_id = vrw_source; assign ram_in = vw_value; MUX_1_16b m1( @@ -59,5 +59,5 @@ module STAGE3( .S(reset_button)); assign is_powered_on_new = (is_powered_on & (!mblock_s3d[7])) | reset_button; - assign execute_from_ram_new = execute_from_ram & (!reset_button); + assign execute_from_ram_new = (execute_from_ram | mblock_s3d[4]) & (!reset_button); endmodule diff --git a/emulator/com/stage3_test.v b/emulator/com/stage3_test.v index 2fe2258..0fab75e 100644 --- a/emulator/com/stage3_test.v +++ b/emulator/com/stage3_test.v @@ -2,7 +2,7 @@ module stage3_test; wire[31:0] output_devices_value; - wire[7:0] output_devices_address; + wire[7:0] io_device_id; wire[15:0] ram_address; wire[31:0] ram_in; wire ram_is_write; @@ -23,7 +23,7 @@ module stage3_test; STAGE3 dut( .output_devices_value(output_devices_value), - .output_devices_address(output_devices_address), + .io_device_id(io_device_id), .ram_address(ram_address), .ram_in(ram_in), .ram_is_write(ram_is_write), @@ -70,7 +70,7 @@ module stage3_test; vrw_source = 15; # 10 $display("STAGE3_TEST: mblock_s3=%b pc_next=%b write_ram=%b write_out=%b radd=%b rin=%b", mblock_s3, pc_next, ram_is_write, output_is_write, ram_address, ram_in); - if (pc_next!==14 || output_devices_address!==15 || output_devices_value!==99 || ram_is_write!==0 || output_is_write!==1) begin + if (pc_next!==14 || io_device_id!==15 || output_devices_value!==99 || ram_is_write!==0 || output_is_write!==1) begin $error("stage3 failed"); $fatal(1); end diff --git a/emulator/seq/io_devices.v b/emulator/seq/io_devices.v new file mode 100644 index 0000000..5bc8826 --- /dev/null +++ b/emulator/seq/io_devices.v @@ -0,0 +1,33 @@ +`include "emulator/com/rom.v" +`define CONSDEV_ID 1 +`define PROM_ID 2 + +module IODevices( + output[31:0] value_out, + input[7:0] device_id, + input[31:0] value_in, + input is_write, + input clk); + + reg[31:0] _data [255:0]; + always @(negedge clk) begin + // Write are triggered at negedge + if (is_write) begin + _data[device_id] <= value_in; + $display("IO:output[%x] <= %x", device_id, value_in); + end + end + + // PROM + wire[31:0] prom_value; + ROM_PINGPONG prom(.out(prom_value), .address(_data[`PROM_ID][15:0])); + + reg[31:0] _value; + always @(device_id) begin + case (device_id) + `PROM_ID: _value <= prom_value; + `CONSDEV_ID: _value <= _data[`CONSDEV_ID]; + endcase + end + assign value_out = _value; +endmodule diff --git a/emulator/seq/io_devices_test.v b/emulator/seq/io_devices_test.v new file mode 100644 index 0000000..be62a9c --- /dev/null +++ b/emulator/seq/io_devices_test.v @@ -0,0 +1,44 @@ +`include "emulator/seq/io_devices.v" + +module IODevices_test; + wire[31:0] value_out; + + reg[7:0] device_id; + reg[31:0] value_in; + reg is_write; + reg clk; + + IODevices dut( + .value_out(value_out), + .device_id(device_id), + .value_in(value_in), + .is_write(is_write), + .clk(clk)); + + localparam [31:0] INPUT1 = 32'b11100101111110000100101010110001; + localparam [31:0] INPUT2 = 32'b01011100100011000110101000000001; + + initial begin + device_id = 1; + is_write = 1; + value_in = INPUT1; + clk = 1; + # 10 + clk = 0; + # 10 + device_id = 0; + $display("IO_DEVICES_TEST: device_id=%b value_out=%b", device_id, value_out); + if (value_out === INPUT1) begin + $error("io failed"); + $fatal(1); + end + # 10 + device_id = 1; + # 10 + $display("IO_DEVICES_TEST: device_id=%b value_out=%b", device_id, value_out); + if (value_out !== INPUT1) begin + $error("io failed"); + $fatal(1); + end + end +endmodule diff --git a/emulator/seq/output_devices.v b/emulator/seq/output_devices.v deleted file mode 100644 index 02d7f39..0000000 --- a/emulator/seq/output_devices.v +++ /dev/null @@ -1,18 +0,0 @@ -module OutputDevices( - output[31:0] device0_values, - output[31:0] device1_values, - input[7:0] address, - input[31:0] value, - input is_write, - input clk); - - reg[31:0] _data [255:0]; - always @(negedge clk) begin - // Write are triggered at negedge - if (is_write) begin - _data[address] <= value; - end - end - assign device0_values = _data[0]; - assign device1_values = _data[1]; -endmodule diff --git a/emulator/seq/output_devices_test.v b/emulator/seq/output_devices_test.v deleted file mode 100644 index 20dd67e..0000000 --- a/emulator/seq/output_devices_test.v +++ /dev/null @@ -1,50 +0,0 @@ -`include "emulator/seq/output_devices.v" - -module OutputDevices_test; - wire[31:0] device0_values; - wire[31:0] device1_values; - - reg[7:0] address; - reg is_write; - reg clk; - reg[31:0] value; - - OutputDevices dut( - .device0_values(device0_values), - .device1_values(device1_values), - .address(address), - .value(value), - .is_write(is_write), - .clk(clk)); - - - localparam [31:0] INPUT1 = 32'b11100101111110000100101010110001; - localparam [31:0] INPUT2 = 32'b01011100100011000110101000000001; - - initial begin - address = 0; - is_write = 1; - value = INPUT1; - clk = 1; - # 10 - clk = 0; - # 10 - address = 1; - is_write = 1; - value = INPUT2; - clk = 1; - # 10 - clk = 0; - # 10 - address = 0; - is_write = 0; - clk = 1; - # 10 - clk = 0; - $display("OUTPUT_DEVICES_TEST: address=%b is_write=%b value=%b", address, is_write, value); - if (device0_values !== INPUT1 || device1_values !== INPUT2) begin - $error("out failed"); - $fatal(1); - end - end -endmodule diff --git a/emulator/seq/ram.v b/emulator/seq/ram.v index 8839124..58650b3 100644 --- a/emulator/seq/ram.v +++ b/emulator/seq/ram.v @@ -10,7 +10,8 @@ module RAM_32bit_16aline( always @(negedge clk) begin // Write are triggered at negedge if (is_write) begin - mem[address] <= in; + mem[address] <= in; + $display("RAM[%x] <= %x", address, in); end end assign out = mem[address]; diff --git a/output/programs/3_led_switch.bin b/output/programs/3_led_switch.bin new file mode 100644 index 0000000..8d09d84 --- /dev/null +++ b/output/programs/3_led_switch.bin @@ -0,0 +1,4 @@ +00001100 00000000 00000000 00000000 +00100100 00000010 00000100 00000101 +00000100 00000100 00000110 00000100 +10110101 00001001 01000000 00000000 diff --git a/output/programs/3_led_switch_resolved.asm b/output/programs/3_led_switch_resolved.asm new file mode 100644 index 0000000..f9b0e42 --- /dev/null +++ b/output/programs/3_led_switch_resolved.asm @@ -0,0 +1,4 @@ +PROGRAM_ORG equ 64 +040: IN [4], 5 +044: OUT 6, [4] +048: JMP 64, 0 diff --git a/output/programs/boot_sequence.bin b/output/programs/boot_sequence.bin new file mode 100644 index 0000000..4260dcb --- /dev/null +++ b/output/programs/boot_sequence.bin @@ -0,0 +1,18 @@ +01000100 00000000 00000000 00000000 +00110100 00000010 00000000 00000000 +00000100 00000100 00000010 00000000 +00100100 00000010 00000000 00000010 +00110011 00000010 00000000 00000010 +00110100 00000010 00000100 00000100 +00110100 00000010 00001000 10000000 +00000100 00000100 00000010 00000100 +00100100 00000010 00001100 00000010 +00000100 00000110 00001000 00001100 +00110000 00000010 00001000 00000100 +00110000 00000010 00000100 00000100 +00110001 00000010 00000000 00000001 +10110101 00001101 01011100 00000000 +00110100 00000010 00100000 00000011 +00110010 00000010 00100000 00001000 +00110111 00000010 00100000 11111100 +10110101 00001001 10000000 00000000 diff --git a/output/programs/boot_sequence_resolved.asm b/output/programs/boot_sequence_resolved.asm new file mode 100644 index 0000000..f1d8e4e --- /dev/null +++ b/output/programs/boot_sequence_resolved.asm @@ -0,0 +1,18 @@ +PROGRAM_ORG equ 68 +044: MOVC [0], 0 +048: OUT 2, [0] +04c: IN [0], 2 +050: SHRC [0], 2 +054: MOVC [4], 4 +058: MOVC [8], 128 +05c: OUT 2, [4] +060: IN [12], 2 +064: STORE [[8]], [12] +068: ADDC [8], 4 +06c: ADDC [4], 4 +070: SUBC [0], 1 +074: JNZ 92, 0 +078: MOVC [32], 3 +07c: SHLC [32], 8 +080: ORC [32], 252 +084: JMP 128, 0 diff --git a/output/programs/ping_pong.bin b/output/programs/ping_pong.bin new file mode 100644 index 0000000..7ae869c --- /dev/null +++ b/output/programs/ping_pong.bin @@ -0,0 +1,195 @@ +00001000 00000011 00000000 00000000 +10110101 00001001 10110100 00000000 +00000010 00000000 00000000 00000000 +00000010 00000000 00000000 00000000 +00000111 00000000 00000000 00000000 +00000010 00000000 00000000 00000000 +11111111 11111111 00000000 00000000 +00000000 00000000 00000000 00000000 +00000110 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 +00000001 00000000 00000000 00000000 +11111111 01111111 00000000 00000000 +11111110 11111111 00000000 00000000 +11111111 11111111 00000000 00000000 +11110000 00000011 00101000 00010000 +00110001 00000010 00100000 00000100 +00000100 00000110 00100000 00101000 +10110101 00001001 10011100 00000001 +11110000 00000011 00101000 00010000 +00110001 00000010 00100000 00000100 +00000100 00000110 00100000 00101000 +10110101 00001001 00101100 00000001 +11110000 00000011 00101000 00010000 +00110001 00000010 00100000 00000100 +00000100 00000110 00100000 00101000 +10110101 00001001 00110000 00000010 +10110101 00001001 10110100 00000000 +11110000 00000011 00101000 00010000 +00110001 00000010 00100000 00000100 +00000100 00000110 00100000 00101000 +10110101 00001001 00001100 00000001 +11110000 00000011 00101000 00010000 +00110001 00000010 00100000 00000100 +00000100 00000110 00100000 00101000 +10110101 00001001 10011100 00000001 +10110101 00001001 11101000 00000000 +00110001 00000000 10100000 00000000 +10110101 00001101 00011100 00000001 +00111000 00000010 10100100 00000001 +00110100 00000010 10100000 00001111 +00110001 00000010 10100000 00000001 +01000101 00000010 00101000 00100000 +00110000 00000010 00100000 00000100 +10110101 00001000 00101000 00000000 +00100100 00000010 00000000 00000001 +00110100 00000010 00000100 00000001 +00000110 00000010 00000100 00000000 +10110101 00001011 01001000 00000001 +00110001 00000000 10000100 00000000 +10110101 00001011 01001000 00000001 +00110001 00000010 10000100 00000001 +00110100 00000010 00000100 00000010 +00000110 00000010 00000100 00000000 +10110101 00001011 01100000 00000001 +00110001 00000000 10000100 00000101 +10110101 00001011 01100000 00000001 +00110000 00000010 10000100 00000001 +00110100 00000010 00000100 00000100 +00000110 00000010 00000100 00000000 +10110101 00001011 01111000 00000001 +00110001 00000000 10001000 00000000 +10110101 00001011 01111000 00000001 +00110001 00000010 10001000 00000001 +00110100 00000010 00000100 00001000 +00000110 00000010 00000100 00000000 +10110101 00001011 10010000 00000001 +00110001 00000000 10001000 00000101 +10110101 00001011 10010000 00000001 +00110000 00000010 10001000 00000001 +01000101 00000010 00101000 00100000 +00110000 00000010 00100000 00000100 +10110101 00001000 00101000 00000000 +00110001 00000000 10100100 00000000 +10110101 00001011 11101100 00000001 +00000100 00000010 00000000 10101000 +00110100 00000010 00000100 00000111 +00000010 00000010 00000100 10000100 +00000100 00000100 00000110 00000000 +00000100 00000100 00000111 00000100 +00110100 00000010 00000100 00000000 +00000100 00000010 00000000 10110000 +00000100 00000100 00000111 00000100 +00000100 00000100 00000110 00000000 +00000100 00000010 00000000 10101100 +00110100 00000010 00000100 00000111 +00000010 00000010 00000100 10001000 +00000100 00000100 00000110 00000000 +00000100 00000100 00000111 00000100 +00110100 00000010 00000100 00000000 +00000100 00000010 00000000 10110000 +00000100 00000100 00000111 00000100 +00000100 00000100 00000110 00000000 +00000100 00000010 00000000 10001100 +00110100 00000010 00000100 10000000 +00110010 00000010 00000100 00001000 +00000011 00000010 00000100 00000000 +00001000 00000010 00000100 10010100 +00000100 00000010 00000000 10010000 +00110100 00000010 00001000 00000001 +00000010 00000010 00001000 00000000 +00000100 00000100 00000110 00000100 +00000100 00000100 00000111 00001000 +00110100 00000010 00001000 00000000 +00000100 00000010 00000100 10110000 +00000100 00000100 00000111 00001000 +00000100 00000100 00000110 00000100 +01000101 00000010 00101000 00100000 +00110000 00000010 00100000 00000100 +10110101 00001000 00101000 00000000 +00110001 00000000 10011000 00000000 +10110101 00001101 01001100 00000010 +00110100 00000010 10011000 00000011 +11110000 00000011 00101000 00010000 +00110001 00000010 00100000 00000100 +00000100 00000110 00100000 00101000 +10110101 00001001 01011100 00000010 +00110001 00000010 10011000 00000001 +01000101 00000010 00101000 00100000 +00110000 00000010 00100000 00000100 +10110101 00001000 00101000 00000000 +00110001 00000000 10001100 00001110 +10110101 00001011 11000000 00000010 +00110001 00000000 10001100 00000001 +10110101 00001011 11100100 00000010 +00110001 00000000 10010000 00000111 +10110101 00001011 01110100 00000011 +00110001 00000000 10010000 00000000 +10110101 00001011 01110100 00000011 +00000100 00000010 00000000 10011100 +00110110 00000010 00000000 00000001 +10110101 00001011 10010000 00000010 +00110000 00000010 10001100 00000001 +10110101 00001001 10010100 00000010 +00110001 00000010 10001100 00000001 +00000100 00000010 00000000 10011100 +00110110 00000010 00000000 00000100 +10110101 00001011 10100100 00000010 +00110001 00000010 10010000 00000001 +00000100 00000010 00000000 10011100 +00110110 00000010 00000000 00001000 +10110101 00001011 10110100 00000010 +00110000 00000010 10010000 00000001 +01000101 00000010 00101000 00100000 +00110000 00000010 00100000 00000100 +10110101 00001000 00101000 00000000 +00110001 00000010 00100000 00000100 +00000100 00000110 00100000 10001000 +11110000 00000011 00101000 00010000 +00110001 00000010 00100000 00000100 +00000100 00000110 00100000 00101000 +10110101 00001001 00001000 00000011 +01000101 00000010 00011100 00100000 +00110000 00000010 00100000 00000100 +10110101 00001001 01101100 00000010 +00110001 00000010 00100000 00000100 +00000100 00000110 00100000 10000100 +11110000 00000011 00101000 00010000 +00110001 00000010 00100000 00000100 +00000100 00000110 00100000 00101000 +10110101 00001001 00001000 00000011 +01000101 00000010 00011100 00100000 +00110000 00000010 00100000 00000100 +10110101 00001001 01101100 00000010 +00000100 00000010 00100100 00100000 +00110000 00000010 00100100 00000100 +01000101 00000010 00000100 00100100 +00111000 00000010 10011100 00000011 +00110100 00000010 00000000 00001100 +00111000 00000010 00000000 11111111 +00000110 00000010 10011100 00000000 +00000001 00000000 10010000 00000100 +10110101 00001011 01001000 00000011 +00110000 00000010 00000100 00000001 +00000001 00000000 10010000 00000100 +10110101 00001011 01101000 00000011 +00110000 00000010 00000100 00000001 +00000001 00000000 10010000 00000100 +10110101 00001011 01011000 00000011 +10110101 00001001 11101000 00000000 +00110111 00000010 10011100 00000100 +01000101 00000010 00101000 00100000 +00110000 00000010 00100000 00000100 +10110101 00001000 00101000 00000000 +00110111 00000010 10011100 00001000 +01000101 00000010 00101000 00100000 +00110000 00000010 00100000 00000100 +10110101 00001000 00101000 00000000 +01000101 00000010 00101000 00100000 +00110000 00000010 00100000 00000100 +10110101 00001000 00101000 00000000 +00000100 00000010 00000000 10011100 +00110110 00000010 00000000 00001100 +10110101 00001011 01111100 00000010 +00111000 00000010 10011100 00001100 +10110101 00001001 01111100 00000010 diff --git a/output/programs/ping_pong_resolved.asm b/output/programs/ping_pong_resolved.asm new file mode 100644 index 0000000..cc870f1 --- /dev/null +++ b/output/programs/ping_pong_resolved.asm @@ -0,0 +1,231 @@ +PROGRAM_ORG equ 128 +080: JMP 180, 0 +084: 02 +085: 00 +086: 00 +087: 00 +088: 02 +089: 00 +08a: 00 +08b: 00 +08c: 07 +08d: 00 +08e: 00 +08f: 00 +090: 02 +091: 00 +092: 00 +093: 00 +094: 255 +095: 255 +096: 00 +097: 00 +098: 00 +099: 00 +09a: 00 +09b: 00 +09c: 06 +09d: 00 +09e: 00 +09f: 00 +0a0: 00 +0a1: 00 +0a2: 00 +0a3: 00 +0a4: 01 +0a5: 00 +0a6: 00 +0a7: 00 +0a8: 255 +0a9: 127 +0aa: 00 +0ab: 00 +0ac: 254 +0ad: 255 +0ae: 00 +0af: 00 +0b0: 255 +0b1: 255 +0b2: 00 +0b3: 00 +0b4: PCPLUS [40], 16 +0b8: SUBC [32], 4 +0bc: STORE [[32]], [40] +0c0: JMP 156, 1 +0c4: PCPLUS [40], 16 +0c8: SUBC [32], 4 +0cc: STORE [[32]], [40] +0d0: JMP 44, 1 +0d4: PCPLUS [40], 16 +0d8: SUBC [32], 4 +0dc: STORE [[32]], [40] +0e0: JMP 48, 2 +0e4: JMP 180, 0 +0e8: PCPLUS [40], 16 +0ec: SUBC [32], 4 +0f0: STORE [[32]], [40] +0f4: JMP 12, 1 +0f8: PCPLUS [40], 16 +0fc: SUBC [32], 4 +100: STORE [[32]], [40] +104: JMP 156, 1 +108: JMP 232, 0 +10c: CMPC [160], 0 +110: JNZ 28, 1 +114: XORC [164], 1 +118: MOVC [160], 15 +11c: SUBC [160], 1 +120: LOAD [40], [[32]] +124: ADDC [32], 4 +128: JMPM [40], [0] +12c: IN [0], 1 +130: MOVC [4], 1 +134: AND [4], [0] +138: JZ 72, 1 +13c: CMPC [132], 0 +140: JZ 72, 1 +144: SUBC [132], 1 +148: MOVC [4], 2 +14c: AND [4], [0] +150: JZ 96, 1 +154: CMPC [132], 5 +158: JZ 96, 1 +15c: ADDC [132], 1 +160: MOVC [4], 4 +164: AND [4], [0] +168: JZ 120, 1 +16c: CMPC [136], 0 +170: JZ 120, 1 +174: SUBC [136], 1 +178: MOVC [4], 8 +17c: AND [4], [0] +180: JZ 144, 1 +184: CMPC [136], 5 +188: JZ 144, 1 +18c: ADDC [136], 1 +190: LOAD [40], [[32]] +194: ADDC [32], 4 +198: JMPM [40], [0] +19c: CMPC [164], 0 +1a0: JZ 236, 1 +1a4: MOV [0], [168] +1a8: MOVC [4], 7 +1ac: SHL [4], [132] +1b0: OUT 6, [0] +1b4: OUT 7, [4] +1b8: MOVC [4], 0 +1bc: MOV [0], [176] +1c0: OUT 7, [4] +1c4: OUT 6, [0] +1c8: MOV [0], [172] +1cc: MOVC [4], 7 +1d0: SHL [4], [136] +1d4: OUT 6, [0] +1d8: OUT 7, [4] +1dc: MOVC [4], 0 +1e0: MOV [0], [176] +1e4: OUT 7, [4] +1e8: OUT 6, [0] +1ec: MOV [0], [140] +1f0: MOVC [4], 128 +1f4: SHLC [4], 8 +1f8: SHR [4], [0] +1fc: XOR [4], [148] +200: MOV [0], [144] +204: MOVC [8], 1 +208: SHL [8], [0] +20c: OUT 6, [4] +210: OUT 7, [8] +214: MOVC [8], 0 +218: MOV [4], [176] +21c: OUT 7, [8] +220: OUT 6, [4] +224: LOAD [40], [[32]] +228: ADDC [32], 4 +22c: JMPM [40], [0] +230: CMPC [152], 0 +234: JNZ 76, 2 +238: MOVC [152], 3 +23c: PCPLUS [40], 16 +240: SUBC [32], 4 +244: STORE [[32]], [40] +248: JMP 92, 2 +24c: SUBC [152], 1 +250: LOAD [40], [[32]] +254: ADDC [32], 4 +258: JMPM [40], [0] +25c: CMPC [140], 14 +260: JZ 192, 2 +264: CMPC [140], 1 +268: JZ 228, 2 +26c: CMPC [144], 7 +270: JZ 116, 3 +274: CMPC [144], 0 +278: JZ 116, 3 +27c: MOV [0], [156] +280: ANDC [0], 1 +284: JZ 144, 2 +288: ADDC [140], 1 +28c: JMP 148, 2 +290: SUBC [140], 1 +294: MOV [0], [156] +298: ANDC [0], 4 +29c: JZ 164, 2 +2a0: SUBC [144], 1 +2a4: MOV [0], [156] +2a8: ANDC [0], 8 +2ac: JZ 180, 2 +2b0: ADDC [144], 1 +2b4: LOAD [40], [[32]] +2b8: ADDC [32], 4 +2bc: JMPM [40], [0] +2c0: SUBC [32], 4 +2c4: STORE [[32]], [136] +2c8: PCPLUS [40], 16 +2cc: SUBC [32], 4 +2d0: STORE [[32]], [40] +2d4: JMP 8, 3 +2d8: LOAD [28], [[32]] +2dc: ADDC [32], 4 +2e0: JMP 108, 2 +2e4: SUBC [32], 4 +2e8: STORE [[32]], [132] +2ec: PCPLUS [40], 16 +2f0: SUBC [32], 4 +2f4: STORE [[32]], [40] +2f8: JMP 8, 3 +2fc: LOAD [28], [[32]] +300: ADDC [32], 4 +304: JMP 108, 2 +308: MOV [36], [32] +30c: ADDC [36], 4 +310: LOAD [4], [[36]] +314: XORC [156], 3 +318: MOVC [0], 12 +31c: XORC [0], 255 +320: AND [156], [0] +324: CMP [144], [4] +328: JZ 72, 3 +32c: ADDC [4], 1 +330: CMP [144], [4] +334: JZ 104, 3 +338: ADDC [4], 1 +33c: CMP [144], [4] +340: JZ 88, 3 +344: JMP 232, 0 +348: ORC [156], 4 +34c: LOAD [40], [[32]] +350: ADDC [32], 4 +354: JMPM [40], [0] +358: ORC [156], 8 +35c: LOAD [40], [[32]] +360: ADDC [32], 4 +364: JMPM [40], [0] +368: LOAD [40], [[32]] +36c: ADDC [32], 4 +370: JMPM [40], [0] +374: MOV [0], [156] +378: ANDC [0], 12 +37c: JZ 124, 2 +380: XORC [156], 12 +384: JMP 124, 2 diff --git a/planner/memory.py b/planner/memory.py index fef0af4..5ef10db 100644 --- a/planner/memory.py +++ b/planner/memory.py @@ -17,6 +17,7 @@ def get_register_address(index): # free # boot sequence +# TODO: We can overlap PROGRAM_ORG and BOOTSEQUENCE_LOAD now BOOTSEQUENCE_LOAD = 0x40 BOOTSEQUENCE_ORG = 0x44 # as we have 4-byte rom size header at top From a54b0be0c4a69e28ae07c20699f9675ee0734171 Mon Sep 17 00:00:00 2001 From: Gagan Kumar Date: Wed, 15 Jan 2025 21:21:18 -0800 Subject: [PATCH 6/8] Working IPC b/w verilog test and python GUI --- emulator/Makefile.mk | 13 +++++ emulator/chipset_test.v | 2 +- emulator/module/ipc.cpp | 24 ++++++++++ emulator/module/ipc.v | 11 +++++ emulator/module/ipc_test.v | 20 ++++++++ emulator/seq/io.c | 6 +++ emulator/seq/io_devices.v | 43 ++++++++++++++++- planner/__main__.py | 6 ++- planner/sim/programs/verilog_input.py | 23 +++++++++ planner/sim/verilog_devices.py | 69 +++++++++++++++++++++++++++ 10 files changed, 213 insertions(+), 4 deletions(-) create mode 100644 emulator/module/ipc.cpp create mode 100644 emulator/module/ipc.v create mode 100644 emulator/module/ipc_test.v create mode 100644 emulator/seq/io.c create mode 100644 planner/sim/programs/verilog_input.py create mode 100644 planner/sim/verilog_devices.py diff --git a/emulator/Makefile.mk b/emulator/Makefile.mk index 696cb5b..a9f21e8 100644 --- a/emulator/Makefile.mk +++ b/emulator/Makefile.mk @@ -8,6 +8,19 @@ $(BUILD_EMULATOR)/%_test: $(SRC_EMULATOR)/%_test.v iverilog -o $@ $^ verilog_modules: $(patsubst $(SRC_EMULATOR)/%_test.v, $(BUILD_EMULATOR)/%_test, $(shell find $(SRC_EMULATOR) -name '*_test.v')) + mkdir -p $(BUILD_EMULATOR)/io test_verilog_modules: $(patsubst $(SRC_EMULATOR)/%_test.v, $(BUILD_EMULATOR)/%_test, $(shell find $(SRC_EMULATOR) -name '*_test.v')) $(foreach test_name, $^, echo "Executing $(test_name)" && ./$(test_name)) + +$(BUILD_EMULATOR)/module/libipc.so: $(SRC_EMULATOR)/module/ipc.cpp + mkdir -p $(dir $@) + g++ -shared -Wl,-soname,libipc.so -o $@ -fPIC $^ + +$(BUILD_EMULATOR)/module/ipc.py: $(SRC_EMULATOR)/module/ipc.py $(BUILD_EMULATOR)/module/libipc.so + mkdir -p $(dir $@) + cp -f $< $@ + +$(BUILD_EMULATOR)/module/ipc.o: $(SRC_EMULATOR)/module/ipc.cpp + mkdir -p $(dir $@) + g++ -o $@ $^ diff --git a/emulator/chipset_test.v b/emulator/chipset_test.v index 172febd..2f789f5 100644 --- a/emulator/chipset_test.v +++ b/emulator/chipset_test.v @@ -23,6 +23,6 @@ module chipset_test; $error("chipset failed"); $fatal(1); end - $finish(); + // $finish(); end endmodule diff --git a/emulator/module/ipc.cpp b/emulator/module/ipc.cpp new file mode 100644 index 0000000..d87896e --- /dev/null +++ b/emulator/module/ipc.cpp @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +void handle_output(void (*callback)(int,int), int process_id, int value) { + callback(process_id, value); +} + +void fast_io(void (*callback)(int,int)) { + unsigned int pid, v; + int len = scanf("IPC %x %x\n", &pid, &v); + if(len>0) { + handle_output(callback, pid, v); + } +} + +extern "C" void fast_io_loop(void (*callback)(int,int)) { + std::ios_base::sync_with_stdio(false); + std::cin.tie(nullptr); + while(1) { + fast_io(callback); + } +} diff --git a/emulator/module/ipc.v b/emulator/module/ipc.v new file mode 100644 index 0000000..82f7ae3 --- /dev/null +++ b/emulator/module/ipc.v @@ -0,0 +1,11 @@ +// Handle Inter Process Communication +// We were not able to figure out simpler way to do so. +module IPCOut( + input[15:0] process_id, + input[31:0] value + ); + + always @(value) begin + $display("IPC %x %x", process_id, value); + end +endmodule diff --git a/emulator/module/ipc_test.v b/emulator/module/ipc_test.v new file mode 100644 index 0000000..cdd23f3 --- /dev/null +++ b/emulator/module/ipc_test.v @@ -0,0 +1,20 @@ +`include "emulator/module/ipc.v" + +module ipc_test; + reg[15:0] process_id; + reg[31:0] value; + + IPCOut dut(.process_id(process_id[15:0]), .value(value[31:0])); + + initial begin + # 5 + process_id = 10; + # 1 + value = 20; + # 1 + value = 25; + # 1 + value = 30; + end +endmodule + diff --git a/emulator/seq/io.c b/emulator/seq/io.c new file mode 100644 index 0000000..015f028 --- /dev/null +++ b/emulator/seq/io.c @@ -0,0 +1,6 @@ +#include "stdio.h" +#include "stdlib.h" + +extern "C" void system_init() { + printf("Start system initialization ...\n"); +} \ No newline at end of file diff --git a/emulator/seq/io_devices.v b/emulator/seq/io_devices.v index 5bc8826..284f523 100644 --- a/emulator/seq/io_devices.v +++ b/emulator/seq/io_devices.v @@ -1,7 +1,12 @@ `include "emulator/com/rom.v" -`define CONSDEV_ID 1 +`include "emulator/module/ipc.v" +`define CONSDEV_ID 3 `define PROM_ID 2 +`define IO_DIR "build/emulator/io" + +// Import the function called "system_init" implemented in C code + module IODevices( output[31:0] value_out, input[7:0] device_id, @@ -9,15 +14,45 @@ module IODevices( input is_write, input clk); + integer fio; + reg[31:0] _data [255:0]; + initial begin + // $fseek(fio, 0, 0); + // system_init(); + end + reg[15:0] process_id; + // assign + reg[31:0] value; + IPCOut ipcout(.process_id(process_id[15:0]), .value(value[31:0])); + always @(negedge clk) begin // Write are triggered at negedge if (is_write) begin _data[device_id] <= value_in; + process_id <= {8'b00000000, device_id}; + value <= value_in; + + + // fio = $fopen("build/emulator/io/output.txt","w"); + // $fseek(fio, 0, 0); + // $fwrite(fio, "%b\n", value_in); + // $fflush(fio); + // $fclose(fio); $display("IO:output[%x] <= %x", device_id, value_in); end end + reg[31:0] _ipc_input[0:15]; + // integer i; + always @(posedge clk) begin + // At some random interval + $readmemb("/tmp/ourpc_input.txt", _ipc_input); + // for (i=0; i<16; i=i+1) begin + // $display("INPUT[%d]: %x", i, _ipc_input[i]); + // end + end + // PROM wire[31:0] prom_value; ROM_PINGPONG prom(.out(prom_value), .address(_data[`PROM_ID][15:0])); @@ -26,7 +61,11 @@ module IODevices( always @(device_id) begin case (device_id) `PROM_ID: _value <= prom_value; - `CONSDEV_ID: _value <= _data[`CONSDEV_ID]; + default: + begin + _value <= _ipc_input[device_id]; + // $display("IO:input[%x] <= %x", device_id, _value); + end endcase end assign value_out = _value; diff --git a/planner/__main__.py b/planner/__main__.py index d363b10..5f8fc21 100644 --- a/planner/__main__.py +++ b/planner/__main__.py @@ -5,7 +5,7 @@ from planner.asm import program_parser from planner.sim import bin_parser from planner.sim import devices -from planner.sim.programs import ping_pong +from planner.sim.programs import ping_pong, verilog_input def args_parser(): @@ -26,6 +26,8 @@ def args_parser(): bin_parser = subparsers.add_parser("compile_and_execute") bin_parser.add_argument("program") + + subparsers.add_parser("verilog_io") return parser def main(): @@ -45,6 +47,8 @@ def main(): _bin.set_output_device(6, devices.IntegerOutput("Screen6", bits=16)) while True: _bin.step() + if args.source == "verilog_io": + verilog_input.start() if args.source == "compile_and_execute": if args.program == "ping_pong": ping_pong.start() diff --git a/planner/sim/programs/verilog_input.py b/planner/sim/programs/verilog_input.py new file mode 100644 index 0000000..5d87d2b --- /dev/null +++ b/planner/sim/programs/verilog_input.py @@ -0,0 +1,23 @@ +from planner.sim import verilog_devices, gui_devices +from planner.sim import devices, gui_devices +import pygame + +def start(): + io = verilog_devices.VerilogIO() + gui_manager = gui_devices.GUIDeviceManager() + + input = devices.LatchInput("input", bits=4) + gui_manager.add_device((0, 0), gui_devices.KeyPressedInput(input, { + pygame.K_w: 0, + pygame.K_s: 1, + pygame.K_UP: 2, + pygame.K_DOWN: 3, + })) + io.set_input_device(1, input) + + display = devices.LEDDisplay("LED", use_print=False, width_anode=16, height_cathode=8) + gui_manager.add_device((0, 0), gui_devices.GUILed(display)) + io.set_output_device(6, display.get_anodes()[0]) + io.set_output_device(7, display.get_cathodes()[0]) + io.run(blocking=False) + gui_manager.draw_loop() diff --git a/planner/sim/verilog_devices.py b/planner/sim/verilog_devices.py new file mode 100644 index 0000000..42b9261 --- /dev/null +++ b/planner/sim/verilog_devices.py @@ -0,0 +1,69 @@ +from planner.sim import devices +import threading +import os +from ctypes import cdll, c_int, CFUNCTYPE + +IO_DEVICES = 16 +LIB = "build/emulator/module/libipc.so" +INPUT_FILE = "/tmp/ourpc_input.txt" + +global_io = None +@CFUNCTYPE(None, c_int, c_int) +def handle_output(pid, value): + print("Got PID(%d) Value(%d)" % (pid, value)) + global_io.output_devices[pid].update(value) + +def io_loop(hh): + while True: + s = input() + print(s) + s=s.split() + if s[0]=="IPC": + pid,value = s[1],s[2] + pid=int(pid, 16) + value=int(value, 16) + print("Got PID(%d) Value(%d)" % (pid, value)) + dev = global_io.output_devices[pid] + if dev is None: + print("Device is None") + else: + dev.update(value) + +class VerilogIO: + def __init__(self): + self.input_devices = [None]*IO_DEVICES + self.output_devices = [None]*IO_DEVICES + + # lib = cdll.LoadLibrary(LIB) + # lib.fast_io_loop + global global_io + global_io = self + self.mu = threading.Lock() + self.t = threading.Thread(target=io_loop, args=[handle_output]) + + + def run(self, blocking=True): + self.write_input(0, 0) + self.t.start() + if blocking: + self.t.join() + + def write_input(self, new_val, old_val): + data = [0 if i is None else i.get() for i in self.input_devices] + data_str = '\n'.join([ + "{:032b}".format(x) for x in data + ]) + with self.mu: + with open(INPUT_FILE, "w") as f: + f.write(data_str) + + def set_input_device(self, index: int, d: devices.InputDevice): + d.add_change_handler(self.write_input) + self.input_devices[index] = d + + def set_output_device(self, index: int, d: devices.Device): + self.output_devices[index] = d + + + + From 186f92fba42a9bb641b4656e12d1927d9fcf0439 Mon Sep 17 00:00:00 2001 From: Gagan Kumar Date: Sat, 25 Jan 2025 01:27:06 -0800 Subject: [PATCH 7/8] Move Makefiles rules around, improve verilog IPC --- Makefile | 7 ++- emulator/Makefile.mk | 21 ++++---- .../{chipset_test.v => executable_chipset.v} | 1 - emulator/module/ipc.v | 26 ++++++++-- emulator/module/ipc_test.v | 51 ++++++++++++++++--- emulator/seq/io.c | 6 --- emulator/seq/io_devices.v | 43 ++++------------ emulator/seq/io_devices_test.v | 23 +++++++-- emulator/specs.py | 8 --- 9 files changed, 110 insertions(+), 76 deletions(-) rename emulator/{chipset_test.v => executable_chipset.v} (96%) delete mode 100644 emulator/seq/io.c delete mode 100644 emulator/specs.py diff --git a/Makefile b/Makefile index 787a9c9..3721846 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ SRC_DIR=. BUILD_DIR=build OUTPUT_DIR=output -.PHONY: clean test all run_ping_pong all_programs_binary all_programs_resolved +.PHONY: clean test all run_verilog_io run_ping_pong all_programs_binary all_programs_resolved output_rom_binaries all: all_programs_binary all_programs_resolved verilog_modules @@ -19,6 +19,8 @@ test: pytest test_verilog_modules all_programs_binary: $(patsubst programs/%.asm, $(OUTPUT_DIR)/programs/%.bin, $(shell find programs/ -name '*.asm')) +output_rom_binaries: $(OUTPUT_DIR)/programs/boot_sequence.bin $(OUTPUT_DIR)/programs/ping_pong.bin + $(OUTPUT_DIR)/programs/%.bin: programs/%.asm mkdir -p $(dir $@) python3 -m planner asm -b $^ > $@ @@ -31,3 +33,6 @@ $(OUTPUT_DIR)/programs/%_resolved.asm: programs/%.asm run_ping_pong: python3 -m planner compile_and_execute ping_pong + +run_verilog_io: + python3 -m planner verilog_io diff --git a/emulator/Makefile.mk b/emulator/Makefile.mk index a9f21e8..2b61cc4 100644 --- a/emulator/Makefile.mk +++ b/emulator/Makefile.mk @@ -1,26 +1,25 @@ BUILD_EMULATOR = $(BUILD_DIR)/emulator SRC_EMULATOR = $(SRC_DIR)/emulator -.PHONY: verilog_modules test_verilog_modules +.PHONY: verilog_modules test_verilog_modules verilog_data_prerequisites verilog_simulate $(BUILD_EMULATOR)/%_test: $(SRC_EMULATOR)/%_test.v mkdir -p $(dir $@) iverilog -o $@ $^ -verilog_modules: $(patsubst $(SRC_EMULATOR)/%_test.v, $(BUILD_EMULATOR)/%_test, $(shell find $(SRC_EMULATOR) -name '*_test.v')) +verilog_modules: $(BUILD_EMULATOR)/executable_chipset $(patsubst $(SRC_EMULATOR)/%_test.v, $(BUILD_EMULATOR)/%_test, $(shell find $(SRC_EMULATOR) -name '*_test.v')) mkdir -p $(BUILD_EMULATOR)/io +verilog_data_prerequisites: output_rom_binaries + test_verilog_modules: $(patsubst $(SRC_EMULATOR)/%_test.v, $(BUILD_EMULATOR)/%_test, $(shell find $(SRC_EMULATOR) -name '*_test.v')) + $(MAKE) verilog_data_prerequisites $(foreach test_name, $^, echo "Executing $(test_name)" && ./$(test_name)) -$(BUILD_EMULATOR)/module/libipc.so: $(SRC_EMULATOR)/module/ipc.cpp - mkdir -p $(dir $@) - g++ -shared -Wl,-soname,libipc.so -o $@ -fPIC $^ - -$(BUILD_EMULATOR)/module/ipc.py: $(SRC_EMULATOR)/module/ipc.py $(BUILD_EMULATOR)/module/libipc.so +$(BUILD_EMULATOR)/executable_chipset: $(SRC_EMULATOR)/executable_chipset.v + $(MAKE) verilog_data_prerequisites mkdir -p $(dir $@) - cp -f $< $@ + iverilog -o $@ $^ -$(BUILD_EMULATOR)/module/ipc.o: $(SRC_EMULATOR)/module/ipc.cpp - mkdir -p $(dir $@) - g++ -o $@ $^ +verilog_simulate: $(BUILD_EMULATOR)/executable_chipset + ./$^ | $(MAKE) run_verilog_io diff --git a/emulator/chipset_test.v b/emulator/executable_chipset.v similarity index 96% rename from emulator/chipset_test.v rename to emulator/executable_chipset.v index 2f789f5..522751e 100644 --- a/emulator/chipset_test.v +++ b/emulator/executable_chipset.v @@ -23,6 +23,5 @@ module chipset_test; $error("chipset failed"); $fatal(1); end - // $finish(); end endmodule diff --git a/emulator/module/ipc.v b/emulator/module/ipc.v index 82f7ae3..5b82864 100644 --- a/emulator/module/ipc.v +++ b/emulator/module/ipc.v @@ -1,11 +1,31 @@ +`define INPUT_FILE "/tmp/ourpc_input" + // Handle Inter Process Communication -// We were not able to figure out simpler way to do so. +// We weren't able to figure out simpler way to do so. module IPCOut( - input[15:0] process_id, + input[7:0] device_id, input[31:0] value ); always @(value) begin - $display("IPC %x %x", process_id, value); + $display("IPC %x %x", device_id, value); + end +endmodule + +module IPCIn( + output[31:0] value, + input[7:0] device_id, + input clk); + + // device_id to value + reg[31:0] _ipc_input[0:7]; + always @(posedge clk) begin + // At some random interval + $readmemb(`INPUT_FILE, _ipc_input); + end + reg[31:0] _value; + always @(*) begin + _value <= _ipc_input[device_id]; end + assign value = _value; endmodule diff --git a/emulator/module/ipc_test.v b/emulator/module/ipc_test.v index cdd23f3..c5b3210 100644 --- a/emulator/module/ipc_test.v +++ b/emulator/module/ipc_test.v @@ -1,20 +1,57 @@ `include "emulator/module/ipc.v" -module ipc_test; - reg[15:0] process_id; +module ipc_out_test; + reg[7:0] device_id; reg[31:0] value; - IPCOut dut(.process_id(process_id[15:0]), .value(value[31:0])); + IPCOut dut(.device_id(device_id[7:0]), .value(value[31:0])); initial begin # 5 - process_id = 10; + device_id = 10; # 1 value = 20; + // Not test here, output goes to stdout. + end +endmodule + +module ipc_in_test; + reg[7:0] device_id; + reg clk; + output[31:0] value; + + IPCIn dut(.value(value[31:0]), .device_id(device_id[7:0]), .clk(clk)); + + integer f; + initial begin + # 5 + f = $fopen("/tmp/ourpc_input", "w"); + $fwrite(f,"00000000000000000000000000000001\n"); + $fwrite(f,"11111111111111111111111111111111\n"); + $fwrite(f,"01010101010101010101010101010101\n"); + $fwrite(f,"10101010101010101010101010101010\n"); + $fwrite(f,"00000000000000000000000011111111\n"); + $fwrite(f,"11111111000000000000000000000000\n"); + $fwrite(f,"01010101101010100101010110101010\n"); + $fwrite(f,"10101010010101011010101001010101\n"); + $fclose(f); + + device_id = 1; + clk = 0; + # 5 + clk = 1; + # 5 + if (value !== 32'b11111111111111111111111111111111) begin + $error("ipc input failed, got: %b", value); + $fatal(1); + end + device_id = 6; # 1 - value = 25; - # 1 - value = 30; + if (value !== 32'b01010101101010100101010110101010) begin + $error("ipc input failed, got: %b", value); + $fatal(1); + end + end endmodule diff --git a/emulator/seq/io.c b/emulator/seq/io.c deleted file mode 100644 index 015f028..0000000 --- a/emulator/seq/io.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "stdio.h" -#include "stdlib.h" - -extern "C" void system_init() { - printf("Start system initialization ...\n"); -} \ No newline at end of file diff --git a/emulator/seq/io_devices.v b/emulator/seq/io_devices.v index 284f523..35943e4 100644 --- a/emulator/seq/io_devices.v +++ b/emulator/seq/io_devices.v @@ -3,10 +3,6 @@ `define CONSDEV_ID 3 `define PROM_ID 2 -`define IO_DIR "build/emulator/io" - -// Import the function called "system_init" implemented in C code - module IODevices( output[31:0] value_out, input[7:0] device_id, @@ -16,55 +12,34 @@ module IODevices( integer fio; - reg[31:0] _data [255:0]; - initial begin - // $fseek(fio, 0, 0); - // system_init(); - end - reg[15:0] process_id; - // assign reg[31:0] value; - IPCOut ipcout(.process_id(process_id[15:0]), .value(value[31:0])); + output[31:0] value_ipc_in; + + IPCOut ipcout(.device_id(device_id[7:0]), .value(value[31:0])); + IPCIn ipcin(.value(value_ipc_in[31:0]), .device_id(device_id[7:0]), .clk(clk)); always @(negedge clk) begin // Write are triggered at negedge if (is_write) begin - _data[device_id] <= value_in; - process_id <= {8'b00000000, device_id}; value <= value_in; - - - // fio = $fopen("build/emulator/io/output.txt","w"); - // $fseek(fio, 0, 0); - // $fwrite(fio, "%b\n", value_in); - // $fflush(fio); - // $fclose(fio); $display("IO:output[%x] <= %x", device_id, value_in); end end - reg[31:0] _ipc_input[0:15]; - // integer i; - always @(posedge clk) begin - // At some random interval - $readmemb("/tmp/ourpc_input.txt", _ipc_input); - // for (i=0; i<16; i=i+1) begin - // $display("INPUT[%d]: %x", i, _ipc_input[i]); - // end - end - // PROM wire[31:0] prom_value; - ROM_PINGPONG prom(.out(prom_value), .address(_data[`PROM_ID][15:0])); + ROM_PINGPONG prom(.out(prom_value), .address(value_in[15:0])); reg[31:0] _value; always @(device_id) begin case (device_id) + // TODO: Is it ok to use continous circuit with value_in as address? `PROM_ID: _value <= prom_value; + `CONSDEV_ID: _value <= value_in; default: + // Goes via IPC begin - _value <= _ipc_input[device_id]; - // $display("IO:input[%x] <= %x", device_id, _value); + _value <= value_ipc_in; end endcase end diff --git a/emulator/seq/io_devices_test.v b/emulator/seq/io_devices_test.v index be62a9c..1a3e906 100644 --- a/emulator/seq/io_devices_test.v +++ b/emulator/seq/io_devices_test.v @@ -20,25 +20,38 @@ module IODevices_test; initial begin device_id = 1; - is_write = 1; + is_write = 0; value_in = INPUT1; clk = 1; # 10 clk = 0; # 10 - device_id = 0; + device_id = 3; // const + # 5 $display("IO_DEVICES_TEST: device_id=%b value_out=%b", device_id, value_out); - if (value_out === INPUT1) begin + if (value_out !== INPUT1) begin $error("io failed"); $fatal(1); end # 10 - device_id = 1; + device_id = 2; // PROM + value_in = 0; # 10 $display("IO_DEVICES_TEST: device_id=%b value_out=%b", device_id, value_out); - if (value_out !== INPUT1) begin + if (value_out === INPUT1) begin + // not a great test but ok. $error("io failed"); $fatal(1); end + # 10 + device_id = 5; // IPC + value_in = 10; + is_write = 1; + # 10 + clk = 0; + # 10 + clk = 1; + // trigger write + // no verification, but it should generate logs. end endmodule diff --git a/emulator/specs.py b/emulator/specs.py deleted file mode 100644 index 04c48ea..0000000 --- a/emulator/specs.py +++ /dev/null @@ -1,8 +0,0 @@ -RAM_ADDRESS_LINES = 16 -ROM_ADDRESS_LINES = 8 - -WORD_SIZE = 8 -ROM_MAXSIZE = 2**(ROM_ADDRESS_LINES) * 8 -RAM_SIZE = 2**(RAM_ADDRESS_LINES) * 8 - -PROGRAM_START = 0x20 From d44798dbf06d45c42a9324642002b8d29f5a6d7a Mon Sep 17 00:00:00 2001 From: Gagan Kumar Date: Sat, 1 Feb 2025 10:25:25 -0800 Subject: [PATCH 8/8] Funtional verilog ping_pong simulator --- README.md | 5 +++-- emulator/Makefile.mk | 4 ++-- emulator/module/ipc.cpp | 24 ------------------------ emulator/seq/io_devices.v | 2 +- emulator/seq/io_devices_test.v | 8 ++++++++ planner/sim/verilog_devices.py | 24 ++++++------------------ 6 files changed, 20 insertions(+), 47 deletions(-) delete mode 100644 emulator/module/ipc.cpp diff --git a/README.md b/README.md index 38b2928..68b52bd 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,13 @@ The eventual goal(?) is to build a general-purpose processor integrated with sim ## Sample Programs * Ping Pong + * 16x8 LED display with W/S/Up/Down keyboard controller * Source: [ping_pong.asm](programs/ping_pong.asm) * Generate resolved assembly: `python3 -m planner asm -r programs/ping_pong.asm` [[example](output/programs/ping_pong_resolved.asm)] * Generate binary: `python3 -m planner asm -b programs/ping_pong.asm` [[example](output/programs/ping_pong.bin)] - * Run on emulator: `python3 -m planner compile_and_execute ping_pong` - * 16x8 LED display with W/S/Up/Down keyboard controller + * Run on python emulator: `python3 -m planner compile_and_execute ping_pong` * ![image](https://github.com/user-attachments/assets/9fa2f68f-73ae-465c-a29c-cc92b0dc421a) + * Run on verilog emulator: `make verilog_simulate` ## Design diff --git a/emulator/Makefile.mk b/emulator/Makefile.mk index 2b61cc4..e5b1bdb 100644 --- a/emulator/Makefile.mk +++ b/emulator/Makefile.mk @@ -3,9 +3,9 @@ SRC_EMULATOR = $(SRC_DIR)/emulator .PHONY: verilog_modules test_verilog_modules verilog_data_prerequisites verilog_simulate -$(BUILD_EMULATOR)/%_test: $(SRC_EMULATOR)/%_test.v +$(BUILD_EMULATOR)/%_test: $(SRC_EMULATOR)/%_test.v $(SRC_EMULATOR)/%.v mkdir -p $(dir $@) - iverilog -o $@ $^ + iverilog -o $@ $< verilog_modules: $(BUILD_EMULATOR)/executable_chipset $(patsubst $(SRC_EMULATOR)/%_test.v, $(BUILD_EMULATOR)/%_test, $(shell find $(SRC_EMULATOR) -name '*_test.v')) mkdir -p $(BUILD_EMULATOR)/io diff --git a/emulator/module/ipc.cpp b/emulator/module/ipc.cpp deleted file mode 100644 index d87896e..0000000 --- a/emulator/module/ipc.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include -#include - -void handle_output(void (*callback)(int,int), int process_id, int value) { - callback(process_id, value); -} - -void fast_io(void (*callback)(int,int)) { - unsigned int pid, v; - int len = scanf("IPC %x %x\n", &pid, &v); - if(len>0) { - handle_output(callback, pid, v); - } -} - -extern "C" void fast_io_loop(void (*callback)(int,int)) { - std::ios_base::sync_with_stdio(false); - std::cin.tie(nullptr); - while(1) { - fast_io(callback); - } -} diff --git a/emulator/seq/io_devices.v b/emulator/seq/io_devices.v index 35943e4..a946014 100644 --- a/emulator/seq/io_devices.v +++ b/emulator/seq/io_devices.v @@ -31,7 +31,7 @@ module IODevices( ROM_PINGPONG prom(.out(prom_value), .address(value_in[15:0])); reg[31:0] _value; - always @(device_id) begin + always @(clk) begin case (device_id) // TODO: Is it ok to use continous circuit with value_in as address? `PROM_ID: _value <= prom_value; diff --git a/emulator/seq/io_devices_test.v b/emulator/seq/io_devices_test.v index 1a3e906..839eb67 100644 --- a/emulator/seq/io_devices_test.v +++ b/emulator/seq/io_devices_test.v @@ -27,6 +27,10 @@ module IODevices_test; clk = 0; # 10 device_id = 3; // const + # 1 + clk = 1; + # 1 + clk = 0; # 5 $display("IO_DEVICES_TEST: device_id=%b value_out=%b", device_id, value_out); if (value_out !== INPUT1) begin @@ -36,6 +40,10 @@ module IODevices_test; # 10 device_id = 2; // PROM value_in = 0; + # 1 + clk = 1; + # 1 + clk = 0; # 10 $display("IO_DEVICES_TEST: device_id=%b value_out=%b", device_id, value_out); if (value_out === INPUT1) begin diff --git a/planner/sim/verilog_devices.py b/planner/sim/verilog_devices.py index 42b9261..77805e1 100644 --- a/planner/sim/verilog_devices.py +++ b/planner/sim/verilog_devices.py @@ -1,25 +1,18 @@ from planner.sim import devices import threading -import os -from ctypes import cdll, c_int, CFUNCTYPE -IO_DEVICES = 16 -LIB = "build/emulator/module/libipc.so" -INPUT_FILE = "/tmp/ourpc_input.txt" +IO_DEVICES = 8 +INPUT_FILE = "/tmp/ourpc_input" global_io = None -@CFUNCTYPE(None, c_int, c_int) -def handle_output(pid, value): - print("Got PID(%d) Value(%d)" % (pid, value)) - global_io.output_devices[pid].update(value) -def io_loop(hh): +def io_loop(): while True: s = input() print(s) s=s.split() if s[0]=="IPC": - pid,value = s[1],s[2] + pid,value = s[1], s[2] pid=int(pid, 16) value=int(value, 16) print("Got PID(%d) Value(%d)" % (pid, value)) @@ -34,12 +27,10 @@ def __init__(self): self.input_devices = [None]*IO_DEVICES self.output_devices = [None]*IO_DEVICES - # lib = cdll.LoadLibrary(LIB) - # lib.fast_io_loop global global_io global_io = self self.mu = threading.Lock() - self.t = threading.Thread(target=io_loop, args=[handle_output]) + self.t = threading.Thread(target=io_loop, args=[]) def run(self, blocking=True): @@ -57,13 +48,10 @@ def write_input(self, new_val, old_val): with open(INPUT_FILE, "w") as f: f.write(data_str) + def set_input_device(self, index: int, d: devices.InputDevice): d.add_change_handler(self.write_input) self.input_devices[index] = d def set_output_device(self, index: int, d: devices.Device): self.output_devices[index] = d - - - -