230 lines
7.6 KiB
Systemverilog
230 lines
7.6 KiB
Systemverilog
`timescale 1ns / 1ps
|
|
|
|
module TB();
|
|
|
|
// ==========================================
|
|
// Parameters & Signal Definitions
|
|
// ==========================================
|
|
parameter CLK_PERIOD = 20; // 50MHz
|
|
parameter BAUD = 115200;
|
|
localparam BIT_TIME = 1_000_000_000 / BAUD;
|
|
|
|
reg clk;
|
|
reg rst_n;
|
|
reg uart_rx; // DUT RX
|
|
wire uart_tx; // DUT TX
|
|
reg sig_in;
|
|
|
|
// Clock Generation
|
|
initial clk = 0;
|
|
always #(CLK_PERIOD/2) clk = ~clk;
|
|
initial begin
|
|
$fsdbDumpfile("wave.fsdb");
|
|
$fsdbDumpvars();
|
|
end
|
|
// ==========================================
|
|
// DUT Instantiation
|
|
// ==========================================
|
|
digital_top u_digital_top(
|
|
.clk (clk),
|
|
.rst_n (rst_n),
|
|
.uart_rx (uart_rx),
|
|
.uart_tx (uart_tx),
|
|
.sig_in (sig_in)
|
|
);
|
|
|
|
|
|
// // ==========================================
|
|
// // TX Driver: Read from case.txt
|
|
// // ==========================================
|
|
// initial begin
|
|
// int file_h;
|
|
// int status;
|
|
// logic [63:0] val;
|
|
|
|
// // Initialize signals
|
|
// rst_n = 0;
|
|
// uart_rx = 1;
|
|
// #(CLK_PERIOD * 10);
|
|
// rst_n = 1;
|
|
// file_h = $fopen("case.txt", "r");
|
|
// if (!file_h) begin
|
|
// $display("[TX ERROR] Cannot open case.txt");
|
|
// $finish;
|
|
// end
|
|
|
|
// $display("[TX] Starting transmission...");
|
|
|
|
// while (!$feof(file_h)) begin
|
|
// // Read hex data per line
|
|
// status = $fscanf(file_h, "%h\n", val);
|
|
// if (status == 1) begin
|
|
// if (val > 64'hFFFF_FFFF) begin
|
|
// $display("[%t] TX CMD: %h", $time, val);
|
|
// send_data(val, 64);
|
|
// end else begin
|
|
// $display("[%t] TX DATA: %h", $time, val[31:0]);
|
|
// send_data(val[31:0], 32);
|
|
// end
|
|
// #(BIT_TIME * 5); // Frame gap
|
|
// }
|
|
// end
|
|
|
|
// $fclose(file_h);
|
|
// $display("[TX] All cases sent.");
|
|
|
|
// // Wait for RX return data
|
|
// #(BIT_TIME * 500);
|
|
// $display("[SIM] Simulation finished.");
|
|
// $finish;
|
|
// end
|
|
|
|
|
|
|
|
// ==========================================
|
|
// RX Monitor: Save to rx_data.txt
|
|
// ==========================================
|
|
int rx_file_h;
|
|
initial begin
|
|
|
|
logic [7:0] rx_byte;
|
|
|
|
rx_file_h = $fopen("rx_data.txt", "w");
|
|
if (!rx_file_h) begin
|
|
$display("[RX ERROR] Cannot create rx_data.txt");
|
|
$finish;
|
|
end
|
|
|
|
forever begin
|
|
logic [31:0] packet_word; // 32-bit data packet
|
|
logic [7:0] rx_byte;
|
|
// Collect 4 bytes to form 32-bit data
|
|
for (int byte_idx = 0; byte_idx < 4; byte_idx++) begin
|
|
// 1. Wait for start bit (falling edge)
|
|
@(negedge uart_tx);
|
|
// 2. Skip start bit, sample at center point
|
|
#(BIT_TIME / 2);
|
|
#(BIT_TIME);
|
|
// Read 8 data bits
|
|
for (int i = 0; i < 8; i++) begin
|
|
rx_byte[i] = uart_tx;
|
|
#(BIT_TIME);
|
|
end
|
|
// Combine to 32-bit (little-endian)
|
|
packet_word[24 - 8*byte_idx +: 8] = rx_byte;
|
|
// $display("[%t] Byte %0d: 0x%h", $time, byte_idx, rx_byte);
|
|
// Wait for end of stop bit
|
|
if (byte_idx < 3) begin
|
|
#(BIT_TIME / 2);
|
|
end
|
|
end
|
|
|
|
// Write to file (one 32-bit data per line)
|
|
$fdisplay(rx_file_h, "%08h", packet_word);
|
|
$display("[%0t] Packet (32-bit): 0x%08h", $time, packet_word);
|
|
// Wait for end of last stop bit
|
|
#(BIT_TIME / 2);
|
|
end
|
|
end
|
|
|
|
final begin
|
|
if (rx_file_h) begin
|
|
$fclose(rx_file_h);
|
|
$display("[RX] File closed at %t",$time);
|
|
end
|
|
end
|
|
|
|
// --- Pulse Generation Task ---
|
|
// freq_khz: Target frequency (kHz)
|
|
// duration_ms: Test duration (ms)
|
|
task automatic gen_pulses(input int freq_khz, input int duration_ms);
|
|
int half_period_ns;
|
|
longint end_time_ns;
|
|
begin
|
|
if (freq_khz <= 0) begin
|
|
sig_in = 0;
|
|
#(duration_ms * 1000000);
|
|
end else begin
|
|
half_period_ns = 500000 / freq_khz;
|
|
end_time_ns = $time + (longint'(duration_ms) * 1000000);
|
|
|
|
$display("[%0t] Start generating signal: %0d kHz", $time, freq_khz);
|
|
while ($time < end_time_ns) begin
|
|
sig_in = 1;
|
|
#(half_period_ns);
|
|
sig_in = 0;
|
|
#(half_period_ns);
|
|
end
|
|
end
|
|
end
|
|
endtask
|
|
|
|
// ==========================================
|
|
// Task: Send one byte (Serial TX)
|
|
// ==========================================
|
|
task automatic send_byte(input [7:0] data);
|
|
begin
|
|
uart_rx = 0; // Start bit
|
|
#(BIT_TIME);
|
|
for (int i = 0; i < 8; i++) begin
|
|
uart_rx = data[i]; // LSB First
|
|
#(BIT_TIME);
|
|
end
|
|
uart_rx = 1; // Stop bit
|
|
#(BIT_TIME);
|
|
end
|
|
endtask
|
|
|
|
// Task: Send 32/64 bit data
|
|
task automatic send_data(input [63:0] data, input int len_bits);
|
|
int bytes = len_bits / 8;
|
|
for (int i = bytes - 1; i >= 0; i--) begin // Send from highest byte
|
|
send_byte(data[i*8 +: 8]);
|
|
end
|
|
endtask
|
|
|
|
initial begin
|
|
// 1. Initialization
|
|
rst_n = 0; uart_rx = 1; sig_in = 0;
|
|
#(CLK_PERIOD * 20);
|
|
rst_n = 1;
|
|
#(CLK_PERIOD * 100);
|
|
$display("------- Step 1: read Thermometer Regs -------");
|
|
send_data(64'h80000004_00000004,64);
|
|
send_data(64'h80000008_00000004,64); //mode[25:24] + win
|
|
send_data(64'h8000000c_00000004,64); //calibration H / L
|
|
send_data(64'h80000010_00000004,64); //rep[31] +rep_gap[23:0]
|
|
send_data(64'h80000014_00000004,64); //result [23:0]
|
|
|
|
|
|
$display("------- Step 2: Running Concurrent Tasks -------");
|
|
fork
|
|
// Process A: Generate input pulses (simulate temperature change)
|
|
begin
|
|
gen_pulses(200, 10); // 100kHz for 10ms
|
|
gen_pulses(300, 20);
|
|
gen_pulses(400, 30);
|
|
end
|
|
|
|
// Process B: Insert read command during reporting
|
|
begin
|
|
#(6ms); // Wait for first report packet
|
|
send_data(64'h80000014_00000004,64); $display("[%0t] == Sending Read Request ==", $time);
|
|
send_data(64'h00000010_00000004,64);send_data(32'h8000_06e8,32); $display("[%0t] == open report_en==",$time);
|
|
send_data(64'h0000008_00000004,64);send_data(32'h0100_03e8,32); $display("[%0t] == mode = 1 ==",$time);
|
|
#15ms;
|
|
send_data(64'h00000010_00000004,64);send_data(32'h0000_06e8,32);$display("[%0t] == cloese report_en==",$time);
|
|
|
|
//send_data(64'h00000010_00000004,64);send_data(32'h8000_06e8,32); $display("[%0t] == open report_en==",$time);
|
|
//send_data(64'h00000010_00000004,64);send_data(32'h0000_06e8,32);$display("[%0t] == cloese report_en==",$time);
|
|
#30000;
|
|
send_data(64'h80000014_00000004,64);
|
|
end
|
|
join
|
|
|
|
#(BIT_TIME * 500);
|
|
$display("Test Done.");
|
|
$finish;
|
|
end
|
|
|
|
endmodule |