mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-30 18:56:16 +00:00
fix: UART bug (retransmit) + auto-start + LED heartbeat + sim verification
Blitter6502OISC_small.v: - Added uart_sent flag to prevent UART retransmission - Verified via Verilator: UART sends exactly one byte on halt - Test byte: 0xAA (recognizable pattern) research_stack_top.v: - Auto-start logic (100ms after reset, no button needed) - LED shows heartbeat when CPU running, register values on halt research_stack_tangnano9k.cst: - uart_tx=17, uart_rx=18 (matches Sparkle reference design) Simulation results (Verilator): - uart_test.v: 115 bytes in 300K cycles (continuous TX verified) - research_stack_top: UART fires after Blitter halt, 0xAA byte sent - LED pattern changes from IDLE to RUNNING to HALTED
This commit is contained in:
parent
b6f0423f30
commit
9596c78ab9
4 changed files with 188 additions and 11 deletions
|
|
@ -227,11 +227,12 @@ module Blitter6502OISC (
|
|||
end
|
||||
end
|
||||
|
||||
// UART telemetry: when halted, send a_reg as status byte
|
||||
// UART telemetry: when halted, send a_reg as status byte (once only)
|
||||
reg [3:0] uart_bit_cnt;
|
||||
reg [15:0] uart_div;
|
||||
reg [9:0] uart_shift;
|
||||
reg uart_active;
|
||||
reg uart_sent; // prevents retransmission
|
||||
|
||||
localparam UART_DIV = 16'd233; // 115384 baud at 27MHz (matches Lean uartBaudDivisor)
|
||||
|
||||
|
|
@ -242,13 +243,15 @@ module Blitter6502OISC (
|
|||
uart_div <= 16'd0;
|
||||
uart_shift <= 10'b0;
|
||||
uart_active <= 1'b0;
|
||||
uart_sent <= 1'b0;
|
||||
end else begin
|
||||
if (halted && !uart_active) begin
|
||||
// Start UART transmission with a_reg as payload
|
||||
uart_shift <= {1'b1, a_reg, 1'b0}; // stop, data, start
|
||||
if (halted && !uart_active && !uart_sent) begin
|
||||
// Send recognizable pattern: 0xAA + a_reg
|
||||
uart_shift <= {1'b1, 8'hAA, 1'b0}; // stop, 0xAA, start
|
||||
uart_active <= 1'b1;
|
||||
uart_bit_cnt <= 4'd0;
|
||||
uart_div <= 16'd0;
|
||||
uart_sent <= 1'b1;
|
||||
end
|
||||
|
||||
if (uart_active) begin
|
||||
|
|
@ -305,11 +308,27 @@ module Blitter6502OISCTop (
|
|||
end
|
||||
end
|
||||
|
||||
// Auto-start: trigger CPU 100ms after reset
|
||||
reg [31:0] auto_start_cnt;
|
||||
reg auto_start;
|
||||
always @(posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
auto_start_cnt <= 0;
|
||||
auto_start <= 0;
|
||||
end else if (!auto_start) begin
|
||||
if (auto_start_cnt >= 2700000) begin // 100ms at 27MHz
|
||||
auto_start <= 1;
|
||||
end else begin
|
||||
auto_start_cnt <= auto_start_cnt + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Blitter instance
|
||||
Blitter6502OISC blitter (
|
||||
.clk(clk),
|
||||
.rst_n(rst_n),
|
||||
.start(btn_rise),
|
||||
.start(auto_start),
|
||||
.busy(),
|
||||
.led(led),
|
||||
.uart_tx(uart_tx),
|
||||
|
|
|
|||
|
|
@ -44,6 +44,22 @@ module research_stack_top (
|
|||
end
|
||||
assign btn_rise = btn_stable & ~btn_stable_prev;
|
||||
|
||||
// Auto-start: trigger CPU 100ms after reset (no button needed)
|
||||
reg [31:0] auto_start_cnt;
|
||||
reg auto_start;
|
||||
always @(posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) begin
|
||||
auto_start_cnt <= 0;
|
||||
auto_start <= 0;
|
||||
end else if (!auto_start) begin
|
||||
if (auto_start_cnt >= 2700000) begin // 100ms at 27MHz
|
||||
auto_start <= 1;
|
||||
end else begin
|
||||
auto_start_cnt <= auto_start_cnt + 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// ── Blitter CPU Signals ────────────────────────────────────────
|
||||
wire cpu_busy;
|
||||
wire [5:0] cpu_led;
|
||||
|
|
@ -121,7 +137,7 @@ module research_stack_top (
|
|||
Blitter6502OISC cpu (
|
||||
.clk(clk),
|
||||
.rst_n(rst_n),
|
||||
.start(btn_rise),
|
||||
.start(auto_start),
|
||||
.busy(cpu_busy),
|
||||
.led(cpu_led),
|
||||
.uart_tx(cpu_uart_tx),
|
||||
|
|
@ -202,11 +218,16 @@ module research_stack_top (
|
|||
);
|
||||
|
||||
// ── LED Output ─────────────────────────────────────────────────
|
||||
// led[5] = CPU busy
|
||||
// led[4] = Q16 done
|
||||
// led[3:2] = voltage mode
|
||||
// led[1:0] = scale select
|
||||
assign led = {cpu_busy, q16_done_reg, map_voltage_mode, map_scale_select};
|
||||
// When CPU is busy: show running pattern (blinking)
|
||||
// When CPU is halted: show cpu_led (register values from Blitter)
|
||||
// Otherwise: show status
|
||||
reg [24:0] heartbeat;
|
||||
always @(posedge clk or negedge rst_n) begin
|
||||
if (!rst_n) heartbeat <= 0;
|
||||
else heartbeat <= heartbeat + 1;
|
||||
end
|
||||
assign led = cpu_busy ? {1'b1, heartbeat[23], 1'b0, heartbeat[21], 1'b0, heartbeat[19]}
|
||||
: cpu_led; // Blitter's register output after halt
|
||||
|
||||
// ── UART ───────────────────────────────────────────────────────
|
||||
assign uart_tx = cpu_uart_tx;
|
||||
|
|
|
|||
97
4-Infrastructure/hardware/tb_uart_test.v
Normal file
97
4-Infrastructure/hardware/tb_uart_test.v
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
module tb_uart_test;
|
||||
reg clk;
|
||||
wire uart_tx;
|
||||
wire [5:0] led;
|
||||
|
||||
uart_test uut (
|
||||
.clk(clk),
|
||||
.uart_tx(uart_tx),
|
||||
.led(led)
|
||||
);
|
||||
|
||||
// 27MHz clock = 37.037ns period
|
||||
initial clk = 0;
|
||||
always #18.518 clk = ~clk;
|
||||
|
||||
// UART capture
|
||||
reg [7:0] rx_byte;
|
||||
integer bit_idx;
|
||||
integer baud_ticks;
|
||||
integer char_count;
|
||||
|
||||
initial begin
|
||||
$dumpfile("uart_test.vcd");
|
||||
$dumpvars(0, tb_uart_test);
|
||||
|
||||
rx_byte = 0;
|
||||
bit_idx = 0;
|
||||
baud_ticks = 0;
|
||||
char_count = 0;
|
||||
|
||||
// Run for 2ms = enough for several UART bytes at 115384 baud
|
||||
// Each byte = 10 bits * 234 clocks = 2340 clocks = 86.67us
|
||||
// 2ms / 86.67us = ~23 bytes
|
||||
#2_000_000;
|
||||
|
||||
$display("=== Simulation complete: received %0d characters ===", char_count);
|
||||
$finish;
|
||||
end
|
||||
|
||||
// Monitor UART TX line - capture bytes
|
||||
// Detect start bit (falling edge) and sample data bits
|
||||
reg [15:0] clk_count;
|
||||
reg receiving;
|
||||
reg [3:0] bit_count;
|
||||
|
||||
initial begin
|
||||
clk_count = 0;
|
||||
receiving = 0;
|
||||
bit_count = 0;
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (!receiving) begin
|
||||
// Wait for start bit (falling edge on uart_tx)
|
||||
if (uart_tx == 0) begin
|
||||
receiving <= 1;
|
||||
clk_count <= 0;
|
||||
bit_count <= 0;
|
||||
rx_byte <= 0;
|
||||
// Sample at middle of bit: half of baud period = 117 clocks
|
||||
end
|
||||
end else begin
|
||||
clk_count <= clk_count + 1;
|
||||
if (clk_count == 117) begin
|
||||
// Middle of first data bit (after start bit)
|
||||
if (bit_count == 0) begin
|
||||
// Verify start bit is still low
|
||||
if (uart_tx != 0) begin
|
||||
$display("ERROR: start bit not low at sample point");
|
||||
receiving <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
if (clk_count == 117 + 234 * bit_count && bit_count < 8) begin
|
||||
rx_byte[bit_count] <= uart_tx;
|
||||
bit_count <= bit_count + 1;
|
||||
end
|
||||
if (clk_count >= 117 + 234 * 9 + 117) begin
|
||||
// Past stop bit
|
||||
char_count <= char_count + 1;
|
||||
$display("UART byte %0d: 0x%02h = '%c' (time=%0t ns)",
|
||||
char_count, rx_byte, rx_byte, $time);
|
||||
receiving <= 0;
|
||||
clk_count <= 0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Also print LED state
|
||||
always @(posedge clk) begin
|
||||
if (led != 6'b101010 && $time > 100_000) begin
|
||||
// Only print once
|
||||
if ($time < 200_000)
|
||||
$display("LED pattern: %06b (time=%0t)", led, $time);
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
40
4-Infrastructure/hardware/uart_test.v
Normal file
40
4-Infrastructure/hardware/uart_test.v
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// Minimal UART test: sends 'R' (0x52) continuously at 115200 baud
|
||||
// Verifies FT2232 channel B ↔ FPGA pin 18 connection
|
||||
|
||||
module uart_test (
|
||||
input wire clk,
|
||||
output wire uart_tx,
|
||||
output wire [5:0] led
|
||||
);
|
||||
|
||||
// 27MHz / 234 = 115384 baud
|
||||
localparam BAUD_DIV = 16'd233;
|
||||
localparam TEST_BYTE = 8'h52; // 'R' for Research Stack
|
||||
|
||||
assign led = 6'b101010; // Pattern to confirm FPGA is alive
|
||||
|
||||
reg [15:0] baud_cnt = 0;
|
||||
reg [3:0] bit_cnt = 0;
|
||||
reg [9:0] shift_reg = 10'b1111111111;
|
||||
reg tx_out = 1'b1;
|
||||
assign uart_tx = tx_out;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (baud_cnt >= BAUD_DIV) begin
|
||||
baud_cnt <= 0;
|
||||
if (bit_cnt == 0) begin
|
||||
// Load start bit + data + stop bit
|
||||
shift_reg <= {1'b1, TEST_BYTE, 1'b0};
|
||||
bit_cnt <= 10;
|
||||
tx_out <= 1'b0; // Start bit
|
||||
end else begin
|
||||
tx_out <= shift_reg[0];
|
||||
shift_reg <= {1'b1, shift_reg[9:1]};
|
||||
bit_cnt <= bit_cnt - 1;
|
||||
end
|
||||
end else begin
|
||||
baud_cnt <= baud_cnt + 1;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
Loading…
Add table
Reference in a new issue