From a76977af62010a392c16010c367185e61e856ffe Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Wed, 30 Oct 2019 20:04:56 +0100 Subject: mv to docs --- docs/j1/verilog/uart.v | 180 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 docs/j1/verilog/uart.v (limited to 'docs/j1/verilog/uart.v') diff --git a/docs/j1/verilog/uart.v b/docs/j1/verilog/uart.v new file mode 100644 index 0000000..4daac0f --- /dev/null +++ b/docs/j1/verilog/uart.v @@ -0,0 +1,180 @@ +`default_nettype none + +module baudgen( + input wire clk, + input wire resetq, + input wire [31:0] baud, + input wire restart, + output wire ser_clk); + parameter CLKFREQ = 1000000; + + wire [38:0] aclkfreq = CLKFREQ; + reg [38:0] d; + wire [38:0] dInc = d[38] ? ({4'd0, baud}) : (({4'd0, baud}) - aclkfreq); + wire [38:0] dN = restart ? 0 : (d + dInc); + wire fastclk = ~d[38]; + assign ser_clk = fastclk; + + always @(negedge resetq or posedge clk) + begin + if (!resetq) begin + d <= 0; + end else begin + d <= dN; + end + end +endmodule + +/* + +-----+ +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+---- + | | | | | | | | | | | | + |start| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |stop1|stop2| + | | | | | | | | | | | ? | + +-----+-----+-----+-----+-----+-----+-----+-----+-----+ + + +*/ + +module uart( + input wire clk, // System clock + input wire resetq, + + // Outputs + output wire uart_busy, // High means UART is transmitting + output reg uart_tx, // UART transmit wire + // Inputs + input wire [31:0] baud, + input wire uart_wr_i, // Raise to transmit byte + input wire [7:0] uart_dat_i // 8-bit data +); + parameter CLKFREQ = 1000000; + + reg [3:0] bitcount; + reg [8:0] shifter; + + assign uart_busy = |bitcount; + wire sending = |bitcount; + + wire ser_clk; + + wire starting = uart_wr_i & ~uart_busy; + baudgen #(.CLKFREQ(CLKFREQ)) _baudgen( + .clk(clk), + .resetq(resetq), + .baud(baud), + .restart(1'b0), + .ser_clk(ser_clk)); + + always @(negedge resetq or posedge clk) + begin + if (!resetq) begin + uart_tx <= 1; + bitcount <= 0; + shifter <= 0; + end else begin + if (starting) begin + shifter <= { uart_dat_i[7:0], 1'b0 }; + bitcount <= 1 + 8 + 1; + end + + if (sending & ser_clk) begin + { shifter, uart_tx } <= { 1'b1, shifter }; + bitcount <= bitcount - 4'd1; + end + end + end + +endmodule + +module rxuart( + input wire clk, + input wire resetq, + input wire [31:0] baud, + input wire uart_rx, // UART recv wire + input wire rd, // read strobe + output wire valid, // has data + output wire [7:0] data); // data + parameter CLKFREQ = 1000000; + + reg [4:0] bitcount; + reg [7:0] shifter; + + // On starting edge, wait 3 half-bits then sample, and sample every 2 bits thereafter + + wire idle = &bitcount; + wire sample; + reg [2:0] hh = 3'b111; + wire [2:0] hhN = {hh[1:0], uart_rx}; + wire startbit = idle & (hhN[2:1] == 2'b10); + wire [7:0] shifterN = sample ? {hh[1], shifter[7:1]} : shifter; + + wire ser_clk; + baudgen #(.CLKFREQ(CLKFREQ)) _baudgen( + .clk(clk), + .baud({baud[30:0], 1'b0}), + .resetq(resetq), + .restart(startbit), + .ser_clk(ser_clk)); + + assign valid = (bitcount == 18); + reg [4:0] bitcountN; + always @* + if (startbit) + bitcountN = 0; + else if (!idle & !valid & ser_clk) + bitcountN = bitcount + 5'd1; + else if (valid & rd) + bitcountN = 5'b11111; + else + bitcountN = bitcount; + + // 3,5,7,9,11,13,15,17 + assign sample = (bitcount > 2) & bitcount[0] & !valid & ser_clk; + assign data = shifter; + + always @(negedge resetq or posedge clk) + begin + if (!resetq) begin + hh <= 3'b111; + bitcount <= 5'b11111; + shifter <= 0; + end else begin + hh <= hhN; + bitcount <= bitcountN; + shifter <= shifterN; + end + end +endmodule + +module buart( + input wire clk, + input wire resetq, + input wire [31:0] baud, + input wire rx, // recv wire + output wire tx, // xmit wire + input wire rd, // read strobe + input wire wr, // write strobe + output wire valid, // has recv data + output wire busy, // is transmitting + input wire [7:0] tx_data, + output wire [7:0] rx_data // data +); + parameter CLKFREQ = 1000000; + + rxuart #(.CLKFREQ(CLKFREQ)) _rx ( + .clk(clk), + .resetq(resetq), + .baud(baud), + .uart_rx(rx), + .rd(rd), + .valid(valid), + .data(rx_data)); + uart #(.CLKFREQ(CLKFREQ)) _tx ( + .clk(clk), + .resetq(resetq), + .baud(baud), + .uart_busy(busy), + .uart_tx(tx), + .uart_wr_i(wr), + .uart_dat_i(tx_data)); +endmodule -- cgit v1.2.3