add beginnings of working io_core with CDC/large inputs

This commit is contained in:
Fischer Moseley 2023-08-29 08:21:28 -07:00
parent 3fe95b75d8
commit 49021411ea
4 changed files with 292 additions and 66 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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