Embedded Systems Spring 2024
HW 10 SPI Light Sensor

Name: Mason Brady
Email: mrbrady1@fortlewis.edu

HW 10

Introduction: This homework is an introduction to SPI using a Light Sensor and 7 Segment Displays

Materials: gvim, vivado, Basys 3, Light Sensor

Methods:

Part 1)

For this I just coppied what they did in the text book and got the following code:

module SPI_leader_receiver(clk, miso, get, data, sck, ss, busy, ready);
parameter data_length = 8;
input clk;
input get;
input miso;
output reg [data_length - 1:0] data;
output reg ss = 1;
output reg sck = 0;
output reg busy = 0;
output reg ready = 0;
localparam RDY = 2'b00, RECEIVE = 2'b01, STOP = 2'b10;
reg [1:0] state = RDY;
reg [data_length - 1:0] data_temp = 0;
reg [7:0] index = 0;
reg [7:0] clkdiv = 0;
always @ (posedge clk)
    if(clkdiv == 8'd25) begin
        clkdiv <= 0;
        sck <= ~sck;
    end else clkdiv <= clkdiv + 1;

always @ (posedge sck)
    case(state)
    RDY:
        if (get) begin
            ss <= 0;
            state <= RECEIVE;
            busy <= 1;
            ready <= 0;
            data_temp <= 0;
            index <= data_length - 1;
        end
    RECEIVE: begin
        if(index == 0) state <= STOP;
        data_temp [index] <= miso;
        index <= index -1;
        end
    STOP: begin
        busy <= 0;
        ready <= 1;
        ss <= 1;
        data_temp <= 0;
        data <= data_temp;
        state <= RDY;
        end
    endcase
endmodule

module binarytoBCD(binary, thos, huns, tens, ones);
    input [11:0] binary;
    output reg[3:0] thos, huns, tens, ones;
    reg [11:0] bcd_data = 0;
    always @ (binary) begin
        bcd_data = binary;
        thos = bcd_data / 1000;
        bcd_data = bcd_data % 1000;
        huns = bcd_data / 100;
        bcd_data = bcd_data % 100;
        tens = bcd_data / 10;
        ones = bcd_data % 10;
    end
endmodule

module decoder_7seg(in1, out1);
    input [3:0] in1;
    output reg [6:0] out1;
    always @ (in1)
        case(in1)
            4'b0000 : out1 = 7'b1000000;
            4'b0001 : out1 = 7'b1111001;
            4'b0010 : out1 = 7'b0100100;
            4'b0011 : out1 = 7'b0110000;
            4'b0100 : out1 = 7'b0011001;
            4'b0101 : out1 = 7'b0010010;
            4'b0110 : out1 = 7'b0000010;
            4'b0111 : out1 = 7'b1111000;
            4'b1000 : out1 = 7'b0000000;
            4'b1001 : out1 = 7'b0010000;
            4'b1010 : out1 = 7'b0001000;
            4'b1011 : out1 = 7'b0000011;
            4'b1100 : out1 = 7'b1000110;
            4'b1101 : out1 = 7'b0100001;
            4'b1110 : out1 = 7'b0000110;
            4'b1111 : out1 = 7'b0001110;
        endcase
endmodule

module sevenseg_driver (clk, in1, in2, in3, in4, seg, an);
    input clk;
    input [3:0] in1, in2, in3, in4;
    output reg[6:0] seg;
    output reg [3:0] an;
    wire [6:0] seg1, seg2, seg3, seg4;
    reg [12:0] segclk;
    localparam LEFT = 2'b00, MIDLEFT = 2'b01, MIDRIGHT = 2'b10, RIGHT = 2'b11;
    reg [1:0] state = LEFT;
    decoder_7seg disp1 (in1, seg1);
    decoder_7seg disp2 (in2, seg2);
    decoder_7seg disp3 (in3, seg3);
    decoder_7seg disp4 (in4, seg4);
    always @ (posedge clk) segclk <= segclk + 1'b1;
    always @ (posedge segclk[2]) begin
        case (state)
            LEFT: begin
                seg <= seg1;
                an <= 4'b0111;
                state <= MIDLEFT;
            end
            MIDLEFT:begin
                seg <= seg2;
                an <= 4'b1011;
                state <= MIDRIGHT;
            end
            MIDRIGHT:begin
                seg <= seg3;
                an <= 4'b1101;
                state <= RIGHT;
            end
            RIGHT:begin
                seg <= seg4;
                an <= 4'b1110;
                state <= LEFT;
            end
        endcase
    end
endmodule

module SPI_light(input clk, sdo, output ss, sck, [15:0] led, [6:0] seg, [3:0] an);
    parameter delaytime = 500;
    localparam TRACK = 1'b0, GETIN = 1'b1;
    reg state = TRACK;
    reg [31:0] delay = 2000 * delaytime;
    reg [15:0] lightdata;
    wire [3:0] thos, huns, tens, ones;
    wire [15:0] data;
    wire busy;
    wire ready;
    reg get = 0;
   
    always @ (posedge sck)
        case(state)
            TRACK:
                if(delay == 0) begin
                    get <= 1;
                    state <= GETIN;
                end else delay <= delay - 1'b1;
            GETIN:
                if(ready == 1) begin
                    get <= 0;
                    lightdata <= data;
                    delay <= 2000 * delaytime;
                    state <= TRACK;
                end
        endcase
    assign led = {thos, huns, tens, ones};
    SPI_leader_receiver #(16) spi(clk, sdo, get, data, sck, ss, busy, ready);
    binarytoBCD bcd({4'b0000, lightdata[12:5]}, thos, huns, tens, ones);
    sevenseg_driver segdriver(clk, thos, huns, tens, ones, seg, an);
endmodule


This was pretty straight forward. I think the caps in my Basys 3 were struggling to discharge fast enough resulting in the ghosting because it looks fine in steady state but struggles when updating rapidly. I tried to play around with the delays but it didn't help much.



Discussion:
Easy peasy. Just copied the text books example and had to change some parameters in the constraints. I think it would've been better to change the values in the code to what the constraints file uses so I don't mess myself up later but I'm not sure.