mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-07 01:54:10 +00:00
Add test cases for co-simulation
This commit is contained in:
parent
4a30c9cb94
commit
7ef6da4c7d
2
tests/sat/.gitignore
vendored
2
tests/sat/.gitignore
vendored
|
@ -1,2 +1,4 @@
|
||||||
*.log
|
*.log
|
||||||
run-test.mk
|
run-test.mk
|
||||||
|
*.vcd
|
||||||
|
*.fst
|
||||||
|
|
79
tests/sat/alu.v
Normal file
79
tests/sat/alu.v
Normal file
|
@ -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
|
||||||
|
|
9
tests/sat/grom.ys
Normal file
9
tests/sat/grom.ys
Normal file
|
@ -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
|
31
tests/sat/grom_computer.v
Normal file
31
tests/sat/grom_computer.v
Normal file
|
@ -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
|
747
tests/sat/grom_cpu.v
Normal file
747
tests/sat/grom_cpu.v
Normal file
|
@ -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
|
37
tests/sat/ram_memory.v
Normal file
37
tests/sat/ram_memory.v
Normal file
|
@ -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
|
48
tests/sat/sim_counter.ys
Normal file
48
tests/sat/sim_counter.ys
Normal file
|
@ -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
|
Loading…
Reference in a new issue