mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-08-17 10:20:35 +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
9e13946972
commit
149f9df6f6
4 changed files with 188 additions and 11 deletions
|
|
@ -227,11 +227,12 @@ module Blitter6502OISC (
|
||||||
end
|
end
|
||||||
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 [3:0] uart_bit_cnt;
|
||||||
reg [15:0] uart_div;
|
reg [15:0] uart_div;
|
||||||
reg [9:0] uart_shift;
|
reg [9:0] uart_shift;
|
||||||
reg uart_active;
|
reg uart_active;
|
||||||
|
reg uart_sent; // prevents retransmission
|
||||||
|
|
||||||
localparam UART_DIV = 16'd233; // 115384 baud at 27MHz (matches Lean uartBaudDivisor)
|
localparam UART_DIV = 16'd233; // 115384 baud at 27MHz (matches Lean uartBaudDivisor)
|
||||||
|
|
||||||
|
|
@ -242,13 +243,15 @@ module Blitter6502OISC (
|
||||||
uart_div <= 16'd0;
|
uart_div <= 16'd0;
|
||||||
uart_shift <= 10'b0;
|
uart_shift <= 10'b0;
|
||||||
uart_active <= 1'b0;
|
uart_active <= 1'b0;
|
||||||
|
uart_sent <= 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
if (halted && !uart_active) begin
|
if (halted && !uart_active && !uart_sent) begin
|
||||||
// Start UART transmission with a_reg as payload
|
// Send recognizable pattern: 0xAA + a_reg
|
||||||
uart_shift <= {1'b1, a_reg, 1'b0}; // stop, data, start
|
uart_shift <= {1'b1, 8'hAA, 1'b0}; // stop, 0xAA, start
|
||||||
uart_active <= 1'b1;
|
uart_active <= 1'b1;
|
||||||
uart_bit_cnt <= 4'd0;
|
uart_bit_cnt <= 4'd0;
|
||||||
uart_div <= 16'd0;
|
uart_div <= 16'd0;
|
||||||
|
uart_sent <= 1'b1;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (uart_active) begin
|
if (uart_active) begin
|
||||||
|
|
@ -305,11 +308,27 @@ module Blitter6502OISCTop (
|
||||||
end
|
end
|
||||||
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
|
// Blitter instance
|
||||||
Blitter6502OISC blitter (
|
Blitter6502OISC blitter (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.rst_n(rst_n),
|
.rst_n(rst_n),
|
||||||
.start(btn_rise),
|
.start(auto_start),
|
||||||
.busy(),
|
.busy(),
|
||||||
.led(led),
|
.led(led),
|
||||||
.uart_tx(uart_tx),
|
.uart_tx(uart_tx),
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,22 @@ module research_stack_top (
|
||||||
end
|
end
|
||||||
assign btn_rise = btn_stable & ~btn_stable_prev;
|
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 ────────────────────────────────────────
|
// ── Blitter CPU Signals ────────────────────────────────────────
|
||||||
wire cpu_busy;
|
wire cpu_busy;
|
||||||
wire [5:0] cpu_led;
|
wire [5:0] cpu_led;
|
||||||
|
|
@ -121,7 +137,7 @@ module research_stack_top (
|
||||||
Blitter6502OISC cpu (
|
Blitter6502OISC cpu (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.rst_n(rst_n),
|
.rst_n(rst_n),
|
||||||
.start(btn_rise),
|
.start(auto_start),
|
||||||
.busy(cpu_busy),
|
.busy(cpu_busy),
|
||||||
.led(cpu_led),
|
.led(cpu_led),
|
||||||
.uart_tx(cpu_uart_tx),
|
.uart_tx(cpu_uart_tx),
|
||||||
|
|
@ -202,11 +218,16 @@ module research_stack_top (
|
||||||
);
|
);
|
||||||
|
|
||||||
// ── LED Output ─────────────────────────────────────────────────
|
// ── LED Output ─────────────────────────────────────────────────
|
||||||
// led[5] = CPU busy
|
// When CPU is busy: show running pattern (blinking)
|
||||||
// led[4] = Q16 done
|
// When CPU is halted: show cpu_led (register values from Blitter)
|
||||||
// led[3:2] = voltage mode
|
// Otherwise: show status
|
||||||
// led[1:0] = scale select
|
reg [24:0] heartbeat;
|
||||||
assign led = {cpu_busy, q16_done_reg, map_voltage_mode, map_scale_select};
|
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 ───────────────────────────────────────────────────────
|
// ── UART ───────────────────────────────────────────────────────
|
||||||
assign uart_tx = cpu_uart_tx;
|
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