commit 0c0908d965c48aa25b36a4262f6799e6039dab93
parent 2c6218d04d9dc3d7d0d3b458b72f4913199c1d8f
Author: Brian Swetland <swetland@frotz.net>
Date: Wed, 8 Feb 2012 20:36:04 -0800
uart: make it actually work
- redesign the uart
- update test firmware
- update testbench
Diffstat:
5 files changed, 123 insertions(+), 96 deletions(-)
diff --git a/Makefile b/Makefile
@@ -3,6 +3,7 @@
SRC := verilog/testbench.v
SRC += verilog/ram.v verilog/rom.v verilog/control.v
SRC += verilog/cpu32.v verilog/alu.v verilog/regfile.v
+SRC += verilog/uart.v
SRC += verilog/library.v
all: a32 testbench
diff --git a/de0nano/de0nano.v b/de0nano/de0nano.v
@@ -35,9 +35,11 @@ assign cs0 = (ramaddr[31:16] == 16'h0000);
assign cs1 = (ramaddr[31:16] == 16'hE000);
assign clk = CLOCK_50;
+assign reset = ~KEY[0];
+
cpu32 cpu(
.clk(clk),
- .reset(SW[0]),
+ .reset(reset),
.i_addr(romaddr),
.i_data(romdata),
.d_data_r(cpurdata),
@@ -67,24 +69,15 @@ aram ram(
.wren(cs0 & ramwe)
);
-wire bclk;
-uartclock bclock(
- .reset(reset),
- .clk(clk),
- .bclk(bclk)
- );
-
uart uart0(
.clk(clk),
- .bclk(bclk),
- .reset(0),
+ .reset(reset),
.we(cs1 & ramwe),
.wdata(ramwdata),
.rdata(uartrdata[7:0]),
.tx(GPIO_A[7])
);
-assign GPIO_A[1] = bclk;
assign GPIO_A[3] = uartrdata[0];
reg [7:0] DBG;
@@ -105,24 +98,3 @@ initial $readmemh("fw.txt", rom);
assign data = rom[addr];
endmodule
-
-module uartclock(
- input reset,
- input clk,
- output bclk
- );
-reg [8:0] bcnt;
-reg bclk0;
-always @(posedge clk or posedge reset)
- if (reset) begin
- bcnt <= 9'h0;
- bclk0 <= 0;
- end else if (bcnt == 13 /*217*/) begin
- bcnt <= 9'h0;
- bclk0 <= ~bclk0;
- end else begin
- bcnt <= bcnt + 9'h1;
- end
- assign bclk = bclk0;
-endmodule
-
diff --git a/de0nano/fw.s b/de0nano/fw.s
@@ -1,36 +1,38 @@
NOP
- MOV R0, 0xAA
- MOV R14, 0xF0000000
- SW R0, [R15]
- B loop
+ MOV R14, 0xF0000000
+ MOV R13, 0xE0000000
-big:
- MOV R9, 0xE0000000
- MOV R8, 0x34
- SW R8, [R9]
+ MOV R0, 0x30
+ BL uart_send
+ MOV R0, 0x31
+ BL uart_send
+ MOV R0, 0x32
+ BL uart_send
+ MOV R0, 0x33
+ BL uart_send
- ADD R0, R0, 1
- SW R0, [R1]
- MOV R2, 5000000
-little:
- SUB R2, R2, 1
- BNZ R2, little
- B big
+ MOV R0, 0
+ MOV R2, 256
+xmit_loop:
+ SW R0, [R14]
+wait_fifo:
+ LW R1, [R13]
+ BNZ R1, wait_fifo
+ SW R0, [R13]
+ ADD R0, R0, 1
+ SUB R2, R2, 1
+ BNZ R2, xmit_loop
-loop:
- MOV R0, 0x34
- BL dputc
- MOV R0, 0x32
- BL dputc
- MOV R0, 10
- BL dputc
- B loop
+ MOV R0, 0
+ SW R0, [R14]
+ B .
-dputc:
- MOV R1, 0xE0000000
-wait:
- LW R2, [R1]
- BNZ R2, wait
- SW R0, [R1]
- B R15
+
+uart_send:
+ MOV R13, 0xE0000000
+uart_wait:
+ LW R12, [R13]
+ BNZ R12, uart_wait
+ SW R0, [R13]
+ B R15
diff --git a/verilog/testbench.v b/verilog/testbench.v
@@ -13,8 +13,10 @@ wire ramwe;
initial
begin
reset = 0;
- #20
+ #15
reset = 1;
+ #20
+ reset = 0;
end
always
@@ -25,11 +27,15 @@ always
#10 ;
end
+wire [7:0] urdata;
+
cpu32 cpu(
.clk(clk),
+ .reset(reset),
.i_addr(romaddr),
.i_data(romdata),
- .d_data_r(ramrdata),
+// .d_data_r(ramrdata),
+ .d_data_r({24'b0,urdata}),
.d_data_w(ramwdata),
.d_addr(ramaddr),
.d_we(ramwe)
@@ -48,10 +54,22 @@ ram #(32,8) ram(
.we(ramwe)
);
+wire tx;
+
+uart uart0(
+ .clk(clk),
+ .reset(reset),
+ .wdata(ramwdata[7:0]),
+ .rdata(urdata),
+ .we(ramwe & (ramaddr[31:28] == 4'hE)),
+ .tx(tx)
+ );
+
+
teleprinter io(
.clk(clk),
.we(ramwe),
- .cs(ramaddr[31:28] == 4'hE),
+ .cs(ramaddr[31:28] == 4'h8),
.data(ramwdata[7:0])
);
@@ -60,8 +78,9 @@ initial begin
$dumpvars(0,testbench);
end
-initial #1000 $finish;
+initial #1000000 $finish;
+/*
always @(posedge clk) begin
if (cpu.ir == 32'hFFFFFFFF) begin
$display("PC> EXIT");
@@ -80,7 +99,7 @@ always @(posedge clk) begin
cpu.REGS.R[15]
);
end
-
+*/
endmodule
module teleprinter (
diff --git a/verilog/uart.v b/verilog/uart.v
@@ -1,10 +1,11 @@
// Copyright 2012, Brian Swetland. If it breaks, you keep both halves.
+// todo: wire up a divisor register
+
`timescale 1ns/1ns
module uart(
input clk,
- input bclk,
input reset,
input [7:0] wdata,
output [7:0] rdata,
@@ -12,41 +13,73 @@ module uart(
output tx
);
-reg [7:0] tx_fifo;
-reg [12:0] tx_shift;
-reg [3:0] tx_count;
-
-wire tx_busy;
-reg tx_start;
+reg out;
+reg busy;
+reg [7:0] data;
+reg [3:0] state;
+wire next_bit;
-assign rdata = { 7'h0, tx_busy };
-assign tx = tx_shift[0];
-assign tx_busy = (tx_count != 0);
+counter bitcounter(
+ .clk(clk),
+ .reset(reset),
+ .max(16'd434),
+ .overflow(next_bit)
+ );
-always @(posedge bclk, posedge reset) begin
- if (reset) begin
- tx_count <= 0;
- tx_shift <= 13'hFFFF;
- end else if (tx_busy) begin
- tx_shift <= { 1'b0, tx_shift[12:1] };
- tx_count <= ( tx_count - 1 );
- end else if (tx_start) begin
- tx_shift[12:1] <= { 2'b11, tx_fifo, 1'b0 };
- tx_count <= 11;
- end
-end
+assign tx = out;
+assign rdata = { 7'b0, busy };
-always @(posedge clk) begin
+always @(posedge clk or posedge reset)
+begin
if (reset) begin
- tx_start <= 0;
+ out <= 1'b1;
+ busy <= 1'b1;
+ state <= 4'b0010;
+ data <= 8'hFF;
end else begin
- if (tx_busy)
- tx_start <= 0;
- else if (we) begin
- tx_fifo <= wdata;
- tx_start <= 1;
+ if (we) begin
+ data <= wdata;
+ busy <= 1'b1;
+ end
+ if (next_bit) begin
+ case (state)
+ 4'b0000: begin state <= (busy ? 4'b0001 : 4'b0000); out <= 1'b1; end
+ 4'b0001: begin state <= 4'b0010; out <= 1'b0; end
+ 4'b0010: begin state <= 4'b0011; out <= data[0]; end
+ 4'b0011: begin state <= 4'b0100; out <= data[1]; end
+ 4'b0100: begin state <= 4'b0101; out <= data[2]; end
+ 4'b0101: begin state <= 4'b0110; out <= data[3]; end
+ 4'b0110: begin state <= 4'b0111; out <= data[4]; end
+ 4'b0111: begin state <= 4'b1000; out <= data[5]; end
+ 4'b1000: begin state <= 4'b1001; out <= data[6]; end
+ 4'b1001: begin state <= 4'b1010; out <= data[7]; end
+ 4'b1010: begin state <= 4'b0000; out <= 1'b1; busy <= 1'b0; end
+ endcase
end
end
end
+
endmodule
+module counter(
+ input clk,
+ input reset,
+ input [15:0] max,
+ output overflow
+ );
+
+reg [15:0] count;
+
+assign overflow = (count == max);
+
+always @(posedge clk or posedge reset)
+begin
+ if (reset)
+ count <= 16'b0;
+ else
+ count <= overflow ? 16'b0 : (count + 16'b1);
+end
+
+endmodule
+
+