diff --git a/Makefile b/Makefile index ecf7648..ba18355 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,7 @@ block_memory_tb: rm sim.out io_core_tb: - iverilog -g2012 -o sim.out -y src/manta \ + iverilog -g2012 -o sim.out \ test/functional_sim/io_core_tb/io_core_tb.sv \ test/functional_sim/io_core_tb/io_core.v vvp sim.out diff --git a/test/functional_sim/io_core_tb/io_core.v b/test/functional_sim/io_core_tb/io_core.v index e4caa92..8f8daa7 100644 --- a/test/functional_sim/io_core_tb/io_core.v +++ b/test/functional_sim/io_core_tb/io_core.v @@ -2,19 +2,20 @@ `timescale 1ns/1ps module io_core( - input wire clk, + input wire bus_clk, + input wire user_clk, // inputs - input wire picard, - input wire [6:0] data, - input wire [9:0] laforge, - input wire troi, + input wire probe0, + input wire [1:0] probe1, + input wire [7:0] probe2, + input wire [19:0] probe3, // outputs - output reg kirk, - output reg [4:0] spock, - output reg [2:0] uhura, - output reg chekov, + output reg probe4, + output reg [1:0] probe5, + output reg [7:0] probe6, + output reg [19:0] probe7, // input port input wire [15:0] addr_i, @@ -31,41 +32,83 @@ module io_core( parameter BASE_ADDR = 0; + reg strobe = 0; + + // configure buffers + // inputs + reg probe0_buf = 0; + reg [1:0] probe1_buf = 0; + reg [7:0] probe2_buf = 0; + reg [19:0] probe3_buf = 0; + + // outputs + reg probe4_buf = 1; // PROBE4_INITIAL_VALUE; + reg [1:0] probe5_buf = 3; // PROBE5_INITIAL_VALUE; + reg [7:0] probe6_buf = 6; // PROBE6_INITIAL_VALUE; + reg [19:0] probe7_buf = 7; // PROBE7_INITIAL_VALUE; + initial begin - kirk = 0; - spock = 0; - uhura = 0; - chekov = 0; + probe4 = 1; // PROBE4_INITIAL_VALUE; + probe5 = 3; // PROBE5_INITIAL_VALUE; + probe6 = 6; // PROBE6_INITIAL_VALUE; + probe7 = 7; // PROBE7_INITIAL_VALUE; end - always @(posedge clk) begin + // synchronize buffers and probes on strobe + always @(posedge user_clk) begin + if(strobe) begin + // update input buffers from input probes + probe0_buf <= probe0; + probe1_buf <= probe1; + probe2_buf <= probe2; + probe3_buf <= probe3; + + // update output buffers from output probes + probe4 <= probe4_buf; + probe5 <= probe5_buf; + probe6 <= probe6_buf; + probe7 <= probe7_buf; + end + end + + + // handle bus operations + always @(posedge bus_clk) begin addr_o <= addr_i; data_o <= data_i; rw_o <= rw_i; valid_o <= valid_i; // check if address is valid - if( (valid_i) && (addr_i >= BASE_ADDR) && (addr_i <= BASE_ADDR + 7)) begin + if( (valid_i) && (addr_i >= BASE_ADDR) && (addr_i <= BASE_ADDR + 10)) begin if(!rw_i) begin // reads case (addr_i) - BASE_ADDR + 0: data_o <= {15'b0, picard}; - BASE_ADDR + 1: data_o <= {9'b0, data}; - BASE_ADDR + 2: data_o <= {6'b0, laforge}; - BASE_ADDR + 3: data_o <= {15'b0, troi}; - BASE_ADDR + 4: data_o <= {15'b0, kirk}; - BASE_ADDR + 5: data_o <= {11'b0, spock}; - BASE_ADDR + 6: data_o <= {13'b0, uhura}; - BASE_ADDR + 7: data_o <= {15'b0, chekov}; + BASE_ADDR + 0: data_o <= strobe; + + BASE_ADDR + 1: data_o <= probe0_buf; // width 1 + BASE_ADDR + 2: data_o <= probe1_buf; // width 2 + BASE_ADDR + 3: data_o <= probe2_buf; // width 8 + BASE_ADDR + 4: data_o <= probe3_buf[15:0]; // width 20 + BASE_ADDR + 5: data_o <= probe3_buf[19:16]; + + BASE_ADDR + 6: data_o <= probe4_buf; // width 1 + BASE_ADDR + 7: data_o <= probe5_buf; // width 2 + BASE_ADDR + 8: data_o <= probe6_buf; // width 8 + BASE_ADDR + 9: data_o <= probe7_buf[15:0]; // width 20 + BASE_ADDR + 10: data_o <= probe7_buf[19:16]; endcase end else begin // writes case (addr_i) - BASE_ADDR + 4: kirk <= data_i[0]; - BASE_ADDR + 5: spock <= data_i[4:0]; - BASE_ADDR + 6: uhura <= data_i[2:0]; - BASE_ADDR + 7: chekov <= data_i[0]; + BASE_ADDR + 0: strobe <= data_i[0]; + + BASE_ADDR + 6: probe4_buf <= data_i[0]; + BASE_ADDR + 7: probe5_buf <= data_i[1:0]; + BASE_ADDR + 8: probe6_buf <= data_i[7:0]; + BASE_ADDR + 9: probe7_buf[15:0] <= data_i; + BASE_ADDR + 10: probe7_buf[19:16] <= data_i[3:0]; endcase end end diff --git a/test/functional_sim/io_core_tb/io_core_tb.sv b/test/functional_sim/io_core_tb/io_core_tb.sv index de350bc..3a1caef 100644 --- a/test/functional_sim/io_core_tb/io_core_tb.sv +++ b/test/functional_sim/io_core_tb/io_core_tb.sv @@ -3,6 +3,65 @@ `define CP 10 `define HCP 5 +task read_reg ( + input [15:0] addr, + output [15:0] data, + input string desc + ); + + io_core_tb.tb_io_addr = addr; + io_core_tb.tb_io_rw = 0; + io_core_tb.tb_io_valid = 1; + #`CP + io_core_tb.tb_io_valid = 0; + while (!io_core_tb.io_tb_valid) #`CP; + data = io_core_tb.io_tb_data; + + $display(" -> read 0x%h from addr 0x%h (%s)", data, addr, desc); +endtask + +task write_reg( + input [15:0] addr, + input [15:0] data, + input string desc + ); + + io_core_tb.tb_io_addr = addr; + io_core_tb.tb_io_data = data; + io_core_tb.tb_io_rw = 1; + io_core_tb.tb_io_valid = 1; + #`CP + io_core_tb.tb_io_valid = 0; + while (!io_core_tb.io_tb_valid) #`CP; + + $display(" -> wrote 0x%h to addr 0x%h (%s)", data, addr, desc); +endtask + +task write_and_verify( + input [15:0] addr, + input [15:0] write_data, + input string desc + ); + + reg [15:0] read_data; + + write_reg(addr, write_data, desc); + read_reg(addr, read_data, desc); + assert(read_data == write_data) else $fatal(0, "data read does not match data written!"); +endtask + +// task read_all_reg(); +// string desc; +// for(int i = 0; i < (io_core_tb.la.block_mem.MAX_ADDR); i++) begin + +// if(i == io_core_tb.la.fsm_registers.BASE_ADDR) desc = "FSM"; +// if(i == io_core_tb.la.trig_blk.BASE_ADDR) desc = "TRIG BLK"; +// if(i == io_core_tb.la.block_mem.BASE_ADDR) desc = "SAMPLE MEM"; + +// read_reg(i, io_core_tb.read_value, desc); +// end +// endtask + module io_core_tb; // boilerplate @@ -10,16 +69,16 @@ module io_core_tb; integer test_num; // inputs - logic picard; - logic [6:0] data; - logic [9:0] laforge; - logic troi; + logic probe0; + logic [1:0] probe1; + logic [7:0] probe2; + logic [19:0] probe3; // outputs - logic kirk; - logic [4:0] spock; - logic [2:0] uhura; - logic chekov; + logic probe4; + logic [1:0] probe5; + logic [7:0] probe6; + logic [19:0] probe7; // tb -> io bus logic [15:0] tb_io_addr; @@ -28,26 +87,27 @@ module io_core_tb; logic tb_io_valid; // la -> io bus - logic [15:0] la_tb_addr; - logic [15:0] la_tb_data; - logic la_tb_rw; - logic la_tb_valid; + logic [15:0] io_tb_addr; + logic [15:0] io_tb_data; + logic io_tb_rw; + logic io_tb_valid; io_core #(.BASE_ADDR(0)) io( - .clk(clk), + .bus_clk(clk), + .user_clk(clk), // inputs - .picard(picard), - .data(data), - .laforge(laforge), - .troi(troi), + .probe0(probe0), + .probe1(probe1), + .probe2(probe2), + .probe3(probe3), // outputs - .kirk(kirk), - .spock(spock), - .uhura(uhura), - .chekov(chekov), + .probe4(probe4), + .probe5(probe5), + .probe6(probe6), + .probe7(probe7), // input port .addr_i(tb_io_addr), @@ -56,16 +116,18 @@ module io_core_tb; .valid_i(tb_io_valid), // output port - .addr_o(la_tb_addr), - .data_o(la_tb_data), - .rw_o(la_tb_rw), - .valid_o(la_tb_valid)); + .addr_o(io_tb_addr), + .data_o(io_tb_data), + .rw_o(io_tb_rw), + .valid_o(io_tb_valid)); always begin #`HCP clk = !clk; end + logic [15:0] read_data; + initial begin $dumpfile("io_core_tb.vcd"); $dumpvars(0, io_core_tb); @@ -79,28 +141,134 @@ module io_core_tb; tb_io_rw = 0; tb_io_valid = 0; - picard = 0; - data = 0; - laforge = 0; - troi = 0; + probe0 = 0; + probe1 = 1; + probe2 = 2; + probe3 = 3; - #`HCP + // #`HCP #(10*`CP); /* ==== Test 1 Begin ==== */ - $display("\n=== test 1: read state register ==="); + $display("\n=== test 1: read initial register states ==="); test_num = 1; + read_reg(0, read_data, "strobe"); + read_reg(1, read_data, "probe0"); + read_reg(2, read_data, "probe1"); + read_reg(3, read_data, "probe2"); + read_reg(4, read_data, "probe3[15:0]"); + read_reg(5, read_data, "probe3[19:16]"); - tb_io_addr = 0; - tb_io_valid = 1; - #`CP - tb_io_valid = 0; - while (!la_tb_valid) #`CP; - $display(" -> read 0x%h from state reg (addr 0x0000)", la_tb_data); + read_reg(6, read_data, "probe4"); + read_reg(7, read_data, "probe5"); + read_reg(8, read_data, "probe6"); + read_reg(9, read_data, "probe7[15:0]"); + read_reg(10, read_data, "probe7[19:16]"); + #(10*`CP); + /* ==== Test 1 End ==== */ + + /* ==== Test 2 Begin ==== */ + $display("\n=== test 2: assert input buffers initialized correctly ==="); + test_num = 2; + read_reg(0, read_data, "strobe"); + assert(read_data == 0) else $fatal(0, "strobe does not initialize to zero!"); + assert(io.strobe == 0) else $fatal(0, "strobe does not initialize to zero!"); + + read_reg(1, read_data, "probe0"); + assert(read_data == 0) else $fatal(0, "probe0_buf does not initialize to zero!"); + assert(io.probe0_buf == 0) else $fatal(0, "probe0_buf does not initialize to zero!"); + + read_reg(2, read_data, "probe1"); + assert(read_data == 0) else $fatal(0, "probe1_buf does not initialize to zero!"); + assert(io.probe1_buf == 0) else $fatal(0, "probe1_buf does not initialize to zero!"); + + read_reg(3, read_data, "probe2"); + assert(read_data == 0) else $fatal(0, "probe2_buf does not initialize to zero!"); + assert(io.probe2_buf == 0) else $fatal(0, "probe2_buf does not initialize to zero!"); + + read_reg(4, read_data, "probe3[15:0]"); + assert(read_data == 0) else $fatal(0, "probe3_buf does not initialize to zero!"); + read_reg(5, read_data, "probe3[19:16]"); + assert(read_data == 0) else $fatal(0, "probe3_buf does not initialize to zero!"); + assert(io.probe3_buf == 0) else $fatal(0, "probe3_buf does not initialize to zero!"); + + #(10*`CP); + /* ==== Test 2 End ==== */ + + + /* ==== Test 3 Begin ==== */ + $display("\n=== test 3: assert outputs and output buffers initialized correctly ==="); + test_num = 3; + read_reg(6, read_data, "probe4"); + assert(read_data == 1) else $fatal(0, "probe4 does not initialize correctly!"); + assert(io.probe4_buf == 1) else $fatal(0, "probe4_buf does not initialize correctly!"); + assert(io.probe4 == 1) else $fatal(0, "probe4 does not initialize correctly!"); + + read_reg(7, read_data, "probe5"); + assert(read_data == 3) else $fatal(0, "probe5 does not initialize correctly!"); + assert(io.probe5_buf == 3) else $fatal(0, "probe5_buf does not initialize correctly!"); + assert(io.probe5 == 3) else $fatal(0, "probe5 does not initialize correctly!"); + + read_reg(8, read_data, "probe6"); + assert(read_data == 6) else $fatal(0, "probe6 does not initialize correctly!"); + assert(io.probe6_buf == 6) else $fatal(0, "probe6_buf does not initialize correctly!"); + assert(io.probe6 == 6) else $fatal(0, "probe6 does not initialize correctly!"); + + read_reg(9, read_data, "probe7[15:0]"); + assert(read_data == 7) else $fatal(0, "probe7 does not initialize correctly!"); + read_reg(10, read_data, "probe7[19:16]"); + assert(read_data == 0) else $fatal(0, "probe7 does not initialize correctly!"); + assert(io.probe7_buf == 7) else $fatal(0, "probe7_buf does not initialize correctly!"); + assert(io.probe7 == 7) else $fatal(0, "probe7 does not initialize correctly!"); #(10*`CP); - /* ==== Test 1 End ==== */ + /* ==== Test 3 End ==== */ + + /* ==== Test 4 Begin ==== */ + $display("\n=== test 4: write new output value to each output probe==="); + test_num = 4; + write_reg(6, 0, "probe4"); + assert(io.probe4_buf == 0) else $fatal(0, "probe4_buf does not update correctly!"); + assert(io.probe4 != 0) else $fatal(0, "probe4 updated without strobing!"); + + write_reg(7, 0, "probe5"); + assert(io.probe5_buf == 0) else $fatal(0, "probe5_buf does not update correctly!"); + assert(io.probe5 != 0) else $fatal(0, "probe5 updated without strobing!"); + + write_reg(8, 0, "probe6"); + assert(io.probe6_buf == 0) else $fatal(0, "probe6_buf does not update correctly!"); + assert(io.probe6 != 0) else $fatal(0, "probe6 updated without strobing!"); + + write_reg(9, 0, "probe7[15:0]"); + write_reg(10, 0, "probe7[19:16]"); + assert(io.probe7_buf == 0) else $fatal(0, "probe7_buf does not update correctly!"); + assert(io.probe7 != 0) else $fatal(0, "probe7 updated without strobing!"); + #(10*`CP); + /* ==== Test 4 End ==== */ + + /* ==== Test 5 Begin ==== */ + $display("\n=== test 5: strobe core, check that inputs and outputs updated ==="); + test_num = 5; + + write_reg(0, 1, "strobe"); + write_reg(0, 0, "strobe"); + + assert(io.probe4 == 0) else $fatal(0, "probe4 did not update correctly!"); + assert(io.probe5 == 0) else $fatal(0, "probe5 did not update correctly!"); + assert(io.probe6 == 0) else $fatal(0, "probe6 did not update correctly!"); + assert(io.probe7 == 0) else $fatal(0, "probe7 did not update correctly!"); + + assert(io.probe0_buf == 0) else $fatal(0, "probe0_buf did not update correctly!"); + assert(io.probe1_buf == 1) else $fatal(0, "probe1_buf did not update correctly!"); + assert(io.probe2_buf == 2) else $fatal(0, "probe2_buf did not update correctly!"); + assert(io.probe3_buf == 3) else $fatal(0, "probe3_buf did not update correctly!"); + assert(io.probe4_buf == 0) else $fatal(0, "probe4_buf did not update correctly!"); + assert(io.probe5_buf == 0) else $fatal(0, "probe5_buf did not update correctly!"); + assert(io.probe6_buf == 0) else $fatal(0, "probe6_buf did not update correctly!"); + assert(io.probe7_buf == 0) else $fatal(0, "probe7_buf did not update correctly!"); + /* ==== Test 5 End ==== */ + $finish(); end diff --git a/test/functional_sim/io_core_tb/manta.yaml b/test/functional_sim/io_core_tb/manta.yaml new file mode 100644 index 0000000..ffe248d --- /dev/null +++ b/test/functional_sim/io_core_tb/manta.yaml @@ -0,0 +1,15 @@ +--- +io_core: + type: io + + inputs: + probe0: 1 + probe1: 2 + probe2: 8 + probe3: 20 + + outputs: + probe4: 1 + probe5: 2 + probe6: 8 + probe7: 20