added nexys video makefile for openxc7 run
This commit is contained in:
parent
848bd3b613
commit
06b6f8f085
|
|
@ -0,0 +1,70 @@
|
||||||
|
PROJECT = nexysvideo_ddr3
|
||||||
|
FAMILY = artix7
|
||||||
|
PART = xc7a200tsbg484-1
|
||||||
|
CHIPDB = ${ARTIX7_CHIPDB}
|
||||||
|
ADDITIONAL_SOURCES = ../../rtl/ddr3_controller.v ../../rtl/ddr3_phy.v ../../rtl/ddr3_top.v uart_rx.v uart_tx.v clk_wiz.v
|
||||||
|
|
||||||
|
#############################################################################################
|
||||||
|
NEXTPNR_XILINX_DIR ?= /snap/openxc7/current/opt/nextpnr-xilinx
|
||||||
|
NEXTPNR_XILINX_PYTHON_DIR ?= ${NEXTPNR_XILINX_DIR}/python
|
||||||
|
PRJXRAY_DB_DIR ?= ${NEXTPNR_XILINX_DIR}/external/prjxray-db
|
||||||
|
|
||||||
|
DBPART = $(shell echo ${PART} | sed -e 's/-[0-9]//g')
|
||||||
|
SPEEDGRADE = $(shell echo ${PART} | sed -e 's/.*\-\([0-9]\)/\1/g')
|
||||||
|
|
||||||
|
CHIPDB ?= ./
|
||||||
|
ifeq ($(CHIPDB),)
|
||||||
|
CHIPDB = ./
|
||||||
|
endif
|
||||||
|
|
||||||
|
PYPY3 ?= pypy3
|
||||||
|
|
||||||
|
TOP ?= ${PROJECT}
|
||||||
|
TOP_MODULE ?= ${TOP}
|
||||||
|
TOP_VERILOG ?= ${TOP}.v
|
||||||
|
|
||||||
|
PNR_DEBUG ?= # --verbose --debug
|
||||||
|
|
||||||
|
BOARD ?= UNKNOWN
|
||||||
|
JTAG_LINK ?= --board ${BOARD}
|
||||||
|
|
||||||
|
XDC ?= ${PROJECT}.xdc
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: ${PROJECT}.bit
|
||||||
|
|
||||||
|
.PHONY: program
|
||||||
|
program: ${PROJECT}.bit
|
||||||
|
openFPGALoader ${JTAG_LINK} --bitstream $<
|
||||||
|
|
||||||
|
${PROJECT}.json: ${TOP_VERILOG} ${ADDITIONAL_SOURCES}
|
||||||
|
yosys -p "synth_xilinx -flatten -abc9 ${SYNTH_OPTS} -arch xc7 -top ${TOP_MODULE}; write_json ${PROJECT}.json" $< ${ADDITIONAL_SOURCES}
|
||||||
|
|
||||||
|
# The chip database only needs to be generated once
|
||||||
|
# that is why we don't clean it with make clean
|
||||||
|
${CHIPDB}/${DBPART}.bin:
|
||||||
|
${PYPY3} ${NEXTPNR_XILINX_PYTHON_DIR}/bbaexport.py --device ${PART} --bba ${DBPART}.bba
|
||||||
|
bbasm -l ${DBPART}.bba ${CHIPDB}/${DBPART}.bin
|
||||||
|
rm -f ${DBPART}.bba
|
||||||
|
|
||||||
|
${PROJECT}.fasm: ${PROJECT}.json ${CHIPDB}/${DBPART}.bin ${XDC}
|
||||||
|
nextpnr-xilinx --chipdb ${CHIPDB}/${DBPART}.bin --xdc ${XDC} --json ${PROJECT}.json --fasm $@ ${PNR_ARGS} ${PNR_DEBUG}
|
||||||
|
|
||||||
|
${PROJECT}.frames: ${PROJECT}.fasm
|
||||||
|
fasm2frames --part ${PART} --db-root ${PRJXRAY_DB_DIR}/${FAMILY} $< > $@
|
||||||
|
|
||||||
|
${PROJECT}.bit: ${PROJECT}.frames
|
||||||
|
xc7frames2bit --part_file ${PRJXRAY_DB_DIR}/${FAMILY}/${PART}/part.yaml --part_name ${PART} --frm_file $< --output_file $@
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
@rm -f *.bit
|
||||||
|
@rm -f *.frames
|
||||||
|
@rm -f *.fasm
|
||||||
|
@rm -f *.json
|
||||||
|
@rm -f *.bin
|
||||||
|
@rm -f *.bba
|
||||||
|
|
||||||
|
.PHONY: pnrclean
|
||||||
|
pnrclean:
|
||||||
|
rm *.fasm *.frames *.bit
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
# Generated by https://github.com/FPGAOL-CE/caas-wizard
|
|
||||||
DB_DIR = /nextpnr-xilinx/xilinx/external/prjxray-db
|
|
||||||
CHIPDB = ./chipdb
|
|
||||||
|
|
||||||
BUILDDIR := ${CURDIR}/build
|
|
||||||
TOP := nexysvideo_ddr3
|
|
||||||
#SOURCES := $(wildcard *.v ../../rtl/ddr3*.v)
|
|
||||||
XDC := $(wildcard $(wildcard Nexys-video.xdc) )
|
|
||||||
|
|
||||||
CHIPFAM := artix7
|
|
||||||
PART := xc7a200tsbg484-1
|
|
||||||
|
|
||||||
LOGFILE := ${BUILDDIR}/top.log
|
|
||||||
|
|
||||||
all: ${CHIPDB} ${BUILDDIR} ${BUILDDIR}/top.bit
|
|
||||||
|
|
||||||
${BUILDDIR}:
|
|
||||||
mkdir -m 777 -p ${BUILDDIR} && chown -R nobody ${BUILDDIR} | true
|
|
||||||
|
|
||||||
${CHIPDB}:
|
|
||||||
mkdir -m 777 -p ${CHIPDB} && chown -R nobody ${CHIPDB} | true
|
|
||||||
|
|
||||||
# we run this in parent directory to seeminglessly import user source files
|
|
||||||
# otherwise have to parse user pattern and add ../
|
|
||||||
${BUILDDIR}/top.json: $(wildcard *.v) $(wildcard ../../rtl/*.v)
|
|
||||||
yosys -p "synth_xilinx -flatten -abc9 -arch xc7 -top ${TOP}; write_json ${BUILDDIR}/top.json" $^ >> ${LOGFILE} 2>&1
|
|
||||||
|
|
||||||
# The chip database only needs to be generated once
|
|
||||||
# that is why we don't clean it with make clean
|
|
||||||
${CHIPDB}/${PART}.bin:
|
|
||||||
pypy3 /nextpnr-xilinx/xilinx/python/bbaexport.py --device ${PART} --bba ${PART}.bba
|
|
||||||
bbasm -l ${PART}.bba ${CHIPDB}/${PART}.bin
|
|
||||||
rm -f ${PART}.bba
|
|
||||||
|
|
||||||
${BUILDDIR}/top.fasm: ${BUILDDIR}/top.json ${CHIPDB}/${PART}.bin
|
|
||||||
nextpnr-xilinx --chipdb ${CHIPDB}/${PART}.bin --xdc ${XDC} --json ${BUILDDIR}/top.json --pre-place constraints.py --pre-route show_bels.py --fasm $@ >> ${LOGFILE} 2>&1
|
|
||||||
#nextpnr-xilinx --chipdb ${CHIPDB}/${PART}.bin --xdc ${XDC} --json ${BUILDDIR}/top.json --fasm $@ >> ${LOGFILE} 2>&1
|
|
||||||
|
|
||||||
${BUILDDIR}/top.frames: ${BUILDDIR}/top.fasm
|
|
||||||
fasm2frames --part ${PART} --db-root ${DB_DIR}/${CHIPFAM} $< > $@
|
|
||||||
|
|
||||||
${BUILDDIR}/top.bit: ${BUILDDIR}/top.frames
|
|
||||||
xc7frames2bit --part_file ${DB_DIR}/${CHIPFAM}/${PART}/part.yaml --part_name ${PART} --frm_file $< --output_file $@ >> ${LOGFILE} 2>&1
|
|
||||||
|
|
||||||
.PHONY: clean
|
|
||||||
clean:
|
|
||||||
@rm -f *.bit
|
|
||||||
@rm -f *.frames
|
|
||||||
@rm -f *.fasm
|
|
||||||
@rm -f *.json
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
# Generated by https://github.com/FPGAOL-CE/caas-wizard
|
|
||||||
BUILDDIR := ${CURDIR}/build
|
|
||||||
# TOP := nexysvideo_ddr3
|
|
||||||
# SOURCES := $(wildcard *.v ../../rtl/ddr3*.v)
|
|
||||||
# XDC := $(wildcard $(wildcard Nexys-video.xdc) $(wildcard Nexys-video-vivado.xdc) )
|
|
||||||
|
|
||||||
# PART := xc7a200tsbg484-1
|
|
||||||
|
|
||||||
LOGFILE := ${BUILDDIR}/top.log
|
|
||||||
|
|
||||||
# Build design
|
|
||||||
all: ${BUILDDIR}/top.bit
|
|
||||||
|
|
||||||
${BUILDDIR}:
|
|
||||||
mkdir -m 777 -p ${BUILDDIR} && chown -R nobody ${BUILDDIR} | true
|
|
||||||
|
|
||||||
.ONESHELL:
|
|
||||||
${BUILDDIR}/vivado.tcl: ${BUILDDIR}
|
|
||||||
cat << EOF > $@
|
|
||||||
# vivado.tcl generated for caas
|
|
||||||
# can be launched from any directory
|
|
||||||
cd ${BUILDDIR}
|
|
||||||
create_project -part xc7a200tsbg484-1 -force v_proj
|
|
||||||
set_property target_language Verilog [current_project]
|
|
||||||
cd ..
|
|
||||||
read_verilog [glob *.v ../../rtl/ddr3*.v]
|
|
||||||
read_xdc [glob $(wildcard Nexys-video.xdc) $(wildcard Nexys-video-vivado.xdc) ]
|
|
||||||
cd build
|
|
||||||
synth_design -top nexysvideo_ddr3
|
|
||||||
opt_design
|
|
||||||
place_design
|
|
||||||
phys_opt_design
|
|
||||||
route_design
|
|
||||||
write_bitstream -verbose -force top.bit
|
|
||||||
# report_utilization -file util.rpt
|
|
||||||
# report_timing_summary -file timing.rpt
|
|
||||||
EOF
|
|
||||||
|
|
||||||
${BUILDDIR}/top.bit: ${BUILDDIR}/vivado.tcl
|
|
||||||
cd ${BUILDDIR} && vivado -mode batch -source $< > ${LOGFILE} 2>&1
|
|
||||||
|
|
||||||
.PHONY: clean
|
|
||||||
clean:
|
|
||||||
rm -rf ${BUILDDIR}
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
set_property INTERNAL_VREF 0.75 [get_iobanks 35]
|
|
||||||
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
|
||||||
set_property CFGBVS VCCO [current_design]
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
ddr3_name = 'ddr3_top_inst.ddr3_phy_inst'
|
|
||||||
def get_cells(name_part):
|
|
||||||
return list(map(lambda c: c.second, filter(lambda c: name_part in c.first, ctx.cells)))
|
|
||||||
|
|
||||||
def get_cell(name_part):
|
|
||||||
return get_cells(name_part)[0]
|
|
||||||
|
|
||||||
c1=get_cell(ddr3_name + '.genblk5[0].ISERDESE2_train')
|
|
||||||
c3=get_cell(ddr3_name + '.genblk5[0].OSERDESE2_train')
|
|
||||||
|
|
||||||
# c2=get_cell(ddr3_name + '.genblk5[1].ISERDESE2_train')
|
|
||||||
# c4=get_cell(ddr3_name + '.genblk5[1].OSERDESE2_train')
|
|
||||||
|
|
||||||
# Usually, nextpnr-xilinx would place these on X0Y149, but
|
|
||||||
# prjxray has missing PIPs on _SING tiles, so we need to
|
|
||||||
# place these on a non-SING tile to make it work
|
|
||||||
c1.setAttr('BEL', 'ILOGIC_X1Y193/ISERDESE2')
|
|
||||||
c3.setAttr('BEL', 'OLOGIC_X1Y193/OSERDESE2')
|
|
||||||
# c2.setAttr('BEL', 'ILOGIC_X0Y245/ISERDESE2')
|
|
||||||
# c4.setAttr('BEL', 'OLOGIC_X0Y245/OSERDESE2')
|
|
||||||
Binary file not shown.
|
|
@ -93,34 +93,64 @@
|
||||||
(* mark_debug = "true" *) wire clk_locked;
|
(* mark_debug = "true" *) wire clk_locked;
|
||||||
clk_wiz clk_wiz_inst
|
clk_wiz clk_wiz_inst
|
||||||
(
|
(
|
||||||
// Clock out ports
|
// Clock out ports
|
||||||
.clk_out1(i_controller_clk), //83.333 Mhz
|
.clk_out1(i_controller_clk), //83.333 Mhz
|
||||||
.clk_out2(i_ddr3_clk), // 333.333 MHz
|
.clk_out2(i_ddr3_clk), // 333.333 MHz
|
||||||
.clk_out3(i_ref_clk), //200MHz
|
.clk_out3(i_ref_clk), //200MHz
|
||||||
.clk_out4(i_ddr3_clk_90), // 333.333 MHz with 90degree shift
|
.clk_out4(i_ddr3_clk_90), // 333.333 MHz with 90degree shift
|
||||||
// Status and control signals
|
// Status and control signals
|
||||||
.reset(i_rst),
|
.reset(i_rst),
|
||||||
.locked(clk_locked),
|
.locked(clk_locked),
|
||||||
// Clock in ports
|
// Clock in ports
|
||||||
.clk_in1(i_clk)
|
.clk_in1(i_clk)
|
||||||
);
|
|
||||||
|
|
||||||
// UART module from https://github.com/alexforencich/verilog-uart
|
|
||||||
uart #(.DATA_WIDTH(8)) uart_m
|
|
||||||
(
|
|
||||||
.clk(i_controller_clk),
|
|
||||||
.rst(i_rst),
|
|
||||||
.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(1085) //9600 Baud Rate
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// UART TX/RXmodule from https://github.com/ben-marshall/uart
|
||||||
|
uart_tx #(
|
||||||
|
.BIT_RATE(9600),
|
||||||
|
.CLK_HZ(83_333_333),
|
||||||
|
.PAYLOAD_BITS(8),
|
||||||
|
.STOP_BITS(1)
|
||||||
|
) uart_tx_inst (
|
||||||
|
.clk(i_controller_clk), // Top level system clock input.
|
||||||
|
.resetn(!i_rst && clk_locked && o_debug1[4:0] == 23), // Asynchronous active low reset.
|
||||||
|
.uart_txd(tx), // UART transmit pin.
|
||||||
|
.uart_tx_busy(), // Module busy sending previous item.
|
||||||
|
.uart_tx_en(o_wb_ack), // Send the data on uart_tx_data
|
||||||
|
.uart_tx_data(o_wb_data) // The data to be sent
|
||||||
|
);
|
||||||
|
uart_rx #(
|
||||||
|
.BIT_RATE(9600),
|
||||||
|
.CLK_HZ(83_333_333),
|
||||||
|
.PAYLOAD_BITS(8),
|
||||||
|
.STOP_BITS(1)
|
||||||
|
) uart_rx_inst (
|
||||||
|
.clk(i_controller_clk), // Top level system clock input.
|
||||||
|
.resetn(!i_rst && clk_locked && o_debug1[4:0] == 23), // Asynchronous active low reset.
|
||||||
|
.uart_rxd(rx), // UART Recieve pin.
|
||||||
|
.uart_rx_en(o_debug1[4:0] == 23), // Recieve enable
|
||||||
|
.uart_rx_break(), // Did we get a BREAK message?
|
||||||
|
.uart_rx_valid(m_axis_tvalid), // Valid data recieved/available.
|
||||||
|
.uart_rx_data(rd_data) // The recieved data.
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// UART module from https://github.com/alexforencich/verilog-uart (DOES NOT WORK ON OPENXC7, UberDDR3 cannot finish calibration when this UART is used)
|
||||||
|
// uart #(.DATA_WIDTH(8)) uart_m
|
||||||
|
// (
|
||||||
|
// .clk(i_controller_clk),
|
||||||
|
// .rst(i_rst),
|
||||||
|
// .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(1085) //9600 Baud Rate (83.33MHz/(8*9600))
|
||||||
|
// );
|
||||||
|
|
||||||
|
|
||||||
// DDR3 Controller
|
// DDR3 Controller
|
||||||
ddr3_top #(
|
ddr3_top #(
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
ddr3_name = 'ddr3_top_inst.ddr3_phy_inst'
|
|
||||||
def get_cells(name_part):
|
|
||||||
return list(map(lambda c: c.second, filter(lambda c: name_part in c.first, ctx.cells)))
|
|
||||||
|
|
||||||
def get_cell(name_part):
|
|
||||||
return get_cells(name_part)[0]
|
|
||||||
|
|
||||||
c1_name = ddr3_name + '.genblk5[0].ISERDESE2_train'
|
|
||||||
# c2_name = ddr3_name + '.genblk5[1].ISERDESE2_train'
|
|
||||||
c3_name = ddr3_name + '.genblk5[0].OSERDESE2_train'
|
|
||||||
# c4_name = ddr3_name + '.genblk5[1].OSERDESE2_train'
|
|
||||||
|
|
||||||
c1=get_cell(c1_name)
|
|
||||||
# c2=get_cell(c2_name)
|
|
||||||
c3=get_cell(c3_name)
|
|
||||||
# c4=get_cell(c4_name)
|
|
||||||
|
|
||||||
print('show_bels: ' + c1_name + ": ", c1.bel)
|
|
||||||
# print('show_bels: ' + c2_name + ": ", c2.bel)
|
|
||||||
print('show_bels: ' + c3_name + ": ", c3.bel)
|
|
||||||
# print('show_bels: ' + c4_name + ": ", c4.bel)
|
|
||||||
|
|
@ -1,113 +0,0 @@
|
||||||
/*
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
@ -1,142 +1,207 @@
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright (c) 2014-2017 Alex Forencich
|
//
|
||||||
|
// Module: uart_rx
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
//
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
// Notes:
|
||||||
in the Software without restriction, including without limitation the rights
|
// - UART reciever module.
|
||||||
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
|
|
||||||
|
|
||||||
|
module uart_rx(
|
||||||
|
input wire clk , // Top level system clock input.
|
||||||
|
input wire resetn , // Asynchronous active low reset.
|
||||||
|
input wire uart_rxd , // UART Recieve pin.
|
||||||
|
input wire uart_rx_en , // Recieve enable
|
||||||
|
output wire uart_rx_break, // Did we get a BREAK message?
|
||||||
|
output wire uart_rx_valid, // Valid data recieved and available.
|
||||||
|
output reg [PAYLOAD_BITS-1:0] uart_rx_data // The recieved data.
|
||||||
);
|
);
|
||||||
|
|
||||||
reg [DATA_WIDTH-1:0] m_axis_tdata_reg = 0;
|
// ---------------------------------------------------------------------------
|
||||||
reg m_axis_tvalid_reg = 0;
|
// External parameters.
|
||||||
|
//
|
||||||
|
|
||||||
reg rxd_reg = 1;
|
//
|
||||||
|
// Input bit rate of the UART line.
|
||||||
|
parameter BIT_RATE = 9600; // bits / sec
|
||||||
|
localparam BIT_P = 1_000_000_000 * 1/BIT_RATE; // nanoseconds
|
||||||
|
|
||||||
reg busy_reg = 0;
|
//
|
||||||
reg overrun_error_reg = 0;
|
// Clock frequency in hertz.
|
||||||
reg frame_error_reg = 0;
|
parameter CLK_HZ = 50_000_000;
|
||||||
|
localparam CLK_P = 1_000_000_000 * 1/CLK_HZ; // nanoseconds
|
||||||
|
|
||||||
reg [DATA_WIDTH-1:0] data_reg = 0;
|
//
|
||||||
reg [18:0] prescale_reg = 0;
|
// Number of data bits recieved per UART packet.
|
||||||
reg [3:0] bit_cnt = 0;
|
parameter PAYLOAD_BITS = 8;
|
||||||
|
|
||||||
assign m_axis_tdata = m_axis_tdata_reg;
|
//
|
||||||
assign m_axis_tvalid = m_axis_tvalid_reg;
|
// Number of stop bits indicating the end of a packet.
|
||||||
|
parameter STOP_BITS = 1;
|
||||||
|
|
||||||
assign busy = busy_reg;
|
// --------------------------------------------------------------------------
|
||||||
assign overrun_error = overrun_error_reg;
|
// Internal parameters.
|
||||||
assign frame_error = frame_error_reg;
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// Number of clock cycles per uart bit.
|
||||||
|
localparam CYCLES_PER_BIT = BIT_P / CLK_P;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Size of the registers which store sample counts and bit durations.
|
||||||
|
localparam COUNT_REG_LEN = 1+$clog2(CYCLES_PER_BIT);
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// Internal registers.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// Internally latched value of the uart_rxd line. Helps break long timing
|
||||||
|
// paths from input pins into the logic.
|
||||||
|
reg rxd_reg;
|
||||||
|
reg rxd_reg_0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Storage for the recieved serial data.
|
||||||
|
reg [PAYLOAD_BITS-1:0] recieved_data;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Counter for the number of cycles over a packet bit.
|
||||||
|
reg [COUNT_REG_LEN-1:0] cycle_counter;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Counter for the number of recieved bits of the packet.
|
||||||
|
reg [3:0] bit_counter;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Sample of the UART input line whenever we are in the middle of a bit frame.
|
||||||
|
reg bit_sample;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Current and next states of the internal FSM.
|
||||||
|
reg [2:0] fsm_state;
|
||||||
|
reg [2:0] n_fsm_state;
|
||||||
|
|
||||||
|
localparam FSM_IDLE = 0;
|
||||||
|
localparam FSM_START= 1;
|
||||||
|
localparam FSM_RECV = 2;
|
||||||
|
localparam FSM_STOP = 3;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Output assignment
|
||||||
|
//
|
||||||
|
|
||||||
|
assign uart_rx_break = uart_rx_valid && ~|recieved_data;
|
||||||
|
assign uart_rx_valid = fsm_state == FSM_STOP && n_fsm_state == FSM_IDLE;
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
if (rst) begin
|
if(!resetn) begin
|
||||||
m_axis_tdata_reg <= 0;
|
uart_rx_data <= {PAYLOAD_BITS{1'b0}};
|
||||||
m_axis_tvalid_reg <= 0;
|
end else if (fsm_state == FSM_STOP) begin
|
||||||
rxd_reg <= 1;
|
uart_rx_data <= recieved_data;
|
||||||
prescale_reg <= 0;
|
end
|
||||||
bit_cnt <= 0;
|
end
|
||||||
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;
|
// FSM next state selection.
|
||||||
end
|
//
|
||||||
|
|
||||||
if (prescale_reg > 0) begin
|
wire next_bit = cycle_counter == CYCLES_PER_BIT ||
|
||||||
prescale_reg <= prescale_reg - 1;
|
fsm_state == FSM_STOP &&
|
||||||
end else if (bit_cnt > 0) begin
|
cycle_counter == CYCLES_PER_BIT/2;
|
||||||
if (bit_cnt > DATA_WIDTH+1) begin
|
wire payload_done = bit_counter == PAYLOAD_BITS ;
|
||||||
if (!rxd_reg) begin
|
|
||||||
bit_cnt <= bit_cnt - 1;
|
//
|
||||||
prescale_reg <= (prescale << 3)-1;
|
// Handle picking the next state.
|
||||||
end else begin
|
always @(*) begin : p_n_fsm_state
|
||||||
bit_cnt <= 0;
|
case(fsm_state)
|
||||||
prescale_reg <= 0;
|
FSM_IDLE : n_fsm_state = rxd_reg ? FSM_IDLE : FSM_START;
|
||||||
end
|
FSM_START: n_fsm_state = next_bit ? FSM_RECV : FSM_START;
|
||||||
end else if (bit_cnt > 1) begin
|
FSM_RECV : n_fsm_state = payload_done ? FSM_STOP : FSM_RECV ;
|
||||||
bit_cnt <= bit_cnt - 1;
|
FSM_STOP : n_fsm_state = next_bit ? FSM_IDLE : FSM_STOP ;
|
||||||
prescale_reg <= (prescale << 3)-1;
|
default : n_fsm_state = FSM_IDLE;
|
||||||
data_reg <= {rxd_reg, data_reg[DATA_WIDTH-1:1]};
|
endcase
|
||||||
end else if (bit_cnt == 1) begin
|
end
|
||||||
bit_cnt <= bit_cnt - 1;
|
|
||||||
if (rxd_reg) begin
|
// ---------------------------------------------------------------------------
|
||||||
m_axis_tdata_reg <= data_reg;
|
// Internal register setting and re-setting.
|
||||||
m_axis_tvalid_reg <= 1;
|
//
|
||||||
overrun_error_reg <= m_axis_tvalid_reg;
|
|
||||||
end else begin
|
//
|
||||||
frame_error_reg <= 1;
|
// Handle updates to the recieved data register.
|
||||||
end
|
integer i = 0;
|
||||||
end
|
always @(posedge clk) begin : p_recieved_data
|
||||||
end else begin
|
if(!resetn) begin
|
||||||
busy_reg <= 0;
|
recieved_data <= {PAYLOAD_BITS{1'b0}};
|
||||||
if (!rxd_reg) begin
|
end else if(fsm_state == FSM_IDLE ) begin
|
||||||
prescale_reg <= (prescale << 2)-2;
|
recieved_data <= {PAYLOAD_BITS{1'b0}};
|
||||||
bit_cnt <= DATA_WIDTH+2;
|
end else if(fsm_state == FSM_RECV && next_bit ) begin
|
||||||
data_reg <= 0;
|
recieved_data[PAYLOAD_BITS-1] <= bit_sample;
|
||||||
busy_reg <= 1;
|
for ( i = PAYLOAD_BITS-2; i >= 0; i = i - 1) begin
|
||||||
end
|
recieved_data[i] <= recieved_data[i+1];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
//
|
||||||
|
// Increments the bit counter when recieving.
|
||||||
|
always @(posedge clk) begin : p_bit_counter
|
||||||
|
if(!resetn) begin
|
||||||
|
bit_counter <= 4'b0;
|
||||||
|
end else if(fsm_state != FSM_RECV) begin
|
||||||
|
bit_counter <= {COUNT_REG_LEN{1'b0}};
|
||||||
|
end else if(fsm_state == FSM_RECV && next_bit) begin
|
||||||
|
bit_counter <= bit_counter + 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
//
|
||||||
|
// Sample the recieved bit when in the middle of a bit frame.
|
||||||
|
always @(posedge clk) begin : p_bit_sample
|
||||||
|
if(!resetn) begin
|
||||||
|
bit_sample <= 1'b0;
|
||||||
|
end else if (cycle_counter == CYCLES_PER_BIT/2) begin
|
||||||
|
bit_sample <= rxd_reg;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Increments the cycle counter when recieving.
|
||||||
|
always @(posedge clk) begin : p_cycle_counter
|
||||||
|
if(!resetn) begin
|
||||||
|
cycle_counter <= {COUNT_REG_LEN{1'b0}};
|
||||||
|
end else if(next_bit) begin
|
||||||
|
cycle_counter <= {COUNT_REG_LEN{1'b0}};
|
||||||
|
end else if(fsm_state == FSM_START ||
|
||||||
|
fsm_state == FSM_RECV ||
|
||||||
|
fsm_state == FSM_STOP ) begin
|
||||||
|
cycle_counter <= cycle_counter + 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Progresses the next FSM state.
|
||||||
|
always @(posedge clk) begin : p_fsm_state
|
||||||
|
if(!resetn) begin
|
||||||
|
fsm_state <= FSM_IDLE;
|
||||||
|
end else begin
|
||||||
|
fsm_state <= n_fsm_state;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Responsible for updating the internal value of the rxd_reg.
|
||||||
|
always @(posedge clk) begin : p_rxd_reg
|
||||||
|
if(!resetn) begin
|
||||||
|
rxd_reg <= 1'b1;
|
||||||
|
rxd_reg_0 <= 1'b1;
|
||||||
|
end else if(uart_rx_en) begin
|
||||||
|
rxd_reg <= rxd_reg_0;
|
||||||
|
rxd_reg_0 <= uart_rxd;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
|
|
@ -1,115 +1,187 @@
|
||||||
/*
|
|
||||||
|
|
||||||
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
|
// Module: uart_tx
|
||||||
in the Software without restriction, including without limitation the rights
|
//
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
// Notes:
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
// - UART transmitter module.
|
||||||
furnished to do so, subject to the following conditions:
|
//
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
module uart_tx(
|
||||||
all copies or substantial portions of the Software.
|
input wire clk , // Top level system clock input.
|
||||||
|
input wire resetn , // Asynchronous active low reset.
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
output wire uart_txd , // UART transmit pin.
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
output wire uart_tx_busy, // Module busy sending previous item.
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
input wire uart_tx_en , // Send the data on uart_tx_data
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
input wire [PAYLOAD_BITS-1:0] uart_tx_data // The data to be sent
|
||||||
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;
|
// ---------------------------------------------------------------------------
|
||||||
|
// External parameters.
|
||||||
|
//
|
||||||
|
|
||||||
reg txd_reg = 1;
|
//
|
||||||
|
// Input bit rate of the UART line.
|
||||||
|
parameter BIT_RATE = 9600; // bits / sec
|
||||||
|
localparam BIT_P = 1_000_000_000 * 1/BIT_RATE; // nanoseconds
|
||||||
|
|
||||||
reg busy_reg = 0;
|
//
|
||||||
|
// Clock frequency in hertz.
|
||||||
|
parameter CLK_HZ = 50_000_000;
|
||||||
|
localparam CLK_P = 1_000_000_000 * 1/CLK_HZ; // nanoseconds
|
||||||
|
|
||||||
reg [DATA_WIDTH:0] data_reg = 0;
|
//
|
||||||
reg [18:0] prescale_reg = 0;
|
// Number of data bits recieved per UART packet.
|
||||||
reg [3:0] bit_cnt = 0;
|
parameter PAYLOAD_BITS = 8;
|
||||||
|
|
||||||
assign s_axis_tready = s_axis_tready_reg;
|
//
|
||||||
assign txd = txd_reg;
|
// Number of stop bits indicating the end of a packet.
|
||||||
|
parameter STOP_BITS = 1;
|
||||||
|
|
||||||
assign busy = busy_reg;
|
// ---------------------------------------------------------------------------
|
||||||
|
// Internal parameters.
|
||||||
|
//
|
||||||
|
|
||||||
always @(posedge clk) begin
|
//
|
||||||
if (rst) begin
|
// Number of clock cycles per uart bit.
|
||||||
s_axis_tready_reg <= 0;
|
localparam CYCLES_PER_BIT = BIT_P / CLK_P;
|
||||||
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;
|
// Size of the registers which store sample counts and bit durations.
|
||||||
prescale_reg <= (prescale << 3)-1;
|
localparam COUNT_REG_LEN = 1+$clog2(CYCLES_PER_BIT);
|
||||||
bit_cnt <= DATA_WIDTH+1;
|
|
||||||
data_reg <= {1'b1, s_axis_tdata};
|
// ---------------------------------------------------------------------------
|
||||||
txd_reg <= 0;
|
// Internal registers.
|
||||||
busy_reg <= 1;
|
//
|
||||||
end
|
|
||||||
end else begin
|
//
|
||||||
if (bit_cnt > 1) begin
|
// Internally latched value of the uart_txd line. Helps break long timing
|
||||||
bit_cnt <= bit_cnt - 1;
|
// paths from the logic to the output pins.
|
||||||
prescale_reg <= (prescale << 3)-1;
|
reg txd_reg;
|
||||||
{data_reg, txd_reg} <= {1'b0, data_reg};
|
|
||||||
end else if (bit_cnt == 1) begin
|
//
|
||||||
bit_cnt <= bit_cnt - 1;
|
// Storage for the serial data to be sent.
|
||||||
prescale_reg <= (prescale << 3);
|
reg [PAYLOAD_BITS-1:0] data_to_send;
|
||||||
txd_reg <= 1;
|
|
||||||
end
|
//
|
||||||
|
// Counter for the number of cycles over a packet bit.
|
||||||
|
reg [COUNT_REG_LEN-1:0] cycle_counter;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Counter for the number of sent bits of the packet.
|
||||||
|
reg [3:0] bit_counter;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Current and next states of the internal FSM.
|
||||||
|
reg [2:0] fsm_state;
|
||||||
|
reg [2:0] n_fsm_state;
|
||||||
|
|
||||||
|
localparam FSM_IDLE = 0;
|
||||||
|
localparam FSM_START= 1;
|
||||||
|
localparam FSM_SEND = 2;
|
||||||
|
localparam FSM_STOP = 3;
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// FSM next state selection.
|
||||||
|
//
|
||||||
|
|
||||||
|
assign uart_tx_busy = fsm_state != FSM_IDLE;
|
||||||
|
assign uart_txd = txd_reg;
|
||||||
|
|
||||||
|
wire next_bit = cycle_counter == CYCLES_PER_BIT;
|
||||||
|
wire payload_done = bit_counter == PAYLOAD_BITS ;
|
||||||
|
wire stop_done = bit_counter == STOP_BITS && fsm_state == FSM_STOP;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Handle picking the next state.
|
||||||
|
always @(*) begin : p_n_fsm_state
|
||||||
|
case(fsm_state)
|
||||||
|
FSM_IDLE : n_fsm_state = uart_tx_en ? FSM_START: FSM_IDLE ;
|
||||||
|
FSM_START: n_fsm_state = next_bit ? FSM_SEND : FSM_START;
|
||||||
|
FSM_SEND : n_fsm_state = payload_done ? FSM_STOP : FSM_SEND ;
|
||||||
|
FSM_STOP : n_fsm_state = stop_done ? FSM_IDLE : FSM_STOP ;
|
||||||
|
default : n_fsm_state = FSM_IDLE;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Internal register setting and re-setting.
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// Handle updates to the sent data register.
|
||||||
|
integer i = 0;
|
||||||
|
always @(posedge clk) begin : p_data_to_send
|
||||||
|
if(!resetn) begin
|
||||||
|
data_to_send <= {PAYLOAD_BITS{1'b0}};
|
||||||
|
end else if(fsm_state == FSM_IDLE && uart_tx_en) begin
|
||||||
|
data_to_send <= uart_tx_data;
|
||||||
|
end else if(fsm_state == FSM_SEND && next_bit ) begin
|
||||||
|
for ( i = PAYLOAD_BITS-2; i >= 0; i = i - 1) begin
|
||||||
|
data_to_send[i] <= data_to_send[i+1];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Increments the bit counter each time a new bit frame is sent.
|
||||||
|
always @(posedge clk) begin : p_bit_counter
|
||||||
|
if(!resetn) begin
|
||||||
|
bit_counter <= 4'b0;
|
||||||
|
end else if(fsm_state != FSM_SEND && fsm_state != FSM_STOP) begin
|
||||||
|
bit_counter <= {COUNT_REG_LEN{1'b0}};
|
||||||
|
end else if(fsm_state == FSM_SEND && n_fsm_state == FSM_STOP) begin
|
||||||
|
bit_counter <= {COUNT_REG_LEN{1'b0}};
|
||||||
|
end else if(fsm_state == FSM_STOP&& next_bit) begin
|
||||||
|
bit_counter <= bit_counter + 1'b1;
|
||||||
|
end else if(fsm_state == FSM_SEND && next_bit) begin
|
||||||
|
bit_counter <= bit_counter + 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Increments the cycle counter when sending.
|
||||||
|
always @(posedge clk) begin : p_cycle_counter
|
||||||
|
if(!resetn) begin
|
||||||
|
cycle_counter <= {COUNT_REG_LEN{1'b0}};
|
||||||
|
end else if(next_bit) begin
|
||||||
|
cycle_counter <= {COUNT_REG_LEN{1'b0}};
|
||||||
|
end else if(fsm_state == FSM_START ||
|
||||||
|
fsm_state == FSM_SEND ||
|
||||||
|
fsm_state == FSM_STOP ) begin
|
||||||
|
cycle_counter <= cycle_counter + 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Progresses the next FSM state.
|
||||||
|
always @(posedge clk) begin : p_fsm_state
|
||||||
|
if(!resetn) begin
|
||||||
|
fsm_state <= FSM_IDLE;
|
||||||
|
end else begin
|
||||||
|
fsm_state <= n_fsm_state;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Responsible for updating the internal value of the txd_reg.
|
||||||
|
always @(posedge clk) begin : p_txd_reg
|
||||||
|
if(!resetn) begin
|
||||||
|
txd_reg <= 1'b1;
|
||||||
|
end else if(fsm_state == FSM_IDLE) begin
|
||||||
|
txd_reg <= 1'b1;
|
||||||
|
end else if(fsm_state == FSM_START) begin
|
||||||
|
txd_reg <= 1'b0;
|
||||||
|
end else if(fsm_state == FSM_SEND) begin
|
||||||
|
txd_reg <= data_to_send[0];
|
||||||
|
end else if(fsm_state == FSM_STOP) begin
|
||||||
|
txd_reg <= 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue