clean up testbenches, add Makefile for sims
This commit is contained in:
parent
e022696b31
commit
4d9792702a
|
|
@ -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/
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
);
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 ==== */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
`default_nettype none
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module fifo_tb();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
`default_nettype none
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module uart_tb();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Loading…
Reference in New Issue