From 6b319525d13feeeb1ec9afbc1fd96688c9cb699d Mon Sep 17 00:00:00 2001 From: Angelo Jacobo Date: Sun, 22 Sep 2024 14:19:08 +0800 Subject: [PATCH] added example demo files for ALINX AX7103 board --- example_demo/alinx_ax7103b/ax7103_ddr3.v | 217 +++++++++++++++++++++++ example_demo/alinx_ax7103b/clk_wiz.v | 66 +++++++ example_demo/alinx_ax7103b/uart.v | 113 ++++++++++++ example_demo/alinx_ax7103b/uart_rx.v | 142 +++++++++++++++ example_demo/alinx_ax7103b/uart_tx.v | 115 ++++++++++++ 5 files changed, 653 insertions(+) create mode 100644 example_demo/alinx_ax7103b/ax7103_ddr3.v create mode 100644 example_demo/alinx_ax7103b/clk_wiz.v create mode 100644 example_demo/alinx_ax7103b/uart.v create mode 100644 example_demo/alinx_ax7103b/uart_rx.v create mode 100644 example_demo/alinx_ax7103b/uart_tx.v diff --git a/example_demo/alinx_ax7103b/ax7103_ddr3.v b/example_demo/alinx_ax7103b/ax7103_ddr3.v new file mode 100644 index 0000000..edd628f --- /dev/null +++ b/example_demo/alinx_ax7103b/ax7103_ddr3.v @@ -0,0 +1,217 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Filename: ax7103_ddr3.v +// Project: UberDDR3 - An Open Source DDR3 Controller +// +// Purpose: Example demo of UberDDR3 for ALINX AX7103 (c7a100tfgg484-2). Mechanism: +// - four LEDs will light up once UberDDR3 is done calibrating +// - if UART (9600 Baud Rate)receives small letter ASCII (a-z), this value will be written to DDR3 +// - if UART receives capital letter ASCII (A-Z), the small letter equivalent will be retrieved from DDR3 by doing +// - a read request, once read data is available this will be sent to UART to be streamed out. +// THUS: +// - Sendng "abcdefg" to the UART terminal will store that small latter to DDR3 +// - Then sending "ABCDEFG" to the UART terminal will return the small letter equivalent: "abcdefg" +// +// Engineer: Angelo C. Jacobo +// +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023-2024 Angelo Jacobo +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +//////////////////////////////////////////////////////////////////////////////// + +`timescale 1ns / 1ps + + module ax7103_ddr3 + ( + input wire sys_clk_p, // system clock positive on board + input wire sys_clk_n, //system clock negative on board + input wire i_rst_n, + // DDR3 I/O Interface + output wire[0:0] ddr3_ck_p, ddr3_ck_n, + output wire ddr3_reset_n, + output wire[0:0] ddr3_cke, + output wire[0:0] ddr3_cs_n, + output wire ddr3_ras_n, + output wire ddr3_cas_n, + output wire ddr3_we_n, + output wire[15-1:0] ddr3_addr, + output wire[3-1:0] ddr3_ba, + inout wire[32-1:0] ddr3_dq, + inout wire[4-1:0] ddr3_dqs_p, ddr3_dqs_n, + output wire[4-1:0] ddr3_dm, + output wire[0:0] ddr3_odt, + // UART line + input wire rx, + output wire tx, + //Debug LEDs + output wire[3:0] led + ); + wire sys_clk_200MHz; + + IBUFDS sys_clk_ibufgds + ( + .O(sys_clk_200MHz), + .I(sys_clk_p), + .IB(sys_clk_n) + ); + + wire i_controller_clk, i_ddr3_clk, i_ref_clk, i_ddr3_clk_90; + wire m_axis_tvalid; + wire rx_empty; + wire tx_full; + wire o_wb_ack; + wire[7:0] o_wb_data; + wire o_aux; + wire[7:0] rd_data; + wire o_wb_stall; + reg i_wb_stb = 0, i_wb_we; + wire[63:0] o_debug1; + reg[7:0] i_wb_data; + reg[7:0] i_wb_addr; + // o_debug1 taps on value of state_calibrate (can be traced inside ddr3_controller module) + assign led[0] = !(o_debug1[4:0] == 23); //light up if at DONE_CALIBRATE + assign led[1] = !(o_debug1[4:0] == 23); //light up if at DONE_CALIBRATE + assign led[2] = !(o_debug1[4:0] == 23); //light up if at DONE_CALIBRATE + assign led[3] = !(o_debug1[4:0] == 23); //light up if at DONE_CALIBRATE + + always @(posedge i_controller_clk) begin + begin + i_wb_stb <= 0; + i_wb_we <= 0; + i_wb_addr <= 0; + i_wb_data <= 0; + if(!o_wb_stall && m_axis_tvalid) begin + if(rd_data >= 97 && rd_data <= 122) begin //write to DDR3 if ASCII is small letter + i_wb_stb <= 1; + i_wb_we <= 1; + i_wb_addr <= ~rd_data ; + i_wb_data <= rd_data; + end + else if(rd_data >= 65 && rd_data <= 90) begin //read from DDR3 if ASCII is capital letter + i_wb_stb <= 1; //make request + i_wb_we <= 0; //read + i_wb_addr <= ~(rd_data + 8'd32); + end + end + end + end + + wire clk_locked; + clk_wiz clk_wiz_inst + ( + // Clock out ports + .clk_out1(i_controller_clk), //100 Mhz + .clk_out2(i_ddr3_clk), // 400 MHz + .clk_out3(i_ref_clk), // 200 MHz + .clk_out4(i_ddr3_clk_90), // 400 MHz 90-degree + // Status and control signals + .reset(!i_rst_n), + .locked(clk_locked), + // Clock in ports + .clk_in1(sys_clk_200MHz) + ); + + // UART module from https://github.com/alexforencich/verilog-uart + uart #(.DATA_WIDTH(8)) uart_m + ( + .clk(i_controller_clk), + .rst(!i_rst_n), + .s_axis_tdata(o_wb_data), + .s_axis_tvalid(o_wb_ack), + .s_axis_tready(), + .m_axis_tdata(rd_data), + .m_axis_tvalid(m_axis_tvalid), + .m_axis_tready(1), + .rxd(rx), + .txd(tx), + .prescale(1302) //9600 Baud Rate: 100MHz/(8*9600) + ); + + // DDR3 Controller + ddr3_top #( + .CONTROLLER_CLK_PERIOD(10_000), //ps, clock period of the controller interface + .DDR3_CLK_PERIOD(2_500), //ps, clock period of the DDR3 RAM device (must be 1/4 of the CONTROLLER_CLK_PERIOD) + .ROW_BITS(15), //width of row address + .COL_BITS(10), //width of column address + .BA_BITS(3), //width of bank address + .BYTE_LANES(4), //number of DDR3 modules to be controlled + .AUX_WIDTH(16), //width of aux line (must be >= 4) + .WB2_ADDR_BITS(32), //width of 2nd wishbone address bus + .WB2_DATA_BITS(32), //width of 2nd wishbone data bus + .MICRON_SIM(0), //enable faster simulation for micron ddr3 model (shorten POWER_ON_RESET_HIGH and INITIAL_CKE_LOW) + .ODELAY_SUPPORTED(0), //set to 1 when ODELAYE2 is supported + .SECOND_WISHBONE(0), //set to 1 if 2nd wishbone is needed + .ECC_ENABLE(0), // set to 1 or 2 to add ECC (1 = Side-band ECC per burst, 2 = Side-band ECC per 8 bursts , 3 = Inline ECC ) + .WB_ERROR(0), // set to 1 to support Wishbone error (asserts at ECC double bit error) + .DIC(2'b01), //Output Driver Impedance Control (2'b00 = RZQ/6, 2'b01 = RZQ/7, RZQ = 240ohms) (only change when you know what you are doing) + .RTT_NOM(3'b001) //RTT Nominal (3'b000 = disabled, 3'b001 = RZQ/4, 3'b010 = RZQ/2 , 3'b011 = RZQ/6, RZQ = 240ohms) (only change when you know what you + ) ddr3_top + ( + //clock and reset + .i_controller_clk(i_controller_clk), + .i_ddr3_clk(i_ddr3_clk), //i_controller_clk has period of CONTROLLER_CLK_PERIOD, i_ddr3_clk has period of DDR3_CLK_PERIOD + .i_ref_clk(i_ref_clk), + .i_ddr3_clk_90(i_ddr3_clk_90), + .i_rst_n(i_rst_n && clk_locked), + // Wishbone inputs + .i_wb_cyc(1), //bus cycle active (1 = normal operation, 0 = all ongoing transaction are to be cancelled) + .i_wb_stb(i_wb_stb), //request a transfer + .i_wb_we(i_wb_we), //write-enable (1 = write, 0 = read) + .i_wb_addr(i_wb_addr), //burst-addressable {row,bank,col} + .i_wb_data(i_wb_data), //write data, for a 4:1 controller data width is 8 times the number of pins on the device + .i_wb_sel(16'hffff), //byte strobe for write (1 = write the byte) + .i_aux(i_wb_we), //for AXI-interface compatibility (given upon strobe) + // Wishbone outputs + .o_wb_stall(o_wb_stall), //1 = busy, cannot accept requests + .o_wb_ack(o_wb_ack), //1 = read/write request has completed + .o_wb_data(o_wb_data), //read data, for a 4:1 controller data width is 8 times the number of pins on the device + .o_aux(o_aux), + // Wishbone 2 (PHY) inputs + .i_wb2_cyc(), //bus cycle active (1 = normal operation, 0 = all ongoing transaction are to be cancelled) + .i_wb2_stb(), //request a transfer + .i_wb2_we(), //write-enable (1 = write, 0 = read) + .i_wb2_addr(), //burst-addressable {row,bank,col} + .i_wb2_data(), //write data, for a 4:1 controller data width is 8 times the number of pins on the device + .i_wb2_sel(), //byte strobe for write (1 = write the byte) + // Wishbone 2 (Controller) outputs + .o_wb2_stall(), //1 = busy, cannot accept requests + .o_wb2_ack(), //1 = read/write request has completed + .o_wb2_data(), //read data, for a 4:1 controller data width is 8 times the number of pins on the device + // PHY Interface (to be added later) + // DDR3 I/O Interface + .o_ddr3_clk_p(ddr3_ck_p), + .o_ddr3_clk_n(ddr3_ck_n), + .o_ddr3_reset_n(ddr3_reset_n), + .o_ddr3_cke(ddr3_cke), // CKE + .o_ddr3_cs_n(ddr3_cs_n), // chip select signal (controls rank 1 only) + .o_ddr3_ras_n(ddr3_ras_n), // RAS# + .o_ddr3_cas_n(ddr3_cas_n), // CAS# + .o_ddr3_we_n(ddr3_we_n), // WE# + .o_ddr3_addr(ddr3_addr), + .o_ddr3_ba_addr(ddr3_ba), + .io_ddr3_dq(ddr3_dq), + .io_ddr3_dqs(ddr3_dqs_p), + .io_ddr3_dqs_n(ddr3_dqs_n), + .o_ddr3_dm(ddr3_dm), + .o_ddr3_odt(ddr3_odt), // on-die termination + .o_debug1(o_debug1), + .o_debug2(), + .o_debug3() + ); + +endmodule + diff --git a/example_demo/alinx_ax7103b/clk_wiz.v b/example_demo/alinx_ax7103b/clk_wiz.v new file mode 100644 index 0000000..f3c2dd4 --- /dev/null +++ b/example_demo/alinx_ax7103b/clk_wiz.v @@ -0,0 +1,66 @@ +`timescale 1ps/1ps + +module clk_wiz + ( + input clk_in1, + output clk_out1, + output clk_out2, + output clk_out3, + output clk_out4, + input reset, + output locked + ); + wire clk_out1_clk_wiz_0; + wire clk_out2_clk_wiz_0; + wire clk_out3_clk_wiz_0; + wire clk_out4_clk_wiz_0; + + wire clkfbout; + + PLLE2_ADV + #(.BANDWIDTH ("OPTIMIZED"), + .COMPENSATION ("INTERNAL"), + .STARTUP_WAIT ("FALSE"), + .DIVCLK_DIVIDE (1), + .CLKFBOUT_MULT (4), // 200 MHz * 4 = 800 MHz + .CLKFBOUT_PHASE (0.000), + .CLKOUT0_DIVIDE (8), // 800 MHz / 8 = 100 MHz + .CLKOUT0_PHASE (0.000), + .CLKOUT0_DUTY_CYCLE (0.500), + .CLKOUT1_DIVIDE (2), // 800 MHz / 2 = 400 MHz + .CLKOUT1_PHASE (0.000), + .CLKOUT1_DUTY_CYCLE (0.500), + .CLKOUT2_DIVIDE (4), // 800 MHz / 4 = 200 MHz + .CLKOUT2_PHASE (0.000), + .CLKOUT2_DUTY_CYCLE (0.500), + .CLKOUT3_DIVIDE (2), // 800 MHz / 2 = 400 MHz + .CLKOUT3_PHASE (90), + .CLKOUT3_DUTY_CYCLE (0.500), + .CLKIN1_PERIOD (5.000) // 200 MHz input + ) + plle2_adv_inst + ( + .CLKFBOUT (clkfbout), + .CLKOUT0 (clk_out1_clk_wiz_0), + .CLKOUT1 (clk_out2_clk_wiz_0), + .CLKOUT2 (clk_out3_clk_wiz_0), + .CLKOUT3 (clk_out4_clk_wiz_0), + .CLKFBIN (clkfbout), + .CLKIN1 (clk_in1), + .LOCKED (locked), + .RST (reset) + ); + BUFG clkout1_buf + (.O (clk_out1), + .I (clk_out1_clk_wiz_0)); + BUFG clkout2_buf + (.O (clk_out2), + .I (clk_out2_clk_wiz_0)); + BUFG clkout3_buf + (.O (clk_out3), + .I (clk_out3_clk_wiz_0)); + BUFG clkout4_buf + (.O (clk_out4), + .I (clk_out4_clk_wiz_0)); + +endmodule diff --git a/example_demo/alinx_ax7103b/uart.v b/example_demo/alinx_ax7103b/uart.v new file mode 100644 index 0000000..a09d895 --- /dev/null +++ b/example_demo/alinx_ax7103b/uart.v @@ -0,0 +1,113 @@ +/* + +Copyright (c) 2014-2017 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`timescale 1ns / 1ps + +/* + * AXI4-Stream UART + */ +module uart # +( + parameter DATA_WIDTH = 8 +) +( + input wire clk, + input wire rst, + + /* + * AXI input + */ + input wire [DATA_WIDTH-1:0] s_axis_tdata, + input wire s_axis_tvalid, + output wire s_axis_tready, + + /* + * AXI output + */ + output wire [DATA_WIDTH-1:0] m_axis_tdata, + output wire m_axis_tvalid, + input wire m_axis_tready, + + /* + * UART interface + */ + input wire rxd, + output wire txd, + + /* + * Status + */ + output wire tx_busy, + output wire rx_busy, + output wire rx_overrun_error, + output wire rx_frame_error, + + /* + * Configuration + */ + input wire [15:0] prescale + +); + +uart_tx #( + .DATA_WIDTH(DATA_WIDTH) +) +uart_tx_inst ( + .clk(clk), + .rst(rst), + // axi input + .s_axis_tdata(s_axis_tdata), + .s_axis_tvalid(s_axis_tvalid), + .s_axis_tready(s_axis_tready), + // output + .txd(txd), + // status + .busy(tx_busy), + // configuration + .prescale(prescale) +); + +uart_rx #( + .DATA_WIDTH(DATA_WIDTH) +) +uart_rx_inst ( + .clk(clk), + .rst(rst), + // axi output + .m_axis_tdata(m_axis_tdata), + .m_axis_tvalid(m_axis_tvalid), + .m_axis_tready(m_axis_tready), + // input + .rxd(rxd), + // status + .busy(rx_busy), + .overrun_error(rx_overrun_error), + .frame_error(rx_frame_error), + // configuration + .prescale(prescale) +); + +endmodule diff --git a/example_demo/alinx_ax7103b/uart_rx.v b/example_demo/alinx_ax7103b/uart_rx.v new file mode 100644 index 0000000..9823be8 --- /dev/null +++ b/example_demo/alinx_ax7103b/uart_rx.v @@ -0,0 +1,142 @@ +/* + +Copyright (c) 2014-2017 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`timescale 1ns / 1ps + +/* + * AXI4-Stream UART + */ +module uart_rx # +( + parameter DATA_WIDTH = 8 +) +( + input wire clk, + input wire rst, + + /* + * AXI output + */ + output wire [DATA_WIDTH-1:0] m_axis_tdata, + output wire m_axis_tvalid, + input wire m_axis_tready, + + /* + * UART interface + */ + input wire rxd, + + /* + * Status + */ + output wire busy, + output wire overrun_error, + output wire frame_error, + + /* + * Configuration + */ + input wire [15:0] prescale + +); + +reg [DATA_WIDTH-1:0] m_axis_tdata_reg = 0; +reg m_axis_tvalid_reg = 0; + +reg rxd_reg = 1; + +reg busy_reg = 0; +reg overrun_error_reg = 0; +reg frame_error_reg = 0; + +reg [DATA_WIDTH-1:0] data_reg = 0; +reg [18:0] prescale_reg = 0; +reg [3:0] bit_cnt = 0; + +assign m_axis_tdata = m_axis_tdata_reg; +assign m_axis_tvalid = m_axis_tvalid_reg; + +assign busy = busy_reg; +assign overrun_error = overrun_error_reg; +assign frame_error = frame_error_reg; + +always @(posedge clk) begin + if (rst) begin + m_axis_tdata_reg <= 0; + m_axis_tvalid_reg <= 0; + rxd_reg <= 1; + prescale_reg <= 0; + bit_cnt <= 0; + busy_reg <= 0; + overrun_error_reg <= 0; + frame_error_reg <= 0; + end else begin + rxd_reg <= rxd; + overrun_error_reg <= 0; + frame_error_reg <= 0; + + if (m_axis_tvalid && m_axis_tready) begin + m_axis_tvalid_reg <= 0; + end + + if (prescale_reg > 0) begin + prescale_reg <= prescale_reg - 1; + end else if (bit_cnt > 0) begin + if (bit_cnt > DATA_WIDTH+1) begin + if (!rxd_reg) begin + bit_cnt <= bit_cnt - 1; + prescale_reg <= (prescale << 3)-1; + end else begin + bit_cnt <= 0; + prescale_reg <= 0; + end + end else if (bit_cnt > 1) begin + bit_cnt <= bit_cnt - 1; + prescale_reg <= (prescale << 3)-1; + data_reg <= {rxd_reg, data_reg[DATA_WIDTH-1:1]}; + end else if (bit_cnt == 1) begin + bit_cnt <= bit_cnt - 1; + if (rxd_reg) begin + m_axis_tdata_reg <= data_reg; + m_axis_tvalid_reg <= 1; + overrun_error_reg <= m_axis_tvalid_reg; + end else begin + frame_error_reg <= 1; + end + end + end else begin + busy_reg <= 0; + if (!rxd_reg) begin + prescale_reg <= (prescale << 2)-2; + bit_cnt <= DATA_WIDTH+2; + data_reg <= 0; + busy_reg <= 1; + end + end + end +end + +endmodule diff --git a/example_demo/alinx_ax7103b/uart_tx.v b/example_demo/alinx_ax7103b/uart_tx.v new file mode 100644 index 0000000..bc53ac8 --- /dev/null +++ b/example_demo/alinx_ax7103b/uart_tx.v @@ -0,0 +1,115 @@ +/* + +Copyright (c) 2014-2017 Alex Forencich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +// Language: Verilog 2001 + +`timescale 1ns / 1ps + +/* + * AXI4-Stream UART + */ +module uart_tx # +( + parameter DATA_WIDTH = 8 +) +( + input wire clk, + input wire rst, + + /* + * AXI input + */ + input wire [DATA_WIDTH-1:0] s_axis_tdata, + input wire s_axis_tvalid, + output wire s_axis_tready, + + /* + * UART interface + */ + output wire txd, + + /* + * Status + */ + output wire busy, + + /* + * Configuration + */ + input wire [15:0] prescale +); + +reg s_axis_tready_reg = 0; + +reg txd_reg = 1; + +reg busy_reg = 0; + +reg [DATA_WIDTH:0] data_reg = 0; +reg [18:0] prescale_reg = 0; +reg [3:0] bit_cnt = 0; + +assign s_axis_tready = s_axis_tready_reg; +assign txd = txd_reg; + +assign busy = busy_reg; + +always @(posedge clk) begin + if (rst) begin + s_axis_tready_reg <= 0; + txd_reg <= 1; + prescale_reg <= 0; + bit_cnt <= 0; + busy_reg <= 0; + end else begin + if (prescale_reg > 0) begin + s_axis_tready_reg <= 0; + prescale_reg <= prescale_reg - 1; + end else if (bit_cnt == 0) begin + s_axis_tready_reg <= 1; + busy_reg <= 0; + + if (s_axis_tvalid) begin + s_axis_tready_reg <= !s_axis_tready_reg; + prescale_reg <= (prescale << 3)-1; + bit_cnt <= DATA_WIDTH+1; + data_reg <= {1'b1, s_axis_tdata}; + txd_reg <= 0; + busy_reg <= 1; + end + end else begin + if (bit_cnt > 1) begin + bit_cnt <= bit_cnt - 1; + prescale_reg <= (prescale << 3)-1; + {data_reg, txd_reg} <= {1'b0, data_reg}; + end else if (bit_cnt == 1) begin + bit_cnt <= bit_cnt - 1; + prescale_reg <= (prescale << 3); + txd_reg <= 1; + end + end + end +end + +endmodule