Embedded Systems Spring 2024
HW 6 VGA

Name: Mason Brady
Email: mrbrady1@fortlewis.edu

HW 6

Introduction: This homework is an introduction to VGA ports

Materials: gvim, vivado

1) Counter With Buttons

This is pretty straightforward just modified my code from the quiz to hold a state so you have to release the button.

module SSDisp(input clk, input btnU, input btnD, output reg [6:0] g_to_a, output reg [3:0] an);
    reg state = 1'b1;
    parameter cntmax = 32'd20000000;
    reg [31:0] cnt;
    reg[3:0] digit = 4'd0;
    parameter digitMax = 4'd9;
    always @(posedge clk) begin
        an = 4'b1110;
        if(btnU && state == 1'b1) begin
            if(digit > digitMax) digit <= 4'b0;
            else if(cnt > cntmax) begin
                digit = digit + 1;
                state <= 1'b0;
                cnt <= 32'b0;
            end else cnt <= cnt + 1;
        end
        else if (btnD) digit = 4'b0;
        else state <= 1'b1;
        case(digit)
            0:g_to_a = 7'b1000000;
            1:g_to_a = 7'b1111001;
            2:g_to_a = 7'b0100100;
            3:g_to_a = 7'b0110000;
            4:g_to_a = 7'b0011001;
            5:g_to_a = 7'b0010010;
            6:g_to_a = 7'b0000010;
            7:g_to_a = 7'b1111000;
            8:g_to_a = 7'b0000000;
            9:g_to_a = 7'b0011000;
            default: g_to_a = 7'b0000000;
        endcase
    end
endmodule

module debounce(sw, clk, sw_out);
    reg prev_switch;
    input clk;
    input sw;
    output reg sw_out;
    initial begin
        prev_switch = sw;
    end
    always @ (posedge clk)
        if(sw != prev_switch)begin
            prev_switch = sw;
            sw_out = 1'b0;
        end
       else sw_out = sw;
endmodule

module hw7(input [15:0] sw, output [3:0] an, output [6:0] seg, input btnU, input btnD, input clk);
    wire btnDebounce;
    debounce d0(.clk(clk), .sw(btnU), .sw_out(btnDebounce));
    SSDisp UUT(.clk(clk), .btnU(btnDebounce), .btnD(btnD), .g_to_a(seg [6:0]), .an(an [3:0]));
endmodule

2) Repeat the UART transmitter in Section 2 to show letters/symbols in the serial monitor. (25 points)



module UART_tx_ctrl (ready, uart_tx, clk, send, data);
    input send, clk;
    input [7:0] data;
    output ready, uart_tx;
    parameter baud = 9600;
    parameter bit_index_max = 10;
    localparam [31:0] baud_timer = 100000000/baud;
    localparam RDY = 2'b00, LOAD_BIT = 1'b01, SEND_BIT = 2'b10;
    reg [1:0] state = RDY;
    reg [31:0] timer = 0;
    reg [9:0] txData;
    reg [3:0] bitIndex;
    reg txBit = 1'b1;
   
    always @(posedge clk)
        case(state)
            RDY: begin
                bitIndex <= 1'b0;
                timer <= 14'b0;
                txBit <= 1'b1;
                if(send == 1'b1) begin
                    txData <= {1'b1, data, 1'b0};
                    state <= LOAD_BIT;
                end
            end
            LOAD_BIT: begin
                if(timer == baud_timer) begin
                    timer <= 14'b0;
                    state <= SEND_BIT;
                    txBit <= txData[bitIndex];
                    bitIndex <= bitIndex + 1'b1;
                end else timer <= timer + 1'b1;
            end
            SEND_BIT: begin
                if(bitIndex == bit_index_max) state <= RDY;
                else state <= LOAD_BIT;
            end
            default: state <= RDY;
        endcase
       
        assign uart_tx = txBit;
        assign ready = (state == RDY);
endmodule

module debounce(sw, clk, sw_out);
    reg prev_switch;
    input clk;
    input sw;
    output reg sw_out;
    initial begin
        prev_switch = sw;
    end
    always @ (posedge clk)
        if(sw != prev_switch)begin
            prev_switch = sw;
            sw_out = 1'b0;
        end
       else sw_out = sw;
endmodule

module UART_tx_top(clk, btnC, RsTx);
    input clk, btnC;
    output RsTx;
    reg [7:0] initStr = 8'h41;
    localparam btnWait = 2'b00, btnSend = 2'b01, btnSendWait = 2'b10;
    reg btnC_prev;
    reg [7:0] uartData;
    reg [1:0] state = btnWait;
    wire btnC_clr;
    wire uartSend;
    wire uartRdy;
   
    debounce debounce_UT(.clk(clk), .sw(btnC), .sw_out(btnC_clr));
    UART_tx_ctrl #(19200) uart(.clk(clk), .send(uartSend), .data(uartData), .uart_tx(RsTx), .ready(uartRdy));
    always @(posedge clk) begin
        btnC_prev <= btnC_clr;
        case(state)
            btnWait: if(btnC_clr == 1'b1 && btnC_prev == 0) state <= btnSend;
            btnSend: begin
                uartData <= initStr;
                initStr <= initStr + 1'b1;
                state <= btnWait;
            end
            btnSendWait: if(uartRdy) state <= btnWait;
            default: state <= btnWait;
        endcase
    end
    assign uartSend = (state == btnSend);
endmodule


3) Repeat the work in Section 3. & Show the numbers you typed in the serial monitor on one seven segment display unit (less than 10). (25 points)

I
combined these two sections because it seemed silly not to do them together (Means I only have to verify a few binary numbers and then can just look at the SSD). I reused the SSDecode module I wrote before and added the code given to get this result:


module UART_rx_ctrl (clk, rx, data, parity, ready, error);
    input clk, rx;
    output reg [7:0] data;
    output reg parity;
    output reg ready = 0;
    output reg error = 0;
    parameter baud = 9600;
    localparam RDY = 3'b000, START = 3'b001, RECEIVE = 3'b010, WAIT = 3'b011, CHECK = 3'b100;
    reg [2:0] state = RDY;
    localparam [31:0] baud_timer = 100000000/baud;
    reg [31:0] timer = 32'b0;
    reg [3:0] bitIndex = 3'b0;
    reg [8:0] rxdata;
   
    always @ (posedge clk)
        case (state)
            RDY: if (rx == 1'b0) begin
                state <= START;
                bitIndex <= 3'b0;
            end
            START: if (timer == baud_timer / 2) begin
                state <= WAIT;
                timer <= 14'b0;
                error <= 1'b0;
                ready <= 1'b0;
            end else timer <= timer + 1'b1;
            WAIT: if (timer == baud_timer) begin
                timer <= 14'b0;
                if (ready) state <= RDY;
                else state <= RECEIVE;
            end else timer <= timer + 1'b1;
           
            RECEIVE: begin
                rxdata[bitIndex] <= rx;
                bitIndex <= bitIndex + 1'b1;
                if (bitIndex == 4'd8) state <= CHECK;
                else state <= WAIT;
            end
            CHECK: if(^rxdata [7:0] == rxdata [8]) begin
                ready <= 1'b1;
                state <= RDY;
                data <= rxdata [7:0];
                parity <= rxdata[8];
            end else begin
                ready <= 1'b1;
                data [7:0] <= 8'bx;
                error <= 1'b1;
                state <= RDY;   
            end
        endcase
endmodule

module SSDecode (input clk, input [3:0] x, output reg [6:0] g_to_a, output reg [3:0] an);
    reg[3:0] digit;
    parameter cntmax = 10'd1023;
    reg state = 1'b0;
    reg [9:0] cnt;
    always @(posedge clk)
    begin
        cnt <= cnt + 1'b1;
        digit <= x[3:0];
        if(cnt >= cntmax) begin
            an <= 4'b1110;
            case(digit)
                0:g_to_a <= 7'b1000000;
                1:g_to_a <= 7'b1111001;
                2:g_to_a <= 7'b0100100;
                3:g_to_a <= 7'b0110000;
                4:g_to_a <= 7'b0011001;
                5:g_to_a <= 7'b0010010;
                6:g_to_a <= 7'b0000010;
                7:g_to_a <= 7'b1111000;
                8:g_to_a <= 7'b0000000;
                9:g_to_a <= 7'b0011000;
            endcase
            cnt <= 10'b0;
        end
    end
endmodule

module UART_rx_top(clk, RsRx, led, seg, an);
    input clk, RsRx;
    output [6:0] seg;
    output [3:0] an;
    output reg [15:0] led = 0;
    localparam RX_RDY = 2'b00, RX_WAIT = 2'b01, RX_DATARDY = 2'b10;
    reg [1:0] state = RX_RDY;
    wire data_ready;
    wire [7:0] out;
    wire parity;
    wire error;
    UART_rx_ctrl #(19200) RX(.clk(clk), .rx(RsRx), .data(out), .parity(parity), .ready(data_ready), .error(error));
    SSDecode UUT(.clk(clk), .x(out [3:0]), .g_to_a(seg), .an(an));
    always @ (posedge clk) case (state)
        RX_RDY: if(!data_ready) state <= RX_WAIT;
        RX_WAIT: if (data_ready) state <= RX_DATARDY;
        RX_DATARDY: begin
            led [9:0] <= {error, parity, out};
            led [15:10] <= led[15:10] + 1'b1;
            state <= RX_RDY;
        end
    endcase
endmodule

which resulted in the following functionality.



Discussion:
Easy peasy. The Tera Term download is exceptionally sketchy and the link on the website didn't work. I ended up downloading off of github because it seemed the safest with the published source code but at leats one of the other links MUST have been a virus (they were bad).