Skip to content

Commit 2e8054e

Browse files
committed
uart loading
1 parent 8832345 commit 2e8054e

4 files changed

Lines changed: 42 additions & 95 deletions

File tree

RISC-V-Scaffold-Basys3/RISC-V-Scaffold-Basys3.srcs/sources_1/new/top.v

Lines changed: 22 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
module Top(
33
input wire clk,
44
input wire btnC,
5+
input wire RsRx,
6+
output wire RsTx,
57
output wire [15:0] led,
68
output wire vgaHSync,
79
output wire vgaVSync,
@@ -20,63 +22,25 @@ module Top(
2022
wire clk_25 = clk_div[1];
2123

2224
// -------------------------------------------------------
23-
// Hardcoded program loader state machine
24-
// Writes 4 instructions then releases CPU to execute
25+
// UART program loader
2526
// -------------------------------------------------------
26-
reg reset_reg;
27-
reg debug_write;
28-
reg [31:0] debug_write_address;
29-
reg [31:0] debug_write_data;
30-
reg execute;
31-
reg [2:0] load_state;
27+
wire cpu_reset;
28+
wire debug_write;
29+
wire [31:0] debug_write_address;
30+
wire [31:0] debug_write_data;
3231

33-
always @(posedge clk_25) begin
34-
if (btnC) begin
35-
reset_reg <= 1;
36-
debug_write <= 0;
37-
debug_write_address <= 0;
38-
debug_write_data <= 0;
39-
execute <= 0;
40-
load_state <= 0;
41-
end else begin
42-
case (load_state)
43-
3'd0: begin
44-
// Release reset, start writing
45-
reset_reg <= 0;
46-
debug_write <= 1;
47-
debug_write_address <= 32'd0;
48-
debug_write_data <= 32'h00004137; // LUI x2, 4
49-
load_state <= 3'd1;
50-
end
51-
3'd1: begin
52-
debug_write_address <= 32'd1;
53-
debug_write_data <= 32'h00808093; // ADDI x1, x1, 8
54-
load_state <= 3'd2;
55-
end
56-
3'd2: begin
57-
debug_write_address <= 32'd2;
58-
debug_write_data <= 32'h00112023; // SW x0, 0(x2)
59-
load_state <= 3'd3;
60-
end
61-
3'd3: begin
62-
debug_write_address <= 32'd3;
63-
debug_write_data <= 32'hFF9FF06F; // JAL x0, -8
64-
load_state <= 3'd4;
65-
end
66-
3'd4: begin
67-
// Stop writing, start executing
68-
debug_write <= 0;
69-
debug_write_address <= 0;
70-
debug_write_data <= 0;
71-
execute <= 1;
72-
load_state <= 3'd5;
73-
end
74-
default: begin
75-
// Stay in execute mode
76-
end
77-
endcase
78-
end
79-
end
32+
uart_program_loader loader (
33+
.clk (clk_25),
34+
.rst_n (~btnC),
35+
.rx (RsRx),
36+
.cpu_reset (cpu_reset),
37+
.debug_write (debug_write),
38+
.debug_write_address (debug_write_address),
39+
.debug_write_data (debug_write_data)
40+
);
41+
42+
wire reset = btnC | cpu_reset;
43+
wire execute = ~reset;
8044

8145
// -------------------------------------------------------
8246
// CPU + VGA
@@ -87,7 +51,7 @@ module Top(
8751

8852
Main cpu (
8953
.clock (clk_25),
90-
.reset (reset_reg),
54+
.reset (reset),
9155
.io_execute (execute),
9256
.io_debug_write (debug_write),
9357
.io_debug_write_address (debug_write_address),
@@ -107,5 +71,6 @@ module Top(
10771
assign vgaBlue = blanking ? 4'h0 : rgb[3:0];
10872

10973
// debug_1 = register 1, debug_2 = program counter
110-
assign led = debug_1[15:0];
74+
assign led = debug_1[15:0];
75+
assign RsTx = 1'b1;
11176
endmodule

RISC-V-Scaffold-Basys3/RISC-V-Scaffold-Basys3.srcs/sources_1/new/uart_program_loader.v

Lines changed: 19 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,11 @@
11
`timescale 1ns / 1ps
22

3-
// Receives a RISC-V program over UART and writes it into CPU memory
4-
// via io_debug_write. Holds CPU in reset until a 4x 0xFF end sequence
5-
// is received.
6-
//
7-
// Protocol:
8-
// - Send program bytes little-endian, 4 bytes per word
9-
// - Send 0xFF 0xFF 0xFF 0xFF to signal end of program
10-
// - CPU is released from reset automatically after end sequence
11-
123
module uart_program_loader (
134
input wire clk,
14-
input wire rst_n, // external reset (active low)
15-
input wire rx, // UART RX pin
5+
input wire rst_n,
6+
input wire rx,
167

17-
// CPU control
18-
output reg cpu_reset, // hold high to keep CPU in reset
8+
output reg cpu_reset,
199
output reg debug_write,
2010
output reg [31:0] debug_write_address,
2111
output reg [31:0] debug_write_data
@@ -38,17 +28,13 @@ module uart_program_loader (
3828
// -------------------------------------------------------
3929
// Loader FSM
4030
// -------------------------------------------------------
41-
// Accumulate 4 bytes into a 32-bit word (little-endian)
42-
// Detect end sequence: 4 consecutive 0xFF bytes
43-
44-
reg [31:0] word_buf; // accumulates current word
45-
reg [1:0] byte_idx; // which byte in current word (0-3)
46-
reg [31:0] word_address; // current word address in memory
47-
reg [1:0] ff_count; // consecutive 0xFF bytes seen
48-
reg loading; // are we in loading mode?
49-
reg rx_valid_prev; // edge detect
31+
reg [31:0] word_buf;
32+
reg [1:0] byte_idx;
33+
reg [31:0] word_address;
34+
reg [1:0] ff_count;
35+
reg loading;
36+
reg rx_valid_prev;
5037

51-
// One-cycle pulse on new byte
5238
wire rx_edge = rx_valid && !rx_valid_prev;
5339

5440
always @(posedge clk) begin
@@ -65,27 +51,26 @@ module uart_program_loader (
6551
rx_valid_prev <= 1'b0;
6652
end else begin
6753
rx_valid_prev <= rx_valid;
68-
debug_write <= 1'b0; // default: no write
54+
debug_write <= 1'b0;
6955

7056
if (loading && rx_edge) begin
7157
if (rx_data == 8'hFF) begin
72-
// Count consecutive 0xFF bytes
7358
ff_count <= ff_count + 2'h1;
74-
75-
// Still assemble into word in case it's data not end seq
7659
word_buf <= {rx_data, word_buf[31:8]};
77-
byte_idx <= byte_idx + 2'h1;
7860

7961
if (ff_count == 2'h3) begin
80-
// 4th 0xFF - end sequence complete, release CPU
62+
// 4th consecutive 0xFF - end sequence, release CPU
8163
loading <= 1'b0;
8264
cpu_reset <= 1'b0;
83-
ff_count <= 2'h0;
65+
end else if (byte_idx == 2'h3) begin
66+
// Word complete - write it even though it contains 0xFF
67+
debug_write <= 1'b1;
68+
debug_write_address <= word_address;
69+
debug_write_data <= {rx_data, word_buf[23:0]};
70+
word_address <= word_address + 32'h1;
71+
byte_idx <= 2'h0;
8472
end else begin
85-
// Might still be end sequence, don't write yet
86-
if (byte_idx == 2'h3) begin
87-
byte_idx <= 2'h0;
88-
end
73+
byte_idx <= byte_idx + 2'h1;
8974
end
9075
end else begin
9176
// Non-0xFF byte resets end sequence counter
@@ -100,7 +85,6 @@ module uart_program_loader (
10085
endcase
10186

10287
if (byte_idx == 2'h3) begin
103-
// Full word assembled - write to memory
10488
debug_write <= 1'b1;
10589
debug_write_address <= word_address;
10690
debug_write_data <= {rx_data, word_buf[23:0]};

RISC-V-Scaffold-Basys3/RISC-V-Scaffold-Basys3.xpr

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,13 @@
101101
</File>
102102
<File Path="$PSRCDIR/sources_1/new/uart_program_loader.v">
103103
<FileInfo>
104-
<Attr Name="AutoDisabled" Val="1"/>
105104
<Attr Name="UsedIn" Val="synthesis"/>
106105
<Attr Name="UsedIn" Val="implementation"/>
107106
<Attr Name="UsedIn" Val="simulation"/>
108107
</FileInfo>
109108
</File>
110109
<File Path="$PSRCDIR/sources_1/new/uart_rx.v">
111110
<FileInfo>
112-
<Attr Name="AutoDisabled" Val="1"/>
113111
<Attr Name="UsedIn" Val="synthesis"/>
114112
<Attr Name="UsedIn" Val="implementation"/>
115113
<Attr Name="UsedIn" Val="simulation"/>

load_program.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272

7373
# Send end sequence: 4x 0xFF
7474
print("Sending end sequence (0xFF 0xFF 0xFF 0xFF)...")
75-
ser.write(bytes([0xFF, 0xFF, 0xFF, 0xFF]))
75+
ser.write(bytes([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]))
7676
time.sleep(0.1)
7777

7878
print("Done! CPU should now be running your program.")

0 commit comments

Comments
 (0)