cpu32

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

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:
MMakefile | 1+
Mde0nano/de0nano.v | 36++++--------------------------------
Mde0nano/fw.s | 62++++++++++++++++++++++++++++++++------------------------------
Mverilog/testbench.v | 29++++++++++++++++++++++++-----
Mverilog/uart.v | 91++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
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 + +