clean up testbenches, add Makefile for sims

This commit is contained in:
Fischer Moseley 2023-03-07 13:02:40 -05:00
parent e022696b31
commit 4d9792702a
12 changed files with 411 additions and 298 deletions

48
Makefile Normal file
View File

@ -0,0 +1,48 @@
build:
python3 -m build
pypi_upload: build
python3 -m twine upload --repository testpypi dist/*
sim: sim_bit_fifo sim_bridge_rx sim_bridge_tx fifo_tb lut_mem_tb uart_tx_tb
sim_bit_fifo:
iverilog -g2012 -o sim.out test/bit_fifo_tb.sv src/manta/bit_fifo.v
vvp sim.out
rm sim.out
sim_bridge_rx:
iverilog -g2012 -o sim.out test/bridge_rx_tb.sv src/manta/bridge_rx.v
vvp sim.out
rm sim.out
sim_bridge_tx:
iverilog -g2012 -o sim.out test/bridge_tx_tb.sv src/manta/bridge_tx.v src/manta/uart_tx.v
vvp sim.out
rm sim.out
fifo_tb:
iverilog -g2012 -o sim.out test/fifo_tb.sv src/manta/fifo.v src/manta/xilinx_true_dual_port_read_first_2_clock_ram.v
vvp sim.out >> /dev/null # this one is noisy right now
rm sim.out
lut_mem_tb:
iverilog -g2012 -o sim.out test/lut_mem_tb.sv src/manta/lut_mem.v
vvp sim.out
rm sim.out
uart_tb:
iverilog -g2012 -o sim.out test/uart_tb.sv src/manta/tx_uart.v src/manta/uart_rx.v
vvp sim.out
rm sim.out
uart_tx_tb:
iverilog -g2012 -o sim.out test/uart_tx_tb.sv src/manta/tx_uart.v src/manta/uart_tx.v src/manta/rx_uart.v
vvp sim.out
rm sim.out
clean:
rm *.out *.vcd
rm -rf dist/

View File

@ -4,16 +4,20 @@
module bridge_rx(
input wire clk,
input wire[7:0] axiid,
input wire axiiv,
input wire[7:0] rx_data,
input wire rx_valid,
output reg[15:0] req_addr,
output reg[15:0] req_data,
output reg req_rw,
output reg req_valid,
input wire req_ready
output reg[15:0] addr_o,
output reg[15:0] wdata_o,
output reg rw_o,
output reg valid_o
);
// this is a hack, the FSM needs to be updated
// but this will bypass it for now
parameter ready_i = 1;
parameter ADDR_WIDTH = 0;
parameter DATA_WIDTH = 0;
@ -30,40 +34,40 @@ reg [3:0] bytes_received;
// no global resets!
initial begin
req_addr = 0;
req_data = 0;
req_rw = 0;
req_valid = 0;
addr_o = 0;
wdata_o = 0;
rw_o = 0;
valid_o = 0;
bytes_received = 0;
state = ACQUIRE;
end
reg [3:0] axiid_decoded;
reg axiid_is_0_thru_9;
reg axiid_is_A_thru_F;
reg [3:0] rx_data_decoded;
reg rx_data_is_0_thru_9;
reg rx_data_is_A_thru_F;
always @(*) begin
axiid_is_0_thru_9 = (axiid >= 8'h30) & (axiid <= 8'h39);
axiid_is_A_thru_F = (axiid >= 8'h41) & (axiid <= 8'h46);
rx_data_is_0_thru_9 = (rx_data >= 8'h30) & (rx_data <= 8'h39);
rx_data_is_A_thru_F = (rx_data >= 8'h41) & (rx_data <= 8'h46);
if (axiid_is_0_thru_9) axiid_decoded = axiid - 8'h30;
else if (axiid_is_A_thru_F) axiid_decoded = axiid - 8'h41 + 'd10;
else axiid_decoded = 0;
if (rx_data_is_0_thru_9) rx_data_decoded = rx_data - 8'h30;
else if (rx_data_is_A_thru_F) rx_data_decoded = rx_data - 8'h41 + 'd10;
else rx_data_decoded = 0;
end
always @(posedge clk) begin
if (state == ACQUIRE) begin
if(axiiv) begin
if(rx_valid) begin
if (bytes_received == 0) begin
if(axiid == PREAMBLE) bytes_received <= 1;
if(rx_data == PREAMBLE) bytes_received <= 1;
end
else if( (bytes_received >= 1) & (bytes_received <= 4) ) begin
// only advance if byte is valid hex digit
if(axiid_is_0_thru_9 | axiid_is_A_thru_F) begin
req_addr <= (req_addr << 4) | axiid_decoded;
if(rx_data_is_0_thru_9 | rx_data_is_A_thru_F) begin
addr_o <= (addr_o << 4) | rx_data_decoded;
bytes_received <= bytes_received + 1;
end
@ -71,16 +75,16 @@ always @(posedge clk) begin
end
else if( bytes_received == 5) begin
if( (axiid == CR) | (axiid == LF)) begin
req_valid <= 1;
req_rw = 0;
if( (rx_data == CR) | (rx_data == LF)) begin
valid_o <= 1;
rw_o = 0;
bytes_received <= 0;
state <= TRANSMIT;
end
else if (axiid_is_0_thru_9 | axiid_is_A_thru_F) begin
else if (rx_data_is_0_thru_9 | rx_data_is_A_thru_F) begin
bytes_received <= bytes_received + 1;
req_data <= (req_data << 4) | axiid_decoded;
wdata_o <= (wdata_o << 4) | rx_data_decoded;
end
else state <= ERROR;
@ -88,8 +92,8 @@ always @(posedge clk) begin
else if ( (bytes_received >= 6) & (bytes_received <= 8) ) begin
if (axiid_is_0_thru_9 | axiid_is_A_thru_F) begin
req_data <= (req_data << 4) | axiid_decoded;
if (rx_data_is_0_thru_9 | rx_data_is_A_thru_F) begin
wdata_o <= (wdata_o << 4) | rx_data_decoded;
bytes_received <= bytes_received + 1;
end
@ -98,9 +102,9 @@ always @(posedge clk) begin
else if (bytes_received == 9) begin
bytes_received <= 0;
if( (axiid == CR) | (axiid == LF)) begin
req_valid <= 1;
req_rw <= 1;
if( (rx_data == CR) | (rx_data == LF)) begin
valid_o <= 1;
rw_o <= 1;
state <= TRANSMIT;
end
@ -111,14 +115,14 @@ always @(posedge clk) begin
else if (state == TRANSMIT) begin
if(req_ready) begin
req_valid <= 0;
if(ready_i) begin
valid_o <= 0;
state <= ACQUIRE;
end
if(axiiv) begin
if ( (axiid != CR) & (axiid != LF)) begin
req_valid <= 0;
if(rx_valid) begin
if ( (rx_data != CR) & (rx_data != LF)) begin
valid_o <= 0;
state <= ERROR;
end
end

View File

@ -7,9 +7,9 @@ module bridge_tx(
input wire [15:0] rdata_i,
input wire rw_i,
input wire valid_i,
input wire ready_i,
output reg [7:0] data_o,
input wire ready_i,
output reg valid_o);
localparam PREAMBLE = 8'h4D;

84
src/manta/fifo.v Normal file
View File

@ -0,0 +1,84 @@
`default_nettype none
`timescale 1ns / 1ps
module fifo (
input wire clk,
input wire rst,
input wire [WIDTH - 1:0] data_in,
input wire input_ready,
input wire request_output,
output reg [WIDTH - 1:0] data_out,
output reg output_valid,
output reg [AW:0] size,
output reg empty,
output reg full
);
parameter WIDTH = 8;
parameter DEPTH = 4096;
localparam AW = $clog2(DEPTH);
reg [AW:0] write_pointer;
reg [AW:0] read_pointer;
reg empty_int;
assign empty_int = (write_pointer[AW] == read_pointer[AW]);
reg full_or_empty;
assign full_or_empty = (write_pointer[AW-1:0] == read_pointer[AW-1:0]);
assign full = full_or_empty & !empty_int;
assign empty = full_or_empty & empty_int;
assign size = write_pointer - read_pointer;
reg output_valid_pip_0;
reg output_valid_pip_1;
always @(posedge clk) begin
if (input_ready && ~full)
write_pointer <= write_pointer + 1'd1;
if (request_output && ~empty)
read_pointer <= read_pointer + 1'd1;
output_valid_pip_0 <= request_output;
output_valid_pip_1 <= output_valid_pip_0;
output_valid <= output_valid_pip_1;
if (rst) begin
read_pointer <= 0;
write_pointer <= 0;
end
end
xilinx_true_dual_port_read_first_2_clock_ram #(
.RAM_WIDTH(WIDTH),
.RAM_DEPTH(DEPTH),
.RAM_PERFORMANCE("HIGH_PERFORMANCE")
) buffer (
// write port
.clka(clk),
.rsta(rst),
.ena(1),
.addra(write_pointer),
.dina(data_in),
.wea(input_ready),
.regcea(1),
.douta(),
// read port
.clkb(clk),
.rstb(rst),
.enb(1),
.addrb(read_pointer),
.dinb(),
.web(0),
.regceb(1),
.doutb(data_out));
endmodule
`default_nettype wire

View File

@ -21,6 +21,7 @@ module lut_mem(
parameter DEPTH = 8;
parameter BASE_ADDR = 0;
parameter READ_ONLY = 0;
reg [DEPTH-1:0][15:0] mem;
always @(posedge clk) begin
@ -37,7 +38,7 @@ always @(posedge clk) begin
if( (addr_i >= BASE_ADDR) && (addr_i <= BASE_ADDR + DEPTH - 1) ) begin
// read/write
if (rw_i) mem[addr_i - BASE_ADDR] <= wdata_i;
if (rw_i && !READ_ONLY) mem[addr_i - BASE_ADDR] <= wdata_i;
else rdata_o <= mem[addr_i - BASE_ADDR];
end
end

View File

@ -0,0 +1,149 @@
// Xilinx True Dual Port RAM, Read First, Dual Clock
// This code implements a parameterizable true dual port memory (both ports can read and write).
// The behavior of this RAM is when data is written, the prior memory contents at the write
// address are presented on the output port. If the output data is
// not needed during writes or the last read value is desired to be retained,
// it is suggested to use a no change RAM as it is more power efficient.
// If a reset or enable is not necessary, it may be tied off or removed from the code.
module xilinx_true_dual_port_read_first_2_clock_ram #(
parameter RAM_WIDTH = 18, // Specify RAM data width
parameter RAM_DEPTH = 1024, // Specify RAM depth (number of entries)
parameter RAM_PERFORMANCE = "HIGH_PERFORMANCE", // Select "HIGH_PERFORMANCE" or "LOW_LATENCY"
parameter INIT_FILE = "" // Specify name/location of RAM initialization file if using one (leave blank if not)
) (
input [clogb2(RAM_DEPTH-1)-1:0] addra, // Port A address bus, width determined from RAM_DEPTH
input [clogb2(RAM_DEPTH-1)-1:0] addrb, // Port B address bus, width determined from RAM_DEPTH
input [RAM_WIDTH-1:0] dina, // Port A RAM input data
input [RAM_WIDTH-1:0] dinb, // Port B RAM input data
input clka, // Port A clock
input clkb, // Port B clock
input wea, // Port A write enable
input web, // Port B write enable
input ena, // Port A RAM Enable, for additional power savings, disable port when not in use
input enb, // Port B RAM Enable, for additional power savings, disable port when not in use
input rsta, // Port A output reset (does not affect memory contents)
input rstb, // Port B output reset (does not affect memory contents)
input regcea, // Port A output register enable
input regceb, // Port B output register enable
output [RAM_WIDTH-1:0] douta, // Port A RAM output data
output [RAM_WIDTH-1:0] doutb // Port B RAM output data
);
reg [RAM_WIDTH-1:0] BRAM [RAM_DEPTH-1:0];
reg [RAM_WIDTH-1:0] ram_data_a = {RAM_WIDTH{1'b0}};
reg [RAM_WIDTH-1:0] ram_data_b = {RAM_WIDTH{1'b0}};
//this loop below allows for rendering with iverilog simulations!
/*
integer idx;
for(idx = 0; idx < RAM_DEPTH; idx = idx+1) begin: cats
wire [RAM_WIDTH-1:0] tmp;
assign tmp = BRAM[idx];
end
*/
// The following code either initializes the memory values to a specified file or to all zeros to match hardware
generate
if (INIT_FILE != "") begin: use_init_file
initial
$readmemh(INIT_FILE, BRAM, 0, RAM_DEPTH-1);
end else begin: init_bram_to_zero
integer ram_index;
initial
for (ram_index = 0; ram_index < RAM_DEPTH; ram_index = ram_index + 1)
BRAM[ram_index] = {RAM_WIDTH{1'b0}};
end
endgenerate
integer idx;
// initial begin
// for (idx = 0; idx < RAM_DEPTH; idx = idx + 1) begin
// $dumpvars(0, BRAM[idx]);
// end
// end
always @(posedge clka)
if (ena) begin
if (wea)
BRAM[addra] <= dina;
ram_data_a <= BRAM[addra];
end
always @(posedge clkb)
if (enb) begin
if (web)
BRAM[addrb] <= dinb;
ram_data_b <= BRAM[addrb];
end
// The following code generates HIGH_PERFORMANCE (use output register) or LOW_LATENCY (no output register)
generate
if (RAM_PERFORMANCE == "LOW_LATENCY") begin: no_output_register
// The following is a 1 clock cycle read latency at the cost of a longer clock-to-out timing
assign douta = ram_data_a;
assign doutb = ram_data_b;
end else begin: output_register
// The following is a 2 clock cycle read latency with improve clock-to-out timing
reg [RAM_WIDTH-1:0] douta_reg = {RAM_WIDTH{1'b0}};
reg [RAM_WIDTH-1:0] doutb_reg = {RAM_WIDTH{1'b0}};
always @(posedge clka)
if (rsta)
douta_reg <= {RAM_WIDTH{1'b0}};
else if (regcea)
douta_reg <= ram_data_a;
always @(posedge clkb)
if (rstb)
doutb_reg <= {RAM_WIDTH{1'b0}};
else if (regceb)
doutb_reg <= ram_data_b;
assign douta = douta_reg;
assign doutb = doutb_reg;
end
endgenerate
// The following function calculates the address width based on specified RAM depth
function integer clogb2;
input integer depth;
for (clogb2=0; depth>0; clogb2=clogb2+1)
depth = depth >> 1;
endfunction
endmodule
// The following is an instantiation template for xilinx_true_dual_port_read_first_2_clock_ram
/*
// Xilinx True Dual Port RAM, Read First, Dual Clock
xilinx_true_dual_port_read_first_2_clock_ram #(
.RAM_WIDTH(18), // Specify RAM data width
.RAM_DEPTH(1024), // Specify RAM depth (number of entries)
.RAM_PERFORMANCE("HIGH_PERFORMANCE"), // Select "HIGH_PERFORMANCE" or "LOW_LATENCY"
.INIT_FILE("") // Specify name/location of RAM initialization file if using one (leave blank if not)
) your_instance_name (
.addra(addra), // Port A address bus, width determined from RAM_DEPTH
.addrb(addrb), // Port B address bus, width determined from RAM_DEPTH
.dina(dina), // Port A RAM input data, width determined from RAM_WIDTH
.dinb(dinb), // Port B RAM input data, width determined from RAM_WIDTH
.clka(clka), // Port A clock
.clkb(clkb), // Port B clock
.wea(wea), // Port A write enable
.web(web), // Port B write enable
.ena(ena), // Port A RAM Enable, for additional power savings, disable port when not in use
.enb(enb), // Port B RAM Enable, for additional power savings, disable port when not in use
.rsta(rsta), // Port A output reset (does not affect memory contents)
.rstb(rstb), // Port B output reset (does not affect memory contents)
.regcea(regcea), // Port A output register enable
.regceb(regceb), // Port B output register enable
.douta(douta), // Port A RAM output data, width determined from RAM_WIDTH
.doutb(doutb) // Port B RAM output data, width determined from RAM_WIDTH
);
*/

View File

@ -5,12 +5,12 @@
`define HCP 5
`define SEND_MESSAGE(MESSAGE) \
uart_rx_axiov = 1; \
rx_valid = 1; \
for(int i=0; i < $size(MESSAGE); i++) begin \
uart_rx_axiod = MESSAGE[i]; \
rx_data = MESSAGE[i]; \
#`CP; \
end \
uart_rx_axiov = 0; \
rx_valid = 0; \
module bridge_rx_tb;
// https://www.youtube.com/watch?v=WCOAr-96bGc
@ -22,34 +22,32 @@ string message;
integer test_num;
// uart inputs and outputs
logic rxd;
logic [7:0] uart_rx_axiod;
logic uart_rx_axiov;
logic rx;
logic [7:0] rx_data;
logic rx_valid;
// the parameter will all get filled out in manta's big instantiator thing hehehee
parameter ADDR_WIDTH = 16; // $clog2( how much memory we need rounded up to the nearest 8 )
parameter DATA_WIDTH = 16;
// request bus, gets connected to uart_rx (through a FSM)
logic [ADDR_WIDTH-1:0] req_addr;
logic [DATA_WIDTH-1:0] req_data;
logic req_rw;
logic req_valid;
logic [ADDR_WIDTH-1:0] addr;
logic [DATA_WIDTH-1:0] wdata;
logic rw;
logic valid;
logic req_ready;
bridge_rx bridge_rx_uut(
.clk(clk),
.rst(rst),
// connect to uart_rx
.axiid(uart_rx_axiod),
.axiiv(uart_rx_axiov),
.rx_data(rx_data),
.rx_valid(rx_valid),
.req_addr(req_addr),
.req_data(req_data),
.req_rw(req_rw),
.req_valid(req_valid),
.req_ready(req_ready));
.addr_o(addr),
.wdata_o(wdata),
.rw_o(rw),
.valid_o(valid));
always begin
#`HCP
@ -63,8 +61,8 @@ initial begin
// setup and reset
clk = 0;
rst = 0;
uart_rx_axiod = 0;
uart_rx_axiov = 0;
rx_data = 0;
rx_valid = 0;
req_ready = 1;
test_num = 0;
#`CP
@ -78,9 +76,9 @@ initial begin
message = {"M12345678", 8'h0D, 8'h0A};
`SEND_MESSAGE(message)
assert(req_addr == 16'h1234) else $error("incorrect addr!");
assert(req_data == 16'h5678) else $error("incorrect data!");
assert(req_rw == 1) else $error("incorrect rw!");
assert(addr == 16'h1234) else $error("incorrect addr!");
assert(wdata == 16'h5678) else $error("incorrect data!");
assert(rw == 1) else $error("incorrect rw!");
assert(bridge_rx_uut.state != bridge_rx_uut.ERROR) else $error("in error state after transmission");
#(10*`CP);
@ -94,9 +92,9 @@ initial begin
message = {"MDEADBEEF", 8'h0D, 8'h0A};
`SEND_MESSAGE(message)
assert(req_addr == 16'hDEAD) else $error("incorrect addr!");
assert(req_data == 16'hBEEF) else $error("incorrect data!");
assert(req_rw == 1) else $error("incorrect rw!");
assert(addr == 16'hDEAD) else $error("incorrect addr!");
assert(wdata == 16'hBEEF) else $error("incorrect data!");
assert(rw == 1) else $error("incorrect rw!");
assert(bridge_rx_uut.state != bridge_rx_uut.ERROR) else $error("in error state after transmission");
#(10*`CP);
@ -110,8 +108,8 @@ initial begin
message = {"MBABE", 8'h0D, 8'h0A};
`SEND_MESSAGE(message)
assert(req_addr == 16'hBABE) else $error("incorrect addr!");
assert(req_rw == 0) else $error("incorrect rw!");
assert(addr == 16'hBABE) else $error("incorrect addr!");
assert(rw == 0) else $error("incorrect rw!");
assert(bridge_rx_uut.state != bridge_rx_uut.ERROR) else $error("in error state after transmission");
#(10*`CP);
@ -124,8 +122,8 @@ initial begin
message = {"M0000", 8'h0D};
`SEND_MESSAGE(message)
assert(req_addr == 16'h0000) else $error("incorrect addr!");
assert(req_rw == 0) else $error("incorrect rw!");
assert(addr == 16'h0000) else $error("incorrect addr!");
assert(rw == 0) else $error("incorrect rw!");
assert(bridge_rx_uut.state != bridge_rx_uut.ERROR) else $error("in error state after transmission");
#(10*`CP);
@ -138,8 +136,8 @@ initial begin
message = {"M1234", 8'h0D};
`SEND_MESSAGE(message)
assert(req_addr == 16'h1234) else $error("incorrect addr!");
assert(req_rw == 0) else $error("incorrect rw!");
assert(addr == 16'h1234) else $error("incorrect addr!");
assert(rw == 0) else $error("incorrect rw!");
assert(bridge_rx_uut.state != bridge_rx_uut.ERROR) else $error("in error state after transmission");
#(10*`CP);
@ -152,9 +150,9 @@ initial begin
message = {"MF00DBEEF", 8'h0D};
`SEND_MESSAGE(message)
assert(req_addr == 16'hF00D) else $error("incorrect addr!");
assert(req_data == 16'hBEEF) else $error("incorrect data!");
assert(req_rw == 1) else $error("incorrect rw!");
assert(addr == 16'hF00D) else $error("incorrect addr!");
assert(wdata == 16'hBEEF) else $error("incorrect data!");
assert(rw == 1) else $error("incorrect rw!");
assert(bridge_rx_uut.state != bridge_rx_uut.ERROR) else $error("in error state after transmission");
#(10*`CP);
@ -167,9 +165,9 @@ initial begin
message = {"MB0BACAFE", 8'h0D};
`SEND_MESSAGE(message)
assert(req_addr == 16'hB0BA) else $error("incorrect addr!");
assert(req_data == 16'hCAFE) else $error("incorrect data!");
assert(req_rw == 1) else $error("incorrect rw!");
assert(addr == 16'hB0BA) else $error("incorrect addr!");
assert(wdata == 16'hCAFE) else $error("incorrect data!");
assert(rw == 1) else $error("incorrect rw!");
assert(bridge_rx_uut.state != bridge_rx_uut.ERROR) else $error("in error state after transmission");
#(10*`CP);
@ -183,7 +181,7 @@ initial begin
message = {"MABC", 8'h0D, 8'h0A};
`SEND_MESSAGE(message)
assert(req_valid == 0) else $error("valid asserted for bad message");
assert(valid == 0) else $error("valid asserted for bad message");
assert(bridge_rx_uut.state == bridge_rx_uut.ERROR) else $error("not in error state after transmission");
#(10*`CP);
@ -198,7 +196,7 @@ initial begin
message = {"MABC", 8'h0D, 8'h0A};
`SEND_MESSAGE(message)
assert(req_valid == 0) else $error("valid asserted for bad message");
assert(valid == 0) else $error("valid asserted for bad message");
assert(bridge_rx_uut.state == bridge_rx_uut.ERROR) else $error("not in error state after transmission");
#(10*`CP);
@ -213,7 +211,7 @@ initial begin
message = {"MABC", 8'h0D, 8'h0A};
`SEND_MESSAGE(message)
assert(req_valid == 0) else $error("valid asserted for bad message");
assert(valid == 0) else $error("valid asserted for bad message");
assert(bridge_rx_uut.state == bridge_rx_uut.ERROR) else $error("not in error state after transmission");
#(10*`CP);
@ -228,7 +226,7 @@ initial begin
message = {"MABC", 8'h0D, 8'h0A};
`SEND_MESSAGE(message)
assert(req_valid == 0) else $error("valid asserted for bad message");
assert(valid == 0) else $error("valid asserted for bad message");
assert(bridge_rx_uut.state == bridge_rx_uut.ERROR) else $error("not in error state after transmission");
#(10*`CP);
@ -243,7 +241,7 @@ initial begin
message = {"MABCG", 8'h0D, 8'h0A};
`SEND_MESSAGE(message)
assert(req_valid == 0) else $error("valid asserted for bad message");
assert(valid == 0) else $error("valid asserted for bad message");
assert(bridge_rx_uut.state == bridge_rx_uut.ERROR) else $error("not in error state after transmission");
#(10*`CP);
@ -258,7 +256,7 @@ initial begin
message = {"MABC[]()##*@", 8'h0D, 8'h0A};
`SEND_MESSAGE(message)
assert(req_valid == 0) else $error("valid asserted for bad message");
assert(valid == 0) else $error("valid asserted for bad message");
assert(bridge_rx_uut.state == bridge_rx_uut.ERROR) else $error("not in error state after transmission");
#(10*`CP);
@ -273,7 +271,7 @@ initial begin
message = {"M", 8'h0D, 8'h0A};
`SEND_MESSAGE(message)
assert(req_valid == 0) else $error("valid asserted for bad message");
assert(valid == 0) else $error("valid asserted for bad message");
assert(bridge_rx_uut.state == bridge_rx_uut.ERROR) else $error("not in error state after transmission");
#(10*`CP);

View File

@ -7,47 +7,45 @@
module bridge_tx_tb;
// https://www.youtube.com/watch?v=WCOAr-96bGc
//boilerplate
// boilerplate
logic clk;
logic rst;
integer test_num;
// uart_tx <--> tb signals
logic txd;
// tb -> bridge_tx signals
logic [15:0] tb_btx_rdata;
logic res_ready;
logic tb_btx_valid;
// uart_tx <--> bridge_tx signals
logic [7:0] axid;
logic axiv;
logic axir;
logic [7:0] btx_utx_data;
logic btx_utx_valid;
logic btx_utx_ready;
// bridge_tx <--> tb signals
logic res_valid;
logic res_ready;
logic [15:0] res_data;
// uart_tx -> tb signals
logic utx_tb_tx;
bridge_tx btx (
.clk(clk),
.rdata_i(tb_btx_rdata),
.rw_i(1'b1),
.valid_i(tb_btx_valid),
.data_o(btx_utx_data),
.ready_i(btx_utx_ready),
.valid_o(btx_utx_valid));
uart_tx #(
.DATA_WIDTH(8),
.CLK_FREQ_HZ(100_000_000),
.BAUDRATE(115200))
uart_tx_uut (
.clk(clk),
.rst(rst),
.txd(txd),
.axiid(axid),
.axiiv(axiv),
.axiir(axir));
bridge_tx bridge_tx_uut(
.CLOCKS_PER_BAUD(868))
utx (
.clk(clk),
.axiod(axid),
.axiov(axiv),
.axior(axir),
.data(btx_utx_data),
.valid(btx_utx_valid),
.busy(),
.ready(btx_utx_ready),
.res_valid(res_valid),
.res_ready(res_ready),
.res_data(res_data));
.tx(utx_tb_tx));
always begin
#`HCP
@ -60,26 +58,21 @@ initial begin
// setup and reset
clk = 0;
rst = 0;
test_num = 0;
res_valid = 0;
res_data = 0;
#`CP
rst = 1;
#`CP
rst = 0;
tb_btx_valid = 0;
tb_btx_rdata = 0;
#(10*`CP);
/* ==== Test 1 Begin ==== */
$display("\n=== test 1: receive 0x0123 for baseline functionality ===");
test_num = 1;
res_data = 16'h0123;
res_valid = 1;
tb_btx_rdata = 16'h0123;
tb_btx_valid = 1;
#`CP;
assert(res_ready == 0) else $error("invalid handshake: res_ready held high for more than one clock cycle");
res_valid = 0;
tb_btx_valid = 0;
#(100000*`CP);
/* ==== Test 1 End ==== */
@ -87,12 +80,12 @@ initial begin
/* ==== Test 2 Begin ==== */
$display("\n=== test 2: receive 0x4567 for baseline functionality ===");
test_num = 2;
res_data = 16'h4567;
res_valid = 1;
tb_btx_rdata = 16'h4567;
tb_btx_valid = 1;
#`CP;
assert(res_ready == 0) else $error("invalid handshake: res_ready held high for more than one clock cycle");
res_valid = 0;
tb_btx_valid = 0;
#(100000*`CP);
/* ==== Test 2 End ==== */
@ -100,12 +93,12 @@ initial begin
/* ==== Test 3 Begin ==== */
$display("\n=== test 3: receive 0x89AB for baseline functionality ===");
test_num = 3;
res_data = 16'h89AB;
res_valid = 1;
tb_btx_rdata = 16'h89AB;
tb_btx_valid = 1;
#`CP;
assert(res_ready == 0) else $error("invalid handshake: res_ready held high for more than one clock cycle");
res_valid = 0;
tb_btx_valid = 0;
#(100000*`CP);
/* ==== Test 3 End ==== */
@ -113,12 +106,12 @@ initial begin
/* ==== Test 4 Begin ==== */
$display("\n=== test 4: receive 0xCDEF for baseline functionality ===");
test_num = 4;
res_data = 16'hCDEF;
res_valid = 1;
tb_btx_rdata = 16'hCDEF;
tb_btx_valid = 1;
#`CP;
assert(res_ready == 0) else $error("invalid handshake: res_ready held high for more than one clock cycle");
res_valid = 0;
tb_btx_valid = 0;
#(100000*`CP);
/* ==== Test 4 End ==== */

View File

@ -1,5 +1,4 @@
`default_nettype none
`timescale 1ns / 1ps
module fifo_tb();

View File

@ -1,69 +0,0 @@
`default_nettype none
`timescale 1ns / 1ps
module manta_tb();
logic clk;
logic rst;
logic rxd;
logic txd;
logic probe0, probe1, probe2;
assign probe0 = count[0];
assign probe1 = count[1];
assign probe2 = count[2];
// manta
// later make this a `MANTA that gets loaded from a svh file that the python script generates
manta #(.FIFO_DEPTH(64)) manta(
.clk(clk),
.rst(rst),
.probe0(probe0),
.probe1(probe1),
.probe2(probe2),
.rxd(rxd),
.txd(txd));
/* Signal Generator */
logic [7:0] count = 0;
always begin
count = count + 1;
#10;
end
always begin
#5;
clk = !clk;
end
logic [9:0] uart_data;
initial begin
$dumpfile("manta.vcd");
$dumpvars(0, manta_tb);
clk = 0;
rst = 1;
rxd = 1;
uart_data = 0;
#10;
rst = 0;
// Wait a little bit to make sure that it doesn't like, explode or something
#1000;
// send arm byte!
uart_data = {1'b1, 8'b00110000, 1'b0};
for (int i=0; i < 10; i++) begin
rxd = uart_data[i];
#8680;
end
// see what happens lmao
#15000000;
$finish();
end
endmodule
`default_nettype wire

View File

@ -1,5 +1,4 @@
`default_nettype none
`timescale 1ns / 1ps
module uart_tb();

View File

@ -1,93 +0,0 @@
`default_nettype none
`timescale 1ns/1ps
`define CP 10
`define HCP 5
module yeet_tb();
logic clk;
logic [15:0] tb_btx_rdata;
logic tb_btx_rw;
logic tb_btx_valid;
bridge_tx btx (
.clk(clk),
.rdata_i(tb_btx_rdata),
.rw_i(tb_btx_rw),
.valid_i(tb_btx_valid),
.ready_i(utx_btx_ready),
.data_o(btx_utx_data),
.valid_o(btx_utx_valid));
logic [7:0] btx_utx_data;
logic btx_utx_valid;
logic utx_btx_ready;
uart_tx #(.CLOCKS_PER_BAUD(10)) utx (
.clk(clk),
.data(btx_utx_data),
.valid(btx_utx_valid),
.ready(utx_btx_ready),
.tx(utx_tb_tx));
logic utx_tb_tx;
logic [7:0] decoded_byte;
logic decoder_valid;
logic [7:0] decoder_data;
always @(posedge clk) if (decoder_valid) decoded_byte <= decoder_data;
rx_uart #(.CLOCKS_PER_BAUD(10)) urx_decoder(
.i_clk(clk),
.i_uart_rx(utx_tb_tx),
.o_wr(decoder_valid),
.o_data(decoder_data));
always begin
#`HCP
clk = !clk;
end
initial begin
$dumpfile("yeet.vcd");
$dumpvars(0, yeet_tb);
clk = 0;
tb_btx_rdata = 0;
tb_btx_valid = 0;
tb_btx_rw = 0;
#`HCP
#(10*`CP);
// put some shit on the bus
tb_btx_rdata = 16'h69;
tb_btx_valid = 1;
tb_btx_rw = 0;
#`CP
tb_btx_valid = 0;
// wait a bit
#(7000 - `CP);
// put some more shit on the bus
tb_btx_rdata = 16'h42;
tb_btx_valid = 1;
tb_btx_rw = 1;
#`CP
tb_btx_valid = 0;
#(7000 - `CP);
$finish();
end
endmodule
`default_nettype wire