diff --git a/xc7/additional_examples/button_debouncer/README.rst b/xc7/additional_examples/button_debouncer/README.rst index 25aff19..08d88dd 100644 --- a/xc7/additional_examples/button_debouncer/README.rst +++ b/xc7/additional_examples/button_debouncer/README.rst @@ -6,7 +6,7 @@ on the basys3 board. The number of presses will be given on the seven segment di by pressing the up button on the board. To build the design first navigate to the additional examples directory: .. code-block:: bash - :name: example-debouncer-basys3 + :name: additional-examples cd additional_examples diff --git a/xc7/additional_examples/immages/registers.gif b/xc7/additional_examples/immages/registers.gif new file mode 100644 index 0000000..aea35ac Binary files /dev/null and b/xc7/additional_examples/immages/registers.gif differ diff --git a/xc7/additional_examples/registers_example/Makefile b/xc7/additional_examples/registers_example/Makefile new file mode 100644 index 0000000..dc81c9c --- /dev/null +++ b/xc7/additional_examples/registers_example/Makefile @@ -0,0 +1,41 @@ +mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) +current_dir := $(patsubst %/,%,$(dir $(mkfile_path))) +TOP := top +SOURCES := ${current_dir}/*.sv +SOURCES += ${current_dir}/*.v +DEVICE := xc7a50t_test +BITSTREAM_DEVICE := artix7 +BUILDDIR:=build + + PARTNAME := xc7a35tcpg236-1 + BOARD_BUILDDIR := ${BUILDDIR}/basys3 + XDC:=${current_dir}/*.xdc + +.DELETE_ON_ERROR: + + +all: ${BOARD_BUILDDIR}/${TOP}.bit + +${BOARD_BUILDDIR}: + mkdir -p ${BOARD_BUILDDIR} + +${BOARD_BUILDDIR}/${TOP}.eblif: | ${BOARD_BUILDDIR} + cd ${BOARD_BUILDDIR} && symbiflow_synth -t ${TOP} -v ${SOURCES} -d ${BITSTREAM_DEVICE} -p ${PARTNAME} -x ${XDC} 2>&1 > /dev/null + +${BOARD_BUILDDIR}/${TOP}.net: ${BOARD_BUILDDIR}/${TOP}.eblif + cd ${BOARD_BUILDDIR} && symbiflow_pack -e ${TOP}.eblif -d ${DEVICE} 2>&1 > /dev/null + +${BOARD_BUILDDIR}/${TOP}.place: ${BOARD_BUILDDIR}/${TOP}.net + cd ${BOARD_BUILDDIR} && symbiflow_place -e ${TOP}.eblif -d ${DEVICE} -n ${TOP}.net -P ${PARTNAME} 2>&1 > /dev/null + +${BOARD_BUILDDIR}/${TOP}.route: ${BOARD_BUILDDIR}/${TOP}.place + cd ${BOARD_BUILDDIR} && symbiflow_route -e ${TOP}.eblif -d ${DEVICE} 2>&1 > /dev/null + +${BOARD_BUILDDIR}/${TOP}.fasm: ${BOARD_BUILDDIR}/${TOP}.route + cd ${BOARD_BUILDDIR} && symbiflow_write_fasm -e ${TOP}.eblif -d ${DEVICE} + +${BOARD_BUILDDIR}/${TOP}.bit: ${BOARD_BUILDDIR}/${TOP}.fasm + cd ${BOARD_BUILDDIR} && symbiflow_write_bitstream -d ${BITSTREAM_DEVICE} -f ${TOP}.fasm -p ${PARTNAME} -b ${TOP}.bit + +clean: + rm -rf ${BUILDDIR} diff --git a/xc7/additional_examples/registers_example/README.rst b/xc7/additional_examples/registers_example/README.rst new file mode 100644 index 0000000..e1b82a0 --- /dev/null +++ b/xc7/additional_examples/registers_example/README.rst @@ -0,0 +1,45 @@ +Registers +~~~~~~~~~~ + +This module implements eight 4-bit registers, one +3:8 decoder, and two 8:1 multiplexors to create a triple ported +register file. This example also demonstrates symbiflows ability to parse a combination of verilog and system verilog files together as well as testing a few primitives. + + +.. code-block:: bash + :name: additional-example + + cd additional_examples + +Then run make to compile the design: + +.. code-block:: bash + :name: example-registers-basys3 + + make -C uart_receiver + + +At completion, the bitstream is located in the build directory: + +.. code-block:: bash + + cd uart_receiver/build/arty_35 + +Now, you can upload the design with: + +.. code-block:: bash + + openocd -f ${INSTALL_DIR}/${FPGA_FAM}/conda/envs/${FPGA_FAM}/share/openocd/scripts/board/digilent_arty.cfg -c "init; pld load 0 top.bit; exit" + +Once the bitstream has been downloaded to the board, you can load different registers by toggling different switches on and off. Switches 0-4 on the basys define the binary value +to be written to the register speciefied by switches 4-6. Switches 4-6 also act as the first read address on the triple ported register file. +switches 6-9 define the second read address. The center button on the board is the write +enable signal. The value being read is displayed on the basys3's seven segment display in hex. +You can chose to display the first or second btnl and the values of reg 1 and 2 together, btnu-reg2+reg1, btnd-reg1-reg2. The value +you chose will be output o the first segment of the basys board. + +.. image:: ../images/registers.gif + :align: center + :width: 50% + + diff --git a/xc7/additional_examples/registers_example/basys3.xdc b/xc7/additional_examples/registers_example/basys3.xdc new file mode 100644 index 0000000..a8e580d --- /dev/null +++ b/xc7/additional_examples/registers_example/basys3.xdc @@ -0,0 +1,37 @@ +# Clock + set_property -dict { PACKAGE_PIN W5 IOSTANDARD LVCMOS33 } [get_ports { clk }]; + create_clock -period 10.00 [get_ports {clk}]; + +# Buttons + set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { btnc }]; + set_property -dict { PACKAGE_PIN T18 IOSTANDARD LVCMOS33 } [get_ports { btnu }]; + set_property -dict { PACKAGE_PIN W19 IOSTANDARD LVCMOS33 } [get_ports { btnl }]; + set_property -dict { PACKAGE_PIN T17 IOSTANDARD LVCMOS33 } [get_ports { btnr }]; + set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { btnd }]; + +# Switches + set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { sw[0] }]; + set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { sw[1] }]; + set_property -dict { PACKAGE_PIN W16 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; + set_property -dict { PACKAGE_PIN W17 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; + set_property -dict { PACKAGE_PIN W15 IOSTANDARD LVCMOS33 } [get_ports { sw[4] }]; + set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { sw[5] }]; + set_property -dict { PACKAGE_PIN W14 IOSTANDARD LVCMOS33 } [get_ports { sw[6] }]; + set_property -dict { PACKAGE_PIN W13 IOSTANDARD LVCMOS33 } [get_ports { sw[7] }]; + set_property -dict { PACKAGE_PIN V2 IOSTANDARD LVCMOS33 } [get_ports { sw[8] }]; + set_property -dict { PACKAGE_PIN T3 IOSTANDARD LVCMOS33 } [get_ports { sw[9] }]; + + +# Seven-Segment Display + set_property -dict { PACKAGE_PIN W7 IOSTANDARD LVCMOS33 } [get_ports { segment[0] }]; + set_property -dict { PACKAGE_PIN W6 IOSTANDARD LVCMOS33 } [get_ports { segment[1] }]; + set_property -dict { PACKAGE_PIN U8 IOSTANDARD LVCMOS33 } [get_ports { segment[2] }]; + set_property -dict { PACKAGE_PIN V8 IOSTANDARD LVCMOS33 } [get_ports { segment[3] }]; + set_property -dict { PACKAGE_PIN U5 IOSTANDARD LVCMOS33 } [get_ports { segment[4] }]; + set_property -dict { PACKAGE_PIN V5 IOSTANDARD LVCMOS33 } [get_ports { segment[5] }]; + set_property -dict { PACKAGE_PIN U7 IOSTANDARD LVCMOS33 } [get_ports { segment[6] }]; + set_property -dict { PACKAGE_PIN V7 IOSTANDARD LVCMOS33 } [get_ports { segment[7] }]; + set_property -dict { PACKAGE_PIN U2 IOSTANDARD LVCMOS33 } [get_ports { anode[0] }]; + set_property -dict { PACKAGE_PIN U4 IOSTANDARD LVCMOS33 } [get_ports { anode[1] }]; + set_property -dict { PACKAGE_PIN V4 IOSTANDARD LVCMOS33 } [get_ports { anode[2] }]; + set_property -dict { PACKAGE_PIN W4 IOSTANDARD LVCMOS33 } [get_ports { anode[3] }]; \ No newline at end of file diff --git a/xc7/additional_examples/registers_example/register4.sv b/xc7/additional_examples/registers_example/register4.sv new file mode 100644 index 0000000..3d8d9d4 --- /dev/null +++ b/xc7/additional_examples/registers_example/register4.sv @@ -0,0 +1,10 @@ +module register4( +input logic clk, we, +input logic[3:0] datain, +output logic[3:0] dataout +); +FDCE my_ff1 (.Q(dataout[0]), .C(clk), .CE(we), .CLR(1'b0), .D(datain[0])); +FDCE my_ff2 (.Q(dataout[1]), .C(clk), .CE(we), .CLR(1'b0), .D(datain[1])); +FDCE my_ff3 (.Q(dataout[2]), .C(clk), .CE(we), .CLR(1'b0), .D(datain[2])); +FDCE my_ff4 (.Q(dataout[3]), .C(clk), .CE(we), .CLR(1'b0), .D(datain[3])); +endmodule \ No newline at end of file diff --git a/xc7/additional_examples/registers_example/register_file_8x4.sv b/xc7/additional_examples/registers_example/register_file_8x4.sv new file mode 100644 index 0000000..7bad39d --- /dev/null +++ b/xc7/additional_examples/registers_example/register_file_8x4.sv @@ -0,0 +1,33 @@ +module register_file_8x4( +input logic clk, we, +input logic[3:0] datain, +input logic[2:0] waddr, raddr1, raddr2, +output logic[3:0] dataout1, dataout2 +); +logic[7:0] RWS; +logic[3:0] reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7; +assign RWS = {8{we}} & (8'b00000001 << waddr); +register4 R1 (.clk(clk), .we(RWS[0]), .datain(datain), .dataout(reg0)); +register4 R2 (.clk(clk), .we(RWS[1]), .datain(datain), .dataout(reg1)); +register4 R3 (.clk(clk), .we(RWS[2]), .datain(datain), .dataout(reg2)); +register4 R4 (.clk(clk), .we(RWS[3]), .datain(datain), .dataout(reg3)); +register4 R5 (.clk(clk), .we(RWS[4]), .datain(datain), .dataout(reg4)); +register4 R6 (.clk(clk), .we(RWS[5]), .datain(datain), .dataout(reg5)); +register4 R7 (.clk(clk), .we(RWS[6]), .datain(datain), .dataout(reg6)); +register4 R8 (.clk(clk), .we(RWS[7]), .datain(datain), .dataout(reg7)); +assign dataout1 = (raddr1 == 0)?reg0: +(raddr1 == 1)?reg1: +(raddr1 == 2)?reg2: +(raddr1 == 3)?reg3:(raddr1 == 4)?reg4: +(raddr1 == 5)?reg5: +(raddr1 == 6)?reg6: +reg7; +assign dataout2= (raddr2 == 0)?reg0: +(raddr2 == 1)?reg1: +(raddr2 == 2)?reg2: +(raddr2 == 3)?reg3: +(raddr2 == 4)?reg4: +(raddr2 == 5)?reg5: +(raddr2 == 6)?reg6: +reg7; +endmodule \ No newline at end of file diff --git a/xc7/additional_examples/registers_example/register_top.sv b/xc7/additional_examples/registers_example/register_top.sv new file mode 100644 index 0000000..7a8d0f8 --- /dev/null +++ b/xc7/additional_examples/registers_example/register_top.sv @@ -0,0 +1,18 @@ +module top( +input logic clk, btnc, btnr, btnu, btnd, btnl, +input logic[9:0] sw, +output logic[7:0] segment, +output logic[3:0] anode +); +logic[3:0] dataout1, dataout2, outdata; +register_file_8x4 R0(.clk(clk), .we(btnc), .datain(sw[3:0]), .waddr(sw[6:4]), +.raddr1(sw[6:4]), .raddr2(sw[9:7]), .dataout1(dataout1), .dataout2(dataout2)); +assign outdata = (btnr == 1) ? dataout2: +(btnu == 1)? dataout2 + dataout1: +(btnd == 1)? dataout1 - dataout2: +(btnl == 1)? dataout1&dataout2: +dataout1; +seven_segment S0(.data(outdata), .segment(segment[6:0])); +assign anode = 4'b1110; +assign segment[7] = 1; +endmodule \ No newline at end of file diff --git a/xc7/additional_examples/registers_example/seven_segment.v b/xc7/additional_examples/registers_example/seven_segment.v new file mode 100644 index 0000000..84b4bb0 --- /dev/null +++ b/xc7/additional_examples/registers_example/seven_segment.v @@ -0,0 +1,39 @@ +module seven_segment( + input [3:0] data, + output [6:0] segment + ); + wire [3:0] CA; + wire [4:0] CB; + wire [3:0] ND; + + not(ND[3], data[3]); + not(ND[2], data[2]); + not(ND[1], data[1]); + not(ND[0], data[0]); + + and(CA[0], ND[3], ND[2], ND[1], data[0]); + and(CA[1], ND[3], data[2], ND[1], ND[0]); + and(CA[2], data[3], ND[2], data[1], data[0]); + and(CA[3], data[3], data[2], ND[1], data[0]); + + or(segment[0], CA[0], CA[1], CA[2], CA[3]); + + and(CB[0], ND[3], data[2], ND[1], data[0]); + and(CB[1], data[2], data[1], ND[0]); + and(CB[2], data[3], data[2], ND[0]); + and(CB[3], data[3], ND[2], data[1], data[0]); + and(CB[4], data[3], data[2], data[1]); + + or(segment[1], CB[0], CB[1], CB[2], CB[3], CB[4]); + + LUT4 #(16'hd004) seg0(.O(segment[2]), .I0(data[0]), .I1(data[1]), .I2(data[2]), .I3(data[3])); + LUT4 #(16'h8492) seg1(.O(segment[3]), .I0(data[0]), .I1(data[1]), .I2(data[2]), .I3(data[3])); + LUT4 #(16'h02ba) seg2(.O(segment[4]), .I0(data[0]), .I1(data[1]), .I2(data[2]), .I3(data[3])); + LUT4 #(16'h208e) seg3(.O(segment[5]), .I0(data[0]), .I1(data[1]), .I2(data[2]), .I3(data[3])); + LUT4 #(16'h1083) seg4(.O(segment[6]), .I0(data[0]), .I1(data[1]), .I2(data[2]), .I3(data[3])); + + + +endmodule + + diff --git a/xc7/additional_examples/uart_transmitter/tx_top.sv b/xc7/additional_examples/uart_transmitter/tx_top.sv index fafd568..8b9ae77 100644 --- a/xc7/additional_examples/uart_transmitter/tx_top.sv +++ b/xc7/additional_examples/uart_transmitter/tx_top.sv @@ -2,7 +2,7 @@ module top( input wire logic clk, - input wire logic btnu, //reset button + input wire logic btnu, input wire logic [7:0] sw, input wire logic btnc, output logic [3:0] anode, diff --git a/xc7/additional_examples/uart_tx-rx/Makefile b/xc7/additional_examples/uart_tx-rx/Makefile new file mode 100644 index 0000000..5c90ee4 --- /dev/null +++ b/xc7/additional_examples/uart_tx-rx/Makefile @@ -0,0 +1,63 @@ +mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) +current_dir := $(patsubst %/,%,$(dir $(mkfile_path))) +TOP := top +SYSTEM_VERILOG := ${current_dir}/*.sv +DEVICE := xc7a50t_test +BITSTREAM_DEVICE := artix7 +BUILDDIR:=build + +ifeq ($(TARGET),arty_35) + PARTNAME := xc7a35tcsg324-1 + BOARD_BUILDDIR := ${BUILDDIR}/arty_35 +else ifeq ($(TARGET),arty_100) + PARTNAME:= xc7a100tcsg324-1 + DEVICE:= xc7a100t_test + BOARD_BUILDDIR := ${BUILDDIR}/arty_100 +else ifeq ($(TARGET),nexys4ddr) + PARTNAME:= xc7a100tcsg324-1 + DEVICE:= xc7a100t_test + BOARD_BUILDDIR := ${BUILDDIR}/nexys4ddr +else ifeq ($(TARGET),zybo) + PARTNAME:= xc7z010clg400-1 + DEVICE:= xc7z010_test + BITSTREAM_DEVICE:= zynq7 + BOARD_BUILDDIR := ${BUILDDIR}/zybo +else ifeq ($(TARGET),nexys_video) + PARTNAME:= xc7a200tsbg484-1 + DEVICE:= xc7a200t_test + BOARD_BUILDDIR := ${BUILDDIR}/nexys_video +else + PARTNAME:= xc7a35tcpg236-1 + BOARD_BUILDDIR := ${BUILDDIR}/basys3 +endif + + XDC:=${current_dir}/*.xdc + +.DELETE_ON_ERROR: + + +all: ${BOARD_BUILDDIR}/${TOP}.bit + +${BOARD_BUILDDIR}: + mkdir -p ${BOARD_BUILDDIR} + +${BOARD_BUILDDIR}/${TOP}.eblif: | ${BOARD_BUILDDIR} + cd ${BOARD_BUILDDIR} && symbiflow_synth -t ${TOP} -v ${SYSTEM_VERILOG} -d ${BITSTREAM_DEVICE} -p ${PARTNAME} -x ${XDC} 2>&1 > /dev/null + +${BOARD_BUILDDIR}/${TOP}.net: ${BOARD_BUILDDIR}/${TOP}.eblif + cd ${BOARD_BUILDDIR} && symbiflow_pack -e ${TOP}.eblif -d ${DEVICE} 2>&1 > /dev/null + +${BOARD_BUILDDIR}/${TOP}.place: ${BOARD_BUILDDIR}/${TOP}.net + cd ${BOARD_BUILDDIR} && symbiflow_place -e ${TOP}.eblif -d ${DEVICE} -n ${TOP}.net -P ${PARTNAME} 2>&1 > /dev/null + +${BOARD_BUILDDIR}/${TOP}.route: ${BOARD_BUILDDIR}/${TOP}.place + cd ${BOARD_BUILDDIR} && symbiflow_route -e ${TOP}.eblif -d ${DEVICE} 2>&1 > /dev/null + +${BOARD_BUILDDIR}/${TOP}.fasm: ${BOARD_BUILDDIR}/${TOP}.route + cd ${BOARD_BUILDDIR} && symbiflow_write_fasm -e ${TOP}.eblif -d ${DEVICE} + +${BOARD_BUILDDIR}/${TOP}.bit: ${BOARD_BUILDDIR}/${TOP}.fasm + cd ${BOARD_BUILDDIR} && symbiflow_write_bitstream -d ${BITSTREAM_DEVICE} -f ${TOP}.fasm -p ${PARTNAME} -b ${TOP}.bit + +clean: + rm -rf ${BUILDDIR} diff --git a/xc7/additional_examples/uart_tx-rx/README.rst b/xc7/additional_examples/uart_tx-rx/README.rst new file mode 100644 index 0000000..691fbdf --- /dev/null +++ b/xc7/additional_examples/uart_tx-rx/README.rst @@ -0,0 +1,43 @@ +UART Receiver +~~~~~~~~~~~~~~~~~~ + +This UART receiver on the basys3 board. + +.. code-block:: bash + :name: additional-example + + cd additional_examples + +Then run make to compile the design: + +.. code-block:: bash + :name: example-uarttx-basys3 + + make -C uart_receiver + + +At completion, the bitstream is located in the build directory: + +.. code-block:: bash + + cd uart_receiver/build/arty_35 + +Now, you can upload the design with: + +.. code-block:: bash + + openocd -f ${INSTALL_DIR}/${FPGA_FAM}/conda/envs/${FPGA_FAM}/share/openocd/scripts/board/digilent_arty.cfg -c "init; pld load 0 top.bit; exit" + +Once the code has been downloaded to the board open a Putty terminal and choose the serial connection line for your board. +Also set the baud rate to 19200, data bits to 8, stop bits to 1, the parity to ODD, and the flow control to NONE. You can +change these properties by looking under the serial settings on the left hand side. + +After configuring Putty, open a session and type some characters. The ASKII values of the keys you press will be displayed +on the basys3 board in hex. The LEDs are used to notify of any reception errors. You can also transmit ASKII characters to putty +by following the same procedures as in the uart_receiver example. The following is an example of the receiver: + +.. image:: ../images/uart_tx.gif + :align: center + :width: 50% + + diff --git a/xc7/additional_examples/uart_tx-rx/SevenSegmentControl.sv b/xc7/additional_examples/uart_tx-rx/SevenSegmentControl.sv new file mode 100644 index 0000000..4fdc193 --- /dev/null +++ b/xc7/additional_examples/uart_tx-rx/SevenSegmentControl.sv @@ -0,0 +1,67 @@ +`default_nettype none +module SevenSegmentControl( + input wire logic clk, + input wire logic reset, + input wire logic [15:0] dataIn, + input wire logic [3:0] digitDisplay, + input wire logic [3:0] digitPoint, + output logic [3:0] anode, + output logic [7:0] segment + ); + + parameter integer COUNT_BITS = 17; + + logic [COUNT_BITS-1:0] count_val; + logic [1:0] anode_select; + logic [3:0] cur_anode; + logic [3:0] cur_data_in; + + always_ff @(posedge clk) begin + if (reset) + count_val <= 0; + else + count_val <= count_val + 1; + end + + assign anode_select = count_val[COUNT_BITS-1:COUNT_BITS-2]; + + assign cur_anode = + (anode_select == 2'b00) ? 4'b1110 : + (anode_select == 2'b01) ? 4'b1101 : + (anode_select == 2'b10) ? 4'b1011 : + 4'b0111; + + assign anode = cur_anode | (~digitDisplay); + + assign cur_data_in = + (anode_select == 2'b00) ? dataIn[3:0] : + (anode_select == 2'b01) ? dataIn[7:4] : + (anode_select == 2'b10) ? dataIn[11:8] : + dataIn[15:12] ; + + assign segment[7] = + (anode_select == 2'b00) ? ~digitPoint[0] : + (anode_select == 2'b01) ? ~digitPoint[1] : + (anode_select == 2'b10) ? ~digitPoint[2] : + ~digitPoint[3] ; + + assign segment[6:0] = + (cur_data_in == 0) ? 7'b1000000 : + (cur_data_in == 1) ? 7'b1111001 : + (cur_data_in == 2) ? 7'b0100100 : + (cur_data_in == 3) ? 7'b0110000 : + (cur_data_in == 4) ? 7'b0011001 : + (cur_data_in == 5) ? 7'b0010010 : + (cur_data_in == 6) ? 7'b0000010 : + (cur_data_in == 7) ? 7'b1111000 : + (cur_data_in == 8) ? 7'b0000000 : + (cur_data_in == 9) ? 7'b0010000 : + (cur_data_in == 10) ? 7'b0001000 : + (cur_data_in == 11) ? 7'b0000011 : + (cur_data_in == 12) ? 7'b1000110 : + (cur_data_in == 13) ? 7'b0100001 : + (cur_data_in == 14) ? 7'b0000110 : + 7'b0001110; + + +endmodule \ No newline at end of file diff --git a/xc7/additional_examples/uart_tx-rx/rx.sv b/xc7/additional_examples/uart_tx-rx/rx.sv new file mode 100644 index 0000000..b537c22 --- /dev/null +++ b/xc7/additional_examples/uart_tx-rx/rx.sv @@ -0,0 +1,107 @@ + +module rx #(parameter CLK_FREQUENCY = 100000000, BAUD_RATE = +19200)( +input wire logic clk, odd, rx_in, +output logic[7:0] dout, +output logic data_strobe, error, busy +); +logic ResetTimer, EnableTimer, LastCycle, HalfCycle, LastBit, NextBit = 0, +ResetCounter, +Shift, Stop, Parity; +localparam ONE_BIT_CNT = CLK_FREQUENCY / BAUD_RATE; +localparam HALF_CNT = ONE_BIT_CNT / 2; +function integer clogb2; +input [31:0] value; +begin +value = value - 1; +for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) begin +value = value >> 1; +end +end +endfunction + +localparam NUM_BITS_FULL_CNT = clogb2(ONE_BIT_CNT); +logic[NUM_BITS_FULL_CNT - 1:0] count = 0; + +always_ff@ (posedge clk) +begin +if(ResetTimer || count == ONE_BIT_CNT) +count <= 0; +else if(EnableTimer) +count <= count + 1; +end +assign LastCycle = (count == ONE_BIT_CNT) ? 1'b1:1'b0; + +assign HalfCycle = (count == HALF_CNT) ? 1'b1:1'b0; + +assign error = ~(((^dout)^odd)==Parity)||(~Stop); +logic[3:0] countBit = 0; +always_ff @(posedge clk) +begin +if(NextBit) +countBit <= countBit + 1; +else if(ResetCounter || LastBit) +countBit <= 0; +end +assign LastBit = (countBit == 4'b1011) ? 1'b1:1'b0; + +logic[9:0] shift = 10'b1111111111; +always_ff @(posedge clk) +begin +if(Shift) +shift <= {rx_in, shift[9:1]}; +end +assign Stop = shift[9];assign Parity = shift[8]; +assign dout = shift[7:0]; + +typedef enum {IDLE, HALF, FULL, LOAD} stateType; +stateType ns, cs; +always_comb +begin +ns = cs; +Shift = 0; +busy = 1; +EnableTimer = 0; +ResetTimer = 0; +ResetCounter = 0; +data_strobe = 0; +NextBit = 0; +case(cs) +IDLE: +begin +ResetTimer = 1;ResetCounter = 1; +busy = 0; +if(!rx_in) +ns = HALF; +end +HALF: +begin +EnableTimer = 1; +if(!HalfCycle && rx_in) +ns = IDLE; +else if(HalfCycle) +ns = LOAD; +end +LOAD: +begin +busy = 1; +Shift = 1; +NextBit = 1;ResetTimer = 1; +ns = FULL; +end +FULL: +begin +busy = 1; +EnableTimer = 1; +if(LastCycle) +ns = LOAD; +else if(LastBit) +begin +data_strobe = 1; +ns = IDLE; +end +end +endcase +end +always_ff @(posedge clk) +cs <= ns;endmodule \ No newline at end of file diff --git a/xc7/additional_examples/uart_tx-rx/tx.sv b/xc7/additional_examples/uart_tx-rx/tx.sv new file mode 100644 index 0000000..06d68c6 --- /dev/null +++ b/xc7/additional_examples/uart_tx-rx/tx.sv @@ -0,0 +1,108 @@ +module tx #(parameter CLK_FREQUENCY = 100000000, BAUD_RATE = 19200)( +input wire logic clk, send, odd, +input wire logic[7:0] din, +output logic busy, tx_out, +output logic[4:0] state +); +logic EnableTimer, ResetTimer, LastCycle, LastBit, NextBit, ResetCounter, +Shift, Load, ParityBit; +localparam MAX_COUNT = CLK_FREQUENCY / BAUD_RATE; +function integer clogb2; +input [31:0] value; +begin +value = value - 1; +for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) begin +value = value >> 1; +end +end +endfunction +localparam NUM_BITS = clogb2(MAX_COUNT); +logic[NUM_BITS - 1:0] count = 0; + +always_ff@ (posedge clk) +begin +if(ResetTimer || count == MAX_COUNT) +count <= 0; +else if(EnableTimer) +count <= count + 1; +end +assign LastCycle = (count == MAX_COUNT) ? 1'b1:1'b0; + +assign ParityBit = ((^din)^odd); + +logic[3:0] countBit = 0; +always_ff @(posedge clk) +begin +if(NextBit) +countBit <= countBit + 1; +else if(ResetCounter == 1'b1 || countBit == 4'd10) +countBit <= 0; +end +assign LastBit = (countBit == 4'b1001) ? 1'b1:1'b0; + +logic[9:0] shift = 10'b1111111111; +always_ff @(posedge clk) +begin +if(Load) +shift <= {ParityBit, din, 1'b0}; +else if(Shift) +shift <= {1'b1, shift[9:1]}; +end +assign tx_out = shift[0]; + +localparam Id = 5'b00001; +localparam Lo = 5'b00010; +localparam Co = 5'b00100; +localparam Sh = 5'b01000; +localparam Wa = 5'b10000; + +logic [4:0] ns, cs=Id; +assign state = cs; +always_comb +begin +ns = cs; +Load = 0; +busy = 0; +ResetCounter = 0; +ResetTimer = 0; +Shift = 0; +ResetTimer = 0; +NextBit = 0; +EnableTimer =0; +case(cs) +Id: +if(send) +ns = Lo; +Lo: +begin +Load = 1; +busy = 1; +ResetCounter = 1; +ResetTimer = 1; +ns = Co; +end +Co: +begin +busy = 1; +EnableTimer = 1; +if(LastCycle) +ns = Sh; +end +Sh:begin +Shift = 1; +ResetTimer = 1; +NextBit = 1; +busy = 1; +if(~LastBit) +ns = Co; +else +ns = Wa; +end +Wa: +if(~send) +ns = Id; +endcase +end +always_ff @(posedge clk) +cs <= ns; +endmodule \ No newline at end of file diff --git a/xc7/additional_examples/uart_tx-rx/uart.xdc b/xc7/additional_examples/uart_tx-rx/uart.xdc new file mode 100644 index 0000000..10ac361 --- /dev/null +++ b/xc7/additional_examples/uart_tx-rx/uart.xdc @@ -0,0 +1,45 @@ +# Clock + set_property -dict { PACKAGE_PIN W5 IOSTANDARD LVCMOS33 } [get_ports { clk }]; + create_clock -period 10.0 [get_ports {clk}] + +# Buttons + set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { btnc }]; + +# Switches + set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { sw[0] }]; + set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { sw[1] }]; + set_property -dict { PACKAGE_PIN W16 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; + set_property -dict { PACKAGE_PIN W17 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; + set_property -dict { PACKAGE_PIN W15 IOSTANDARD LVCMOS33 } [get_ports { sw[4] }]; + set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { sw[5] }]; + set_property -dict { PACKAGE_PIN W14 IOSTANDARD LVCMOS33 } [get_ports { sw[6] }]; + set_property -dict { PACKAGE_PIN W13 IOSTANDARD LVCMOS33 } [get_ports { sw[7] }]; + + +# LEDs + set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { debugLED[0] }]; + set_property -dict { PACKAGE_PIN E19 IOSTANDARD LVCMOS33 } [get_ports { debugLED[1] }]; + set_property -dict { PACKAGE_PIN U19 IOSTANDARD LVCMOS33 } [get_ports { debugLED[2] }]; + set_property -dict { PACKAGE_PIN V19 IOSTANDARD LVCMOS33 } [get_ports { debugLED[3] }]; + set_property -dict { PACKAGE_PIN W18 IOSTANDARD LVCMOS33 } [get_ports { debugLED[4] }]; + + +# Seven Segment Display + set_property -dict { PACKAGE_PIN W7 IOSTANDARD LVCMOS33 } [get_ports { segment[0] }]; + set_property -dict { PACKAGE_PIN W6 IOSTANDARD LVCMOS33 } [get_ports { segment[1] }]; + set_property -dict { PACKAGE_PIN U8 IOSTANDARD LVCMOS33 } [get_ports { segment[2] }]; + set_property -dict { PACKAGE_PIN V8 IOSTANDARD LVCMOS33 } [get_ports { segment[3] }]; + set_property -dict { PACKAGE_PIN U5 IOSTANDARD LVCMOS33 } [get_ports { segment[4] }]; + set_property -dict { PACKAGE_PIN V5 IOSTANDARD LVCMOS33 } [get_ports { segment[5] }]; + set_property -dict { PACKAGE_PIN U7 IOSTANDARD LVCMOS33 } [get_ports { segment[6] }]; + set_property -dict { PACKAGE_PIN V7 IOSTANDARD LVCMOS33 } [get_ports { segment[7] }]; + set_property -dict { PACKAGE_PIN U2 IOSTANDARD LVCMOS33 } [get_ports { anode[0] }]; + set_property -dict { PACKAGE_PIN U4 IOSTANDARD LVCMOS33 } [get_ports { anode[1] }]; + set_property -dict { PACKAGE_PIN V4 IOSTANDARD LVCMOS33 } [get_ports { anode[2] }]; + set_property -dict { PACKAGE_PIN W4 IOSTANDARD LVCMOS33 } [get_ports { anode[3] }]; + +# UART + set_property -dict { PACKAGE_PIN B18 IOSTANDARD LVCMOS33 } [get_ports { rx_in }]; + set_property -dict { PACKAGE_PIN A18 IOSTANDARD LVCMOS33 } [get_ports { tx_out }]; + set_property -dict { PACKAGE_PIN J1 IOSTANDARD LVCMOS33 } [get_ports { tx_debug }]; + diff --git a/xc7/additional_examples/uart_tx-rx/uart_top.sv b/xc7/additional_examples/uart_tx-rx/uart_top.sv new file mode 100644 index 0000000..7194aa3 --- /dev/null +++ b/xc7/additional_examples/uart_tx-rx/uart_top.sv @@ -0,0 +1,31 @@ +module top( +input wire logic clk, btnc, rx_in, +input wire logic[7:0] sw, +output logic[7:0] segment, +output logic[3:0] anode, +output logic tx_debug, tx_out, +output logic[4:0] debugLED +); +logic rx_error, rx_debug; + +logic busyByBy, tx_mid, send, btn[1:0]; +tx T0(.tx_out(tx_mid), .odd(1'b0), .busy(busyByBy), .din(sw), .clk(clk), .send(btn[1]), +.state(debugLED)); +assign tx_out = tx_mid; +assign tx_debug = tx_mid; + +logic busyByByRx, dataGoner, btnRx[1:0]; +logic[7:0] rx_data; +rx R0(.rx_in(rx_in), .odd(1'b0), .busy(busyByByRx), .data_strobe(dataGoner), +.dout(rx_data), .error(rx_error), .clk(clk)); +assign rx_debug = rx_in; + +SevenSegmentControl S1(.dataIn({rx_data[7:0], +sw[7:0]}), .reset(0), .digitDisplay(4'hf), .digitPoint(4'h4), .anode(anode), +.segment(segment), .clk(clk)); +always_ff @(posedge clk) +btn[0] <= btnc; +always_ff @(posedge clk) +btn[1] <= btn[0]; + +endmodule diff --git a/xc7/pulse_width_led/README.rst b/xc7/pulse_width_led/README.rst index 5a414c4..a3a2d0a 100644 --- a/xc7/pulse_width_led/README.rst +++ b/xc7/pulse_width_led/README.rst @@ -6,7 +6,7 @@ demonstrates a PWM that drives the RGB leds on the board. To build this example commands: .. code-block:: bash - :name: example-watch-basys3 + :name: example-pulse-arty-35t make -C pulse_width_led