Add test cases for co-simulation
authorMiodrag Milanovic <mmicko@gmail.com>
Wed, 2 Feb 2022 12:22:44 +0000 (13:22 +0100)
committerMiodrag Milanovic <mmicko@gmail.com>
Wed, 2 Feb 2022 12:22:44 +0000 (13:22 +0100)
tests/sat/.gitignore
tests/sat/alu.v [new file with mode: 0644]
tests/sat/grom.ys [new file with mode: 0644]
tests/sat/grom_computer.v [new file with mode: 0644]
tests/sat/grom_cpu.v [new file with mode: 0644]
tests/sat/ram_memory.v [new file with mode: 0644]
tests/sat/sim_counter.ys [new file with mode: 0644]

index 8355de9dc881470c84da3de438737fd886c70422..664425d738b59d72748e713e70426078dcead6dc 100644 (file)
@@ -1,2 +1,4 @@
 *.log
 run-test.mk
+*.vcd
+*.fst
diff --git a/tests/sat/alu.v b/tests/sat/alu.v
new file mode 100644 (file)
index 0000000..9826fe0
--- /dev/null
@@ -0,0 +1,79 @@
+module alu(
+       input clk,
+       input [7:0] A,
+       input [7:0] B,
+       input [3:0] operation,
+       output reg [7:0] result,
+       output reg CF,
+       output reg ZF,
+       output reg SF
+);
+
+       localparam ALU_OP_ADD /* verilator public_flat */ = 4'b0000;
+       localparam ALU_OP_SUB /* verilator public_flat */ = 4'b0001;
+       localparam ALU_OP_ADC /* verilator public_flat */ = 4'b0010;
+       localparam ALU_OP_SBC /* verilator public_flat */ = 4'b0011;
+
+       localparam ALU_OP_AND /* verilator public_flat */ = 4'b0100;
+       localparam ALU_OP_OR  /* verilator public_flat */ = 4'b0101;
+       localparam ALU_OP_NOT /* verilator public_flat */ = 4'b0110;
+       localparam ALU_OP_XOR /* verilator public_flat */ = 4'b0111;
+
+       localparam ALU_OP_SHL /* verilator public_flat */ = 4'b1000;
+       localparam ALU_OP_SHR /* verilator public_flat */ = 4'b1001;
+       localparam ALU_OP_SAL /* verilator public_flat */ = 4'b1010;
+       localparam ALU_OP_SAR /* verilator public_flat */ = 4'b1011;
+
+       localparam ALU_OP_ROL /* verilator public_flat */ = 4'b1100;
+       localparam ALU_OP_ROR /* verilator public_flat */ = 4'b1101;
+       localparam ALU_OP_RCL /* verilator public_flat */ = 4'b1110;
+       localparam ALU_OP_RCR /* verilator public_flat */ = 4'b1111;
+
+       reg [8:0] tmp;
+
+       always @(posedge clk)
+       begin
+               case (operation)
+                       ALU_OP_ADD :
+                               tmp = A + B;
+                       ALU_OP_SUB :
+                               tmp = A - B;
+                       ALU_OP_ADC :
+                               tmp = A + B + { 7'b0000000, CF };
+                       ALU_OP_SBC :
+                               tmp = A - B - { 7'b0000000, CF };
+                       ALU_OP_AND :
+                               tmp = {1'b0, A & B };
+                       ALU_OP_OR :
+                               tmp = {1'b0, A | B };
+                       ALU_OP_NOT :
+                               tmp = {1'b0, ~B };
+                       ALU_OP_XOR :
+                               tmp = {1'b0, A ^ B};
+                       ALU_OP_SHL :
+                               tmp = { A[7], A[6:0], 1'b0};
+                       ALU_OP_SHR :
+                               tmp = { A[0], 1'b0, A[7:1]};
+                       ALU_OP_SAL :
+                               // Same as SHL
+                               tmp = { A[7], A[6:0], 1'b0};
+                       ALU_OP_SAR :
+                               tmp = { A[0], A[7], A[7:1]};
+                       ALU_OP_ROL :
+                               tmp = { A[7], A[6:0], A[7]};
+                       ALU_OP_ROR :
+                               tmp = { A[0], A[0], A[7:1]};
+                       ALU_OP_RCL :
+                               tmp = { A[7], A[6:0], CF};
+                       ALU_OP_RCR :
+                               tmp = { A[0], CF, A[7:1]};
+               endcase
+
+               CF <= tmp[8];
+               ZF <= tmp[7:0] == 0;
+               SF <= tmp[7];
+
+               result <= tmp[7:0];
+       end
+endmodule
+
diff --git a/tests/sat/grom.ys b/tests/sat/grom.ys
new file mode 100644 (file)
index 0000000..2c2cd71
--- /dev/null
@@ -0,0 +1,9 @@
+read_verilog grom_computer.v grom_cpu.v alu.v ram_memory.v;
+prep -top grom_computer; 
+sim -clock clk -reset reset -fst grom.fst -vcd grom.vcd -a -n 80
+
+sim -clock clk -r grom.fst -scope grom_computer -start 25ns -stop 100ns -sim-cmp
+
+sim -clock clk -r grom.fst -scope grom_computer -stop 100ns -sim-gold
+
+sim -clock clk -r grom.fst -scope grom_computer -n 10 -sim-gate -a
diff --git a/tests/sat/grom_computer.v b/tests/sat/grom_computer.v
new file mode 100644 (file)
index 0000000..63a5c8f
--- /dev/null
@@ -0,0 +1,31 @@
+module grom_computer
+  (input  clk,     // Main Clock
+   input  reset,   // reset
+   output hlt,
+   output reg[7:0] display_out
+  );
+
+ wire [11:0] addr;
+ wire [7:0] memory_out;
+ wire [7:0] memory_in;
+ wire mem_enable;
+ wire  we;
+ wire ioreq;
+
+ grom_cpu cpu(.clk(clk),.reset(reset),.addr(addr),.data_in(memory_out),.data_out(memory_in),.we(we),.ioreq(ioreq),.hlt(hlt));
+
+ assign mem_enable = we & ~ioreq;
+
+ ram_memory memory(.clk(clk),.addr(addr),.data_in(memory_in),.we(mem_enable),.data_out(memory_out));
+
+ always @(posedge clk)
+       begin
+               if(ioreq==1 && we==1)
+               begin
+                       display_out <= memory_in;
+                       `ifdef DISASSEMBLY
+                       $display("Display output : %h", memory_in);
+                       `endif
+               end
+       end
+endmodule
diff --git a/tests/sat/grom_cpu.v b/tests/sat/grom_cpu.v
new file mode 100644 (file)
index 0000000..f9fef04
--- /dev/null
@@ -0,0 +1,747 @@
+module grom_cpu(
+       input clk,
+       input reset,
+       output reg [11:0] addr,
+       input [7:0] data_in,
+       output reg [7:0] data_out,
+       output reg we,
+       output reg ioreq,
+       output reg hlt
+);
+
+       reg[11:0] PC /* verilator public_flat */;               // Program counter
+       reg[7:0] IR /* verilator public_flat */;            // Instruction register
+       reg[7:0] VALUE /* verilator public_flat */;             // Temp reg for storing 2nd operand
+       reg[3:0] CS /* verilator public_flat */;                // Code segment regiser
+       reg[3:0] DS /* verilator public_flat */;                // Data segment regiser
+       reg[11:0] SP /* verilator public_flat */;               // Stack pointer regiser
+       reg[7:0] R[0:3] /* verilator public_flat */;            // General purpose registers
+       reg[11:0] FUTURE_PC /* verilator public_flat */;    // PC to jump to
+
+       localparam STATE_RESET             /*verilator public_flat*/ = 5'b00000;
+       localparam STATE_FETCH_PREP        /*verilator public_flat*/ = 5'b00001;
+       localparam STATE_FETCH_WAIT        /*verilator public_flat*/ = 5'b00010;
+       localparam STATE_FETCH             /*verilator public_flat*/ = 5'b00011;
+       localparam STATE_EXECUTE           /*verilator public_flat*/ = 5'b00100;
+       localparam STATE_FETCH_VALUE_PREP  /*verilator public_flat*/ = 5'b00101;
+       localparam STATE_FETCH_VALUE       /*verilator public_flat*/ = 5'b00110;
+       localparam STATE_EXECUTE_DBL       /*verilator public_flat*/ = 5'b00111;
+       localparam STATE_LOAD_VALUE        /*verilator public_flat*/ = 5'b01000;
+       localparam STATE_LOAD_VALUE_WAIT   /*verilator public_flat*/ = 5'b01001;
+       localparam STATE_ALU_RESULT_WAIT   /*verilator public_flat*/ = 5'b01010;
+       localparam STATE_ALU_RESULT        /*verilator public_flat*/ = 5'b01011;
+       localparam STATE_PUSH_PC_LOW       /*verilator public_flat*/ = 5'b01100;
+       localparam STATE_JUMP              /*verilator public_flat*/ = 5'b01101;
+       localparam STATE_RET_VALUE_WAIT    /*verilator public_flat*/ = 5'b01110;
+       localparam STATE_RET_VALUE         /*verilator public_flat*/ = 5'b01111;
+       localparam STATE_RET_VALUE_WAIT2   /*verilator public_flat*/ = 5'b10000;
+       localparam STATE_RET_VALUE2        /*verilator public_flat*/ = 5'b10001;
+
+       reg [4:0] state /* verilator public_flat */ = STATE_RESET;
+
+       reg [7:0]  alu_a /* verilator public_flat */;
+       reg [7:0]  alu_b /* verilator public_flat */;
+       reg [3:0]  alu_op /* verilator public_flat */;
+
+       reg [1:0]  RESULT_REG /* verilator public_flat */;
+
+       wire [7:0] alu_res /* verilator public_flat */;
+       wire alu_CF /* verilator public_flat */;
+       wire alu_ZF /* verilator public_flat */;
+       wire alu_SF /* verilator public_flat */;
+       reg jump;
+
+       alu alu(.clk(clk),.A(alu_a),.B(alu_b),.operation(alu_op),.result(alu_res),.CF(alu_CF),.ZF(alu_ZF),.SF(alu_SF));
+
+       always @(posedge clk)
+       begin
+               if (reset)
+               begin
+                       state <= STATE_RESET;
+                       hlt   <= 0;
+               end
+               else
+               begin
+                       case (state)
+                               STATE_RESET :
+                                       begin
+                                               PC    <= 12'h000;
+                                               state <= STATE_FETCH_PREP;
+                                               CS    <= 4'h0;
+                                               DS    <= 4'h0;
+                                               R[0]  <= 8'h00;
+                                               R[1]  <= 8'h00;
+                                               R[2]  <= 8'h00;
+                                               R[3]  <= 8'h00;
+                                               SP    <= 12'hfff;
+                                       end
+
+                               STATE_FETCH_PREP :
+                                       begin
+                                               addr  <= PC;
+                                               we    <= 0;
+                                               ioreq <= 0;
+
+                                               state <= STATE_FETCH_WAIT;
+                                       end
+
+                               STATE_FETCH_WAIT :
+                                       begin
+                                               // Sync with memory due to CLK
+                                               state <= (hlt) ? STATE_FETCH_PREP : STATE_FETCH;
+                                       end
+
+                               STATE_FETCH :
+                                       begin
+                                               IR    <= data_in;
+                                               PC    <= PC + 1;
+
+                                               state <= STATE_EXECUTE;
+                                       end
+                               STATE_EXECUTE :
+                                       begin
+                                               `ifdef DISASSEMBLY
+                                               $display("    PC %h R0 %h R1 %h R2 %h R3 %h CS %h DS %h SP %h ALU [%d %d %d]", PC, R[0], R[1], R[2], R[3], CS, DS, SP, alu_CF,alu_SF,alu_ZF);
+                                               `endif
+                                               if (IR[7])
+                                               begin
+                                                       addr  <= PC;
+                                                       state <= STATE_FETCH_VALUE_PREP;
+                                                       PC    <= PC + 1;
+                                               end
+                                               else
+                                               begin
+                                                       case(IR[6:4])
+                                                               3'b000 :
+                                                                       begin
+                                                                               `ifdef DISASSEMBLY
+                                                                               $display("MOV R%d,R%d",IR[3:2],IR[1:0]);
+                                                                               `endif
+                                                                               R[IR[3:2]] <= R[IR[1:0]];
+                                                                               state <= STATE_FETCH_PREP;
+                                                                       end
+                                                               3'b001 :
+                                                                       begin
+                                                                               alu_a   <= R[0];      // first input R0
+                                                                               alu_b   <= R[IR[1:0]];
+                                                                               RESULT_REG <= 0;         // result in R0
+                                                                               alu_op  <= { 2'b00, IR[3:2] };
+
+                                                                               state   <= STATE_ALU_RESULT_WAIT;
+
+                                                                               `ifdef DISASSEMBLY
+                                                                               case(IR[3:2])
+                                                                                       2'b00 : begin
+                                                                                                       $display("ADD R%d",IR[1:0]);
+                                                                                                       end
+                                                                                       2'b01 : begin
+                                                                                                       $display("SUB R%d",IR[1:0]);
+                                                                                                       end
+                                                                                       2'b10 : begin
+                                                                                                       $display("ADC R%d",IR[1:0]);
+                                                                                                       end
+                                                                                       2'b11 : begin
+                                                                                                       $display("SBC R%d",IR[1:0]);
+                                                                                                       end
+                                                                               endcase
+                                                                               `endif
+                                                                       end
+                                                               3'b010 :
+                                                                       begin
+                                                                               alu_a   <= R[0];      // first input R0
+                                                                               alu_b   <= R[IR[1:0]];
+                                                                               RESULT_REG <= 0;         // result in R0
+                                                                               alu_op  <= { 2'b01, IR[3:2] };
+                                                                               state   <= STATE_ALU_RESULT_WAIT;
+                                                                               `ifdef DISASSEMBLY
+                                                                               case(IR[3:2])
+                                                                                       2'b00 : begin
+                                                                                                       $display("AND R%d",IR[1:0]);
+                                                                                                       end
+                                                                                       2'b01 : begin
+                                                                                                       $display("OR R%d",IR[1:0]);
+                                                                                                       end
+                                                                                       2'b10 : begin
+                                                                                                       $display("NOT R%d",IR[1:0]);
+                                                                                                       end
+                                                                                       2'b11 : begin
+                                                                                                       $display("XOR R%d",IR[1:0]);
+                                                                                                       end
+                                                                               endcase
+                                                                               `endif
+                                                                       end
+                                                               3'b011 :
+                                                                       begin
+                                                                               RESULT_REG <= IR[1:0];  // result in REG
+                                                                               // CMP and TEST are not storing result                                                                          
+                                                                               state   <= IR[3] ? STATE_FETCH_PREP : STATE_ALU_RESULT_WAIT;
+                                                                               // CMP and TEST are having first input R0, for INC and DEC is REG
+                                                                               alu_a   <= IR[3] ? R[0] : R[IR[1:0]];                                                           
+                                                                               // CMP and TEST are having second input REG, for INC and DEC is 1
+                                                                               alu_b   <= IR[3] ? R[IR[1:0]] : 8'b00000001;                                                            
+
+                                                                               case(IR[3:2])
+                                                                                       2'b00 : begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("INC R%d",IR[1:0]);
+                                                                                                       `endif
+                                                                                                       alu_op  <= 4'b0001;     // ALU_OP_ADD
+                                                                                                       end
+                                                                                       2'b01 : begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("DEC R%d",IR[1:0]);
+                                                                                                       `endif
+                                                                                                       alu_op  <= 4'b0001;     // ALU_OP_SUB
+                                                                                                       end
+                                                                                       2'b10 : begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("CMP R%d",IR[1:0]);
+                                                                                                       `endif
+                                                                                                       alu_op  <= 4'b0001;     // ALU_OP_SUB
+                                                                                                       end
+                                                                                       2'b11 : begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("TST R%d",IR[1:0]);
+                                                                                                       `endif
+                                                                                                       alu_op  <= 4'b0100;     // ALU_OP_AND
+                                                                                                       end
+                                                                               endcase
+                                                                       end
+                                                               3'b100 :
+                                                                       begin
+                                                                               if (IR[3]==0)
+                                                                               begin
+                                                                                       alu_a   <= R[0];      // first input R0
+                                                                                       // no 2nd input
+                                                                                       RESULT_REG <= 0;         // result in R0
+                                                                                       alu_op  <= { 1'b1, IR[2:0] };
+                                                                                       `ifdef DISASSEMBLY
+                                                                                       case(IR[2:0])
+                                                                                               3'b000 : begin
+                                                                                                               $display("SHL");
+                                                                                                               end
+                                                                                               3'b001 : begin
+                                                                                                               $display("SHR");
+                                                                                                               end
+                                                                                               3'b010 : begin
+                                                                                                               $display("SAL");
+                                                                                                               end
+                                                                                               3'b011 : begin
+                                                                                                               $display("SAR");
+                                                                                                               end
+                                                                                               3'b100 : begin
+                                                                                                               $display("ROL");
+                                                                                                               end
+                                                                                               3'b101 : begin
+                                                                                                               $display("ROR");
+                                                                                                               end
+                                                                                               3'b110 : begin
+                                                                                                               $display("RCL");
+                                                                                                               end
+                                                                                               3'b111 : begin
+                                                                                                               $display("RCR");
+                                                                                                               end
+                                                                                       endcase
+                                                                                       `endif
+                                                                                       state   <= STATE_ALU_RESULT_WAIT;
+                                                                               end
+                                                                               else
+                                                                               begin
+                                                                                       if (IR[2]==0)
+                                                                                       begin
+                                                                                               `ifdef DISASSEMBLY
+                                                                                               $display("PUSH R%d",IR[1:0]);
+                                                                                               `endif
+                                                                                               addr     <= SP;
+                                                                                               we       <= 1;
+                                                                                               ioreq    <= 0;
+                                                                                               data_out <= R[IR[1:0]];
+                                                                                               SP       <= SP - 1;
+                                                                                               state    <= STATE_FETCH_PREP;
+                                                                                       end
+                                                                                       else
+                                                                                       begin
+                                                                                               `ifdef DISASSEMBLY
+                                                                                               $display("POP R%d",IR[1:0]);
+                                                                                               `endif
+                                                                                               addr  <= SP + 1;
+                                                                                               we    <= 0;
+                                                                                               ioreq <= 0;
+                                                                                               RESULT_REG <= IR[1:0];
+                                                                                               SP    <= SP + 1;
+                                                                                               state <= STATE_LOAD_VALUE_WAIT;
+                                                                                       end
+                                                                               end
+                                                                       end
+                                                               3'b101 :
+                                                                       begin
+                                                                               `ifdef DISASSEMBLY
+                                                                               $display("LOAD R%d,[R%d]", IR[3:2], IR[1:0]);
+                                                                               `endif
+                                                                               addr  <= { DS, R[IR[1:0]] };
+                                                                               we    <= 0;
+                                                                               ioreq <= 0;
+                                                                               RESULT_REG <= IR[3:2];
+
+                                                                               state <= STATE_LOAD_VALUE_WAIT;
+                                                                       end
+                                                               3'b110 :
+                                                                       begin
+                                                                               `ifdef DISASSEMBLY
+                                                                               $display("STORE [R%d],R%d", IR[3:2], IR[1:0]);
+                                                                               `endif
+                                                                               addr     <= { DS, R[IR[3:2]] };
+                                                                               we       <= 1;
+                                                                               ioreq    <= 0;
+                                                                               data_out <= R[IR[1:0]];
+
+                                                                               state    <= STATE_FETCH_PREP;
+                                                                       end
+                                                               3'b111 :
+                                                                       begin
+                                                                               // Special instuctions
+                                                                               case(IR[3:2])
+                                                                                       2'b00 : begin
+                                                                                                       CS <= R[IR[1:0]][3:0];
+                                                                                                       state <= STATE_FETCH_PREP;
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("MOV CS,R%d",IR[1:0]);
+                                                                                                       `endif
+                                                                                                       end
+                                                                                       2'b01 : begin
+                                                                                                       DS <= R[IR[1:0]][3:0];
+                                                                                                       state <= STATE_FETCH_PREP;
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("MOV DS,R%d",IR[1:0]);
+                                                                                                       `endif
+                                                                                                       end
+                                                                                       2'b10 : begin
+                                                                                                               case(IR[1:0])
+                                                                                                                       2'b00 : begin
+                                                                                                                                       `ifdef DISASSEMBLY
+                                                                                                                                       $display("PUSH CS");
+                                                                                                                                       `endif
+                                                                                                                                       addr     <= SP;
+                                                                                                                                       we       <= 1;
+                                                                                                                                       ioreq    <= 0;
+                                                                                                                                       data_out <= { 4'b0000, CS};
+                                                                                                                                       SP       <= SP - 1;
+                                                                                                                                       state    <= STATE_FETCH_PREP;
+                                                                                                                                       end
+                                                                                                                       2'b01 : begin
+                                                                                                                                       `ifdef DISASSEMBLY
+                                                                                                                                       $display("PUSH DS");
+                                                                                                                                       `endif
+                                                                                                                                       addr     <= SP;
+                                                                                                                                       we       <= 1;
+                                                                                                                                       ioreq    <= 0;
+                                                                                                                                       data_out <= { 4'b0000, DS};
+                                                                                                                                       SP       <= SP - 1;
+                                                                                                                                       state    <= STATE_FETCH_PREP;
+                                                                                                                                       end
+                                                                                                                       2'b10 : begin
+                                                                                                                                       `ifdef DISASSEMBLY
+                                                                                                                                       $display("Unused opcode");
+                                                                                                                                       `endif
+                                                                                                                                       end
+                                                                                                                       2'b11 : begin
+                                                                                                                                       `ifdef DISASSEMBLY
+                                                                                                                                       $display("Unused opcode");
+                                                                                                                                       `endif
+                                                                                                                               end
+                                                                                                               endcase
+                                                                                                               state <= STATE_FETCH_PREP;
+                                                                                                       end
+                                                                                       2'b11 : begin
+                                                                                                               case(IR[1:0])
+                                                                                                                       2'b00 : begin
+                                                                                                                                       `ifdef DISASSEMBLY
+                                                                                                                                       $display("Unused opcode");
+                                                                                                                                       `endif
+                                                                                                                                       state <= STATE_FETCH_PREP;
+                                                                                                                                       end
+                                                                                                                       2'b01 : begin
+                                                                                                                                       `ifdef DISASSEMBLY
+                                                                                                                                       $display("Unused opcode");
+                                                                                                                                       `endif
+                                                                                                                                       state <= STATE_FETCH_PREP;
+                                                                                                                                       end
+                                                                                                                       2'b10 : begin
+                                                                                                                                       `ifdef DISASSEMBLY
+                                                                                                                                       $display("RET");
+                                                                                                                                       `endif
+                                                                                                                                       addr  <= SP + 1;
+                                                                                                                                       we    <= 0;
+                                                                                                                                       ioreq <= 0;
+                                                                                                                                       SP    <= SP + 1;
+                                                                                                                                       state <= STATE_RET_VALUE_WAIT;
+                                                                                                                                       end
+                                                                                                                       2'b11 : begin
+                                                                                                                                       hlt <= 1;
+                                                                                                                                       `ifdef DISASSEMBLY
+                                                                                                                                       $display("HALT");
+                                                                                                                                       `endif
+                                                                                                                                       state <= STATE_FETCH_PREP;
+                                                                                                                                       end
+                                                                                                               endcase
+                                                                                               end
+                                                                               endcase
+                                                                       end
+                                                       endcase
+                                               end
+                                       end
+                               STATE_FETCH_VALUE_PREP :
+                                       begin
+                                               // Sync with memory due to CLK
+                                               state <= STATE_FETCH_VALUE;
+                                       end
+                               STATE_FETCH_VALUE :
+                                       begin
+                                               VALUE <= data_in;
+                                               state <= STATE_EXECUTE_DBL;
+                                       end
+                               STATE_EXECUTE_DBL :
+                                       begin
+                                               case(IR[6:4])
+                                                       3'b000 :
+                                                               begin
+                                                               if (IR[3]==0)
+                                                                       begin
+                                                                               case(IR[2:0])
+                                                                                       3'b000 :
+                                                                                               begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("JMP %h ",{ CS, VALUE[7:0] });
+                                                                                                       `endif
+                                                                                                       jump = 1;
+                                                                                               end
+                                                                                       3'b001 :
+                                                                                               begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("JC %h ",{CS, VALUE[7:0] });
+                                                                                                       `endif
+                                                                                                       jump = (alu_CF==1);
+                                                                                               end
+                                                                                       3'b010 :
+                                                                                               begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("JNC %h ",{CS, VALUE[7:0] });
+                                                                                                       `endif
+                                                                                                       jump = (alu_CF==0);
+                                                                                               end
+                                                                                       3'b011 :
+                                                                                               begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("JM %h ",{CS, VALUE[7:0] });
+                                                                                                       `endif
+                                                                                                       jump = (alu_SF==1);
+                                                                                               end
+                                                                                       3'b100 :
+                                                                                               begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("JP %h ",{CS, VALUE[7:0] });
+                                                                                                       `endif
+                                                                                                       jump = (alu_SF==0);
+                                                                                               end
+                                                                                       3'b101 :
+                                                                                               begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("JZ %h ",{CS, VALUE[7:0] });
+                                                                                                       `endif
+                                                                                                       jump = (alu_ZF==1);
+                                                                                               end
+                                                                                       3'b110 :
+                                                                                               begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("JNZ %h ",{CS, VALUE[7:0] });
+                                                                                                       `endif
+                                                                                                       jump = (alu_ZF==0);
+                                                                                               end
+                                                                                       3'b111 :
+                                                                                               begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("Unused opcode %h",IR);
+                                                                                                       `endif
+                                                                                                       jump = 0;
+                                                                                               end
+                                                                               endcase
+
+                                                                               if (jump)
+                                                                               begin
+                                                                                       PC    <= { CS, VALUE[7:0] };
+                                                                                       addr  <= { CS, VALUE[7:0] };
+                                                                                       we    <= 0;
+                                                                                       ioreq <= 0;
+                                                                               end
+                                                                               state <= STATE_FETCH_PREP;
+                                                                       end
+                                                               else
+                                                                       begin
+                                                                               case(IR[2:0])
+                                                                                       3'b000 :
+                                                                                               begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("JR %h ", PC + {VALUE[7],VALUE[7],VALUE[7],VALUE[7],VALUE[7:0]} );
+                                                                                                       `endif
+                                                                                                       jump = 1;
+                                                                                               end
+                                                                                       3'b001 :
+                                                                                               begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("JRC %h ",{CS, VALUE[7:0] });
+                                                                                                       `endif
+                                                                                                       jump = (alu_CF==1);
+                                                                                               end
+                                                                                       3'b010 :
+                                                                                               begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("JRNC %h ",{CS, VALUE[7:0] });
+                                                                                                       `endif
+                                                                                                       jump = (alu_CF==0);
+                                                                                               end
+                                                                                       3'b011 :
+                                                                                               begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("JRM %h ",{CS, VALUE[7:0] });
+                                                                                                       `endif
+                                                                                                       jump = (alu_SF==1);
+                                                                                               end
+                                                                                       3'b100 :
+                                                                                               begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("JRP %h ",{CS, VALUE[7:0] });
+                                                                                                       `endif
+                                                                                                       jump = (alu_SF==0);
+                                                                                               end
+                                                                                       3'b101 :
+                                                                                               begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("JRZ %h ",{CS, VALUE[7:0] });
+                                                                                                       `endif
+                                                                                                       jump = (alu_ZF==1);
+                                                                                               end
+                                                                                       3'b110 :
+                                                                                               begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("JRNZ %h ",{CS, VALUE[7:0] });
+                                                                                                       `endif
+                                                                                                       jump = (alu_ZF==0);
+                                                                                               end
+                                                                                       3'b111 :
+                                                                                               begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("Unused opcode %h",IR);
+                                                                                                       `endif
+                                                                                                       jump = 0;
+                                                                                               end
+                                                                               endcase
+                                                                               if (jump)
+                                                                               begin
+                                                                                       PC    <= PC + {VALUE[7],VALUE[7],VALUE[7],VALUE[7],VALUE[7:0]};
+                                                                                       addr  <= PC + {VALUE[7],VALUE[7],VALUE[7],VALUE[7],VALUE[7:0]};
+                                                                                       we    <= 0;
+                                                                                       ioreq <= 0;
+                                                                               end
+                                                                               state <= STATE_FETCH_PREP;
+                                                                       end
+                                                               end
+                                                       3'b001 :
+                                                               begin
+                                                                       `ifdef DISASSEMBLY
+                                                                       $display("JUMP %h ",{ IR[3:0], VALUE[7:0] });
+                                                                       `endif
+                                                                       PC    <= { IR[3:0], VALUE[7:0] };
+                                                                       addr  <= { IR[3:0], VALUE[7:0] };
+                                                                       we    <= 0;
+                                                                       ioreq <= 0;
+                                                                       state <= STATE_FETCH_PREP;
+                                                               end
+                                                       3'b010 :
+                                                               begin
+                                                                       `ifdef DISASSEMBLY
+                                                                       $display("CALL %h ",{ IR[3:0], VALUE[7:0] });
+                                                                       `endif
+                                                                       FUTURE_PC <= { IR[3:0], VALUE[7:0] };
+                                                                       addr     <= SP;
+                                                                       we       <= 1;
+                                                                       ioreq    <= 0;
+                                                                       data_out <= { 4'b0000, PC[11:8]};
+                                                                       SP       <= SP - 1;
+                                                                       state    <= STATE_PUSH_PC_LOW;
+                                                               end
+                                                       3'b011 :
+                                                               begin
+                                                                       `ifdef DISASSEMBLY
+                                                                       $display("MOV SP,%h ",{ IR[3:0], VALUE[7:0] });
+                                                                       `endif
+                                                                       SP <= { IR[3:0], VALUE[7:0] };
+                                                                       state <= STATE_FETCH_PREP;
+                                                               end
+                                                       3'b100 :
+                                                               begin
+                                                                       `ifdef DISASSEMBLY
+                                                                       $display("IN R%d,[0x%h]",IR[1:0], VALUE);
+                                                                       `endif
+                                                                       ioreq <= 1;
+                                                                       we    <= 0;
+                                                                       addr  <= { 4'b0000, VALUE };
+                                                                       RESULT_REG <= IR[1:0];
+                                                                       state    <= STATE_LOAD_VALUE_WAIT;
+                                                               end
+                                                       3'b101 :
+                                                               begin
+                                                                       `ifdef DISASSEMBLY
+                                                                       $display("OUT [0x%h],R%d",VALUE,IR[1:0]);
+                                                                       `endif
+                                                                       ioreq <= 1;
+                                                                       we    <= 1;
+                                                                       addr  <= { 4'b0000, VALUE };
+                                                                       data_out <= R[IR[1:0]];
+                                                                       state    <= STATE_FETCH_PREP;
+                                                               end
+                                                       3'b110 :
+                                                               begin
+                                                                       // Special instuctions
+                                                                       case(IR[1:0])
+                                                                               2'b00 : begin
+                                                                                               `ifdef DISASSEMBLY
+                                                                                               $display("MOV CS,0x%h",VALUE);
+                                                                                               `endif
+                                                                                               CS <= VALUE[3:0];
+                                                                                               state <= STATE_FETCH_PREP;
+                                                                                               end
+                                                                               2'b01 : begin
+                                                                                               `ifdef DISASSEMBLY
+                                                                                               $display("MOV DS,0x%h",VALUE);
+                                                                                               `endif
+                                                                                               DS <= VALUE[3:0];
+                                                                                               state <= STATE_FETCH_PREP;
+                                                                                               end
+                                                                               2'b10 : begin
+                                                                                               `ifdef DISASSEMBLY
+                                                                                               $display("Unused opcode %h",IR);
+                                                                                               `endif
+                                                                                               state <= STATE_FETCH_PREP;
+                                                                                               end
+                                                                               2'b11 : begin
+                                                                                               `ifdef DISASSEMBLY
+                                                                                               $display("Unused opcode %h",IR);
+                                                                                               `endif
+                                                                                               state <= STATE_FETCH_PREP;
+                                                                                               end
+                                                                       endcase
+                                                               end
+                                                       3'b111 :
+                                                               begin
+                                                                       case(IR[3:2])
+                                                                               2'b00 : begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("MOV R%d,0x%h",IR[1:0],VALUE);
+                                                                                                       `endif
+                                                                                                       R[IR[1:0]] <= VALUE;
+                                                                                                       state <= STATE_FETCH_PREP;
+                                                                                               end
+                                                                               2'b01 : begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("LOAD R%d,[0x%h]",IR[1:0], {DS, VALUE});
+                                                                                                       `endif
+                                                                                                       addr  <= { DS, VALUE };
+                                                                                                       we    <= 0;
+                                                                                                       ioreq <= 0;
+                                                                                                       RESULT_REG <= IR[1:0];
+
+                                                                                                       state <= STATE_LOAD_VALUE_WAIT;
+                                                                                               end
+                                                                               2'b10 : begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("STORE [0x%h],R%d", {DS, VALUE}, IR[1:0]);
+                                                                                                       `endif
+                                                                                                       addr     <= { DS, VALUE };
+                                                                                                       we       <= 1;
+                                                                                                       ioreq    <= 0;
+                                                                                                       data_out <= R[IR[1:0]];
+
+                                                                                                       state    <= STATE_FETCH_PREP;
+                                                                                               end
+                                                                               2'b11 : begin
+                                                                                                       `ifdef DISASSEMBLY
+                                                                                                       $display("Unused opcode %h",IR);
+                                                                                                       `endif
+                                                                                                       state <= STATE_FETCH_PREP;
+                                                                                               end
+                                                                       endcase
+                                                               end
+                                               endcase
+                                       end
+                               STATE_LOAD_VALUE_WAIT :
+                                       begin
+                                               // Sync with memory due to CLK
+                                               state <= STATE_LOAD_VALUE;
+                                       end
+                               STATE_LOAD_VALUE :
+                                       begin
+                                               R[RESULT_REG] <= data_in;
+                                               we    <= 0;
+                                               state <= STATE_FETCH_PREP;
+                                       end
+                               STATE_ALU_RESULT_WAIT :
+                                       begin
+                                               state <= STATE_ALU_RESULT;
+                                       end
+                               STATE_ALU_RESULT :
+                                       begin
+                                               R[RESULT_REG] <= alu_res;
+                                               state <= STATE_FETCH_PREP;
+                                       end
+                               STATE_PUSH_PC_LOW :
+                                       begin
+                                               addr     <= SP;
+                                               we       <= 1;
+                                               ioreq    <= 0;
+                                               data_out <= PC[7:0];
+                                               SP       <= SP - 1;
+                                               state    <= STATE_JUMP;
+                                       end
+                               STATE_JUMP :
+                                       begin
+                                               `ifdef DISASSEMBLY
+                                               $display("Jumping to %h",FUTURE_PC);
+                                               `endif
+                                               PC <= FUTURE_PC;
+                                               state <= STATE_FETCH_PREP;
+                                       end
+                               STATE_RET_VALUE_WAIT :
+                                       begin
+                                               // Sync with memory due to CLK
+                                               state <= STATE_RET_VALUE;
+                                       end
+                               STATE_RET_VALUE :
+                                       begin
+                                               FUTURE_PC <= { 4'b0000, data_in };
+                                               we    <= 0;
+                                               state <= STATE_RET_VALUE_WAIT2;
+
+                                               addr  <= SP + 1;
+                                               we    <= 0;
+                                               ioreq <= 0;
+                                               SP    <= SP + 1;
+                                       end
+                               STATE_RET_VALUE_WAIT2 :
+                                       begin
+                                               // Sync with memory due to CLK
+                                               state <= STATE_RET_VALUE2;
+                                       end
+                               STATE_RET_VALUE2 :
+                                       begin
+                                               FUTURE_PC <= FUTURE_PC | ({ 4'b0000, data_in } << 8);
+                                               we    <= 0;
+                                               state <= STATE_JUMP;
+                                       end
+                               default :
+                                       begin
+                                               state <= STATE_FETCH_PREP;
+                                       end
+                       endcase
+               end
+       end
+endmodule
diff --git a/tests/sat/ram_memory.v b/tests/sat/ram_memory.v
new file mode 100644 (file)
index 0000000..053ef20
--- /dev/null
@@ -0,0 +1,37 @@
+module ram_memory(
+  input clk,
+  input [11:0] addr,
+  input [7:0] data_in,
+  input we,
+  output reg [7:0] data_out
+);
+
+  reg [7:0] store[0:4095] /* verilator public_flat */;
+
+  initial
+  begin
+       store[0] <= 8'b11100001; // MOV DS,2
+       store[1] <= 8'b00000010; //
+       store[2] <= 8'b01010100; // LOAD R1,[R0]
+       store[3] <= 8'b00110001; // INC R1
+       store[4] <= 8'b00110001; // INC R1
+       store[5] <= 8'b01100001; // STORE [R0],R1
+       store[6] <= 8'b11010001; // OUT [0],R1
+       store[7] <= 8'b00000000; //
+       store[8] <= 8'b00110001; // INC R1
+       store[9] <= 8'b10100001; // CALL 0x100
+       store[10] <= 8'b00000000; //
+       store[11] <= 8'b01111111; // HLT
+
+
+       store[256] <= 8'b11010001; // OUT [0],R1
+       store[257] <= 8'b00000000; //
+       store[258] <= 8'b01111110; // RET
+  end
+
+  always @(posedge clk)
+       if (we)
+         store[addr] <= data_in;
+       else
+         data_out <= store[addr];
+endmodule
diff --git a/tests/sat/sim_counter.ys b/tests/sat/sim_counter.ys
new file mode 100644 (file)
index 0000000..a0ff41b
--- /dev/null
@@ -0,0 +1,48 @@
+# Create stimulus file
+read_verilog <<EOT
+module top (clk, reset, cnt);
+
+input          clk;
+input          reset;
+output [7:0]   cnt;
+
+reg    [7:0]   cnt;
+
+endmodule
+EOT
+prep -top top;
+sim -clock clk -reset reset -fst stimulus.fst -n 10
+design -reset
+
+# Counter implementation
+read_verilog <<EOT
+module top (clk, reset, cnt);
+
+input          clk;
+input          reset;
+output [7:0]   cnt;
+
+reg    [7:0]   cnt;
+
+always @(posedge clk)
+       if (!reset)
+               cnt = cnt + 1;
+       else
+               cnt = 0;
+
+endmodule
+EOT
+prep -top top;
+
+# Simulate with stimulus
+sim -clock clk -scope top -r stimulus.fst
+
+# Stimulus does not have counter values
+# x in FST can match any value in simulation
+sim -clock clk -scope top -r stimulus.fst -sim-gate
+
+# Stimulus does not have counter values
+# x in simulation can match any value in FST
+# so we expect error
+logger -expect error "Signal difference" 1
+sim -clock clk -scope top -r stimulus.fst -sim-gold