diff --git a/Lab 2 Report.pdf b/Lab 2 Report.pdf new file mode 100644 index 0000000..26b8ed8 Binary files /dev/null and b/Lab 2 Report.pdf differ diff --git a/datamemory.v b/datamemory.v index 0d82131..02225af 100644 --- a/datamemory.v +++ b/datamemory.v @@ -17,7 +17,7 @@ module datamemory input [addresswidth-1:0] address, input writeEnable, input [width-1:0] dataIn -) +); reg [width-1:0] memory [depth-1:0]; diff --git a/fsm.t.v b/fsm.t.v new file mode 100644 index 0000000..7263c0c --- /dev/null +++ b/fsm.t.v @@ -0,0 +1,27 @@ +//Finite state machine test bench +`timescale 1 ns / 1 ps +`include "fsm.v" +module testFSM(); + + reg lsb; + reg chipSelect; + reg clk; + wire sr_we; + wire addr_we; + wire dm_we; + wire[4:0] currentState; + + fsm dut(lsb, chipSelect, clk, sr_we, addr_we, dm_we, currentState); + initial clk=0; + always #10 clk=!clk; + + initial begin + $dumpfile("fsm.vcd"); + $dumpvars(0, testFSM); + lsb=1;chipSelect=1; #350 + $display("testing chip select"); + chipSelect=0; #10 + + lsb=0;chipSelect=1; + end +endmodule diff --git a/fsm.v b/fsm.v new file mode 100644 index 0000000..1a55703 --- /dev/null +++ b/fsm.v @@ -0,0 +1,196 @@ +//Finite state machine +module fsm +( +input lsb, //Least significant bit +input chipSelect, //Chip select +input clk, //Serial clock +output reg sr_we, +output reg addr_we, +output reg dm_we, +output reg[4:0] currentState +); + parameter beg = 0; + parameter loadA6 = 1; + parameter loadA5 = 2; + parameter loadA4 = 3; + parameter loadA3 = 4; + parameter loadA2 = 5; + parameter loadA1 = 6; + parameter loadA0 = 7; + parameter loadRW = 8; + + parameter readD7 = 9; + parameter readD6 = 10; + parameter readD5 = 11; + parameter readD4 = 12; + parameter readD3 = 13; + parameter readD2 = 14; + parameter readD1 = 15; + parameter readD0 = 16; + + parameter writeD7 = 17; + parameter writeD6 = 18; + parameter writeD5 = 19; + parameter writeD4 = 20; + parameter writeD3 = 21; + parameter writeD2 = 22; + parameter writeD1 = 23; + parameter writeD0 = 24; + + initial currentState = beg; + always @(posedge clk) begin + if (!chipSelect && currentState == beg) begin + currentState <= loadA6; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == loadA6) begin + currentState <= loadA5; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == loadA5) begin + currentState <= loadA4; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == loadA4) begin + currentState <= loadA3; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == loadA3) begin + currentState <= loadA2; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == loadA2) begin + currentState <= loadA1; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == loadA1) begin + currentState <= loadA0; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == loadA0) begin + currentState <= loadRW; + sr_we <= 0; + addr_we <= 1; + dm_we <= 0; + end + else if (!chipSelect && currentState == loadRW) begin + if (lsb == 1) begin + currentState <= readD7; + sr_we <= 1; + addr_we <= 0; + dm_we <= 0; + end + else begin + currentState <= writeD7; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + end + else if (!chipSelect && currentState == readD7) begin + currentState <= readD6; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == readD6) begin + currentState <= readD5; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == readD5) begin + currentState <= readD4; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == readD4) begin + currentState <= readD3; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == readD3) begin + currentState <= readD2; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == readD2) begin + currentState <= readD1; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == readD1) begin + currentState <= readD0; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == writeD7) begin + currentState <= writeD6; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == writeD6) begin + currentState <= writeD5; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == writeD5) begin + currentState <= writeD4; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == writeD4) begin + currentState <= writeD3; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == writeD3) begin + currentState <= writeD2; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == writeD2) begin + currentState <= writeD1; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + else if (!chipSelect && currentState == writeD1) begin + currentState <= writeD0; + sr_we <= 0; + addr_we <= 0; + dm_we <= 1; + end + else begin + //Reset to begin state + currentState <= beg; + sr_we <= 0; + addr_we <= 0; + dm_we <= 0; + end + end +endmodule diff --git a/inputconditioner.t.v b/inputconditioner.t.v index 2814163..0104103 100644 --- a/inputconditioner.t.v +++ b/inputconditioner.t.v @@ -1,6 +1,8 @@ //------------------------------------------------------------------------ // Input Conditioner test bench //------------------------------------------------------------------------ +`timescale 1 ns / 1 ps +`include "inputconditioner.v" module testConditioner(); @@ -11,10 +13,10 @@ module testConditioner(); wire falling; inputconditioner dut(.clk(clk), - .noisysignal(pin), + .noisysignal(pin), .conditioned(conditioned), .positiveedge(rising), - .negativeedge(falling)) + .negativeedge(falling)); // Generate clock (50MHz) @@ -22,8 +24,44 @@ module testConditioner(); always #10 clk=!clk; // 50MHz Clock initial begin + $dumpfile("inputconditioner.vcd"); + $dumpvars(0,testConditioner); // Your Test Code // Be sure to test each of the three conditioner functions: // Synchronization, Debouncing, Edge Detection + + $display("clk noisysignal | conditioned posedge negedge | expected output"); + // initial condition + pin=0; #5 //Offsetting signal + pin=1; #100 + + // test input synchronization + pin=0; #100 + + // test debouncing & edge detection + pin=0; #100 + pin=1; #20 + pin=0; #30 + pin=1; #150 + + pin=0; #10 + pin=1; #20 + pin=0; #100 + + // test maximum glitch + pin=1; #50 + pin=0; #30 + pin=1; #60 + pin=0; #30 + pin=1; #70 + pin=0; #30 + pin=1; #80 + pin=0; #30 + pin=1; #150 + pin=0; + + //Take a look at sync.png file for the waveform and confirm the proper behaviors + + end endmodule diff --git a/inputconditioner.v b/inputconditioner.v index 736a866..d41ed9a 100644 --- a/inputconditioner.v +++ b/inputconditioner.v @@ -22,12 +22,21 @@ output reg negativeedge // 1 clk pulse at falling edge of conditioned reg synchronizer1 = 0; always @(posedge clk ) begin - if(conditioned == synchronizer1) + if(conditioned == synchronizer1) begin counter <= 0; + positiveedge <= 0; + negativeedge <= 0; + end else begin if( counter == waittime) begin counter <= 0; conditioned <= synchronizer1; + if (synchronizer1 == 1) begin + positiveedge <= 1; + end + else begin + negativeedge <= 1; + end end else counter <= counter+1; diff --git a/midpoint.md b/midpoint.md new file mode 100644 index 0000000..b8c78d6 --- /dev/null +++ b/midpoint.md @@ -0,0 +1,11 @@ +Midpoint + +Since there are 4 leds on FPGA board, I put a MUX to control led by Switch 2. If Switch 2 is off, 0-3 bits are shown on LED. Otherwise, 4-7 bits are shown on LED. + +I tested the followings. +1. Check the initial value(xA5 = 10100101). When Switch 2 is off, LED 0 and 2 are on and LED 1 and 3 are off.(x5 = 0101) When Switch 2 is on, LED 1 and 3 are on and LED 0 and 2 are off.(xA = 1010) +2. When I turn Switch 1 on, if Switch 0 is off the bits shift up by one and 0 is loaded to the LSB(Least Significant Bit). +3. Otherwise, if Switch 1 is on, then 1 is loaded to the LSB. +4. If I click Button 0, the value is reseted to the initial value. + +The test video is [here](https://drive.google.com/open?id=0BwRWdLa3OOtLUC1XQm1iU0lKaEU) \ No newline at end of file diff --git a/midpoint.v b/midpoint.v new file mode 100644 index 0000000..30b35a0 --- /dev/null +++ b/midpoint.v @@ -0,0 +1,65 @@ +`include "shiftregister.v" +`include "inputconditioner.v" + +// Wrapper for Lab 2 + +`timescale 1ns / 1ps + +// Two-input MUX with parameterized bit width (default: 1-bit) +module mux2 #( parameter W = 1 ) +( + input[W-1:0] in0, + input[W-1:0] in1, + input sel, + output[W-1:0] out +); + // Conditional operator - http://www.verilog.renerta.com/source/vrg00010.htm + assign out = (sel) ? in1 : in0; +endmodule + + + +// Main Lab 2 wrapper module +// Interfaces with switches, buttons, and LEDs on ZYBO board. + +module midpoint +( + input clk, + input [3:0] sw, + input [3:0] btn, + output [3:0] led +); + + wire[7:0] result; // total output + wire parallelLoad; // wire for Parallel Load of Shift Register + wire serialIn; // wire for Serial Input of Shift Register + wire clkEdge; // wire for Clk Edge of Shift Register + wire[7:0] parallelIn; // wire for Parallel Input of Shift Register + + inputconditioner conditioner1 ( + .clk(clk), .noisysignal(btn[0]), + .negativeedge(parallelLoad) + ); + + inputconditioner conditioner2 ( + .clk(clk), .noisysignal(sw[0]), + .conditioned(serialIn) + ); + + inputconditioner conditioner3 ( + .clk(clk), .noisysignal(sw[1]), + .positiveedge(clkEdge) + ); + + assign parallelIn = 8'hA5; + + shiftregister sr ( + .clk(clk), .peripheralClkEdge(clkEdge), + .parallelLoad(parallelLoad), .parallelDataIn(parallelIn), + .serialDataIn(serialIn), + .parallelDataOut(result) + ); + + mux2 #(4) output_select(.in0(result[3:0]), .in1(result[7:4]), .sel(sw[2]), .out(led)); + +endmodule \ No newline at end of file diff --git a/register.v b/register.v new file mode 100644 index 0000000..afeca39 --- /dev/null +++ b/register.v @@ -0,0 +1,31 @@ +module register +( +output reg q, +input d, +input wrenable, +input clk +); + always @(posedge clk) begin + if(wrenable) begin + q = d; + end + end +endmodule + +module addresslatch +#( + parameter width = 8 +) +( +output reg[width-1:0] q, +input[width-1:0] d, +input wrenable, +input clk +); + always @(posedge clk) begin + if(wrenable) begin + q = d; + end + end +endmodule + diff --git a/shiftregister.t.v b/shiftregister.t.v index abe5b48..b177b63 100644 --- a/shiftregister.t.v +++ b/shiftregister.t.v @@ -1,7 +1,8 @@ //------------------------------------------------------------------------ // Shift Register test bench //------------------------------------------------------------------------ - +`timescale 1 ns / 1 ps +`include "shiftregister.v" module testshiftregister(); reg clk; @@ -14,16 +15,52 @@ module testshiftregister(); // Instantiate with parameter width = 8 shiftregister #(8) dut(.clk(clk), - .peripheralClkEdge(peripheralClkEdge), - .parallelLoad(parallelLoad), - .parallelDataIn(parallelDataIn), - .serialDataIn(serialDataIn), - .parallelDataOut(parallelDataOut), - .serialDataOut(serialDataOut)); + .peripheralClkEdge(peripheralClkEdge), + .parallelLoad(parallelLoad), + .parallelDataIn(parallelDataIn), + .serialDataIn(serialDataIn), + .parallelDataOut(parallelDataOut), + .serialDataOut(serialDataOut)); + initial clk=0; + always #10 clk=!clk; + initial begin - // Your Test Code - end + // Your Test Code + $dumpfile("shiftregister.vcd"); + $dumpvars(0, testshiftregister); + + // Parallel mode Test + $display("Testing parallel mode"); + $display("ParallelDataOut | Expected Result"); + peripheralClkEdge=0;parallelLoad=1;parallelDataIn=8'b00000000;serialDataIn=1; #50 + $display("%b | %b", parallelDataOut, parallelDataIn); + + parallelLoad=0;parallelDataIn=8'b11111111;serialDataIn=0; #50 + $display("%b | 00000000", parallelDataOut); + parallelLoad=1; #50 + $display("%b | %b", parallelDataOut, parallelDataIn); + + parallelDataIn=8'b00110110;serialDataIn=0; #50 + $display("%b | %b", parallelDataOut, parallelDataIn); -endmodule + parallelLoad=0; #30 + // Serial mode Test + $display("Testing serial mode"); + $display("ParallelDataOut serialDataOut | Expected Result"); + peripheralClkEdge=1;serialDataIn = 1; #20 + $display("%b %b | 01101101 0", parallelDataOut, serialDataOut); + peripheralClkEdge=0;serialDataIn = 0; #20 + $display("%b %b | 01101101 0", parallelDataOut, serialDataOut); + + peripheralClkEdge=1; #20 + $display("%b %b | 11011010 1", parallelDataOut, serialDataOut); + peripheralClkEdge=0; #20 + + peripheralClkEdge=1;serialDataIn = 0; #20 + $display("%b %b | 10110100 1", parallelDataOut, serialDataOut); + peripheralClkEdge=0; + + end +endmodule \ No newline at end of file diff --git a/shiftregister.v b/shiftregister.v index b4ec057..b75aef6 100644 --- a/shiftregister.v +++ b/shiftregister.v @@ -19,7 +19,16 @@ output serialDataOut // Positive edge synchronized ); reg [width-1:0] shiftregistermem; + assign parallelDataOut = shiftregistermem; + assign serialDataOut = shiftregistermem[width-1]; always @(posedge clk) begin // Your Code Here + + if (parallelLoad) begin + shiftregistermem <= parallelDataIn; + end + else if (peripheralClkEdge) begin + shiftregistermem <= {shiftregistermem[width-2:0], serialDataIn}; + end end endmodule diff --git a/spimemory.t.v b/spimemory.t.v new file mode 100644 index 0000000..3cb5593 --- /dev/null +++ b/spimemory.t.v @@ -0,0 +1,92 @@ +//------------------------------------------------------------------------ +// SPI Memory test bench +//------------------------------------------------------------------------ +`timescale 1 ns / 1 ps +`include "spimemory.v" + +module testspimemory(); + + reg clk; + reg cs; + reg sclk; + reg mosi; + output miso; + reg[7:0] data; // For test + + spiMemory spi(.clk(clk), .sclk_pin(sclk), .cs_pin(cs), .miso_pin(miso), .mosi_pin(mosi)); + + + // Generate clock (50MHz) + initial clk=0; + initial sclk = 0; + always #10 clk=!clk; // 50MHz Clock + always #100 sclk=!sclk; // 10 Clock period + + initial begin + $dumpfile("spimemory.vcd"); + $dumpvars(0,testspimemory); + + $display("SPI Memory Test start"); + cs = 1; #150 + cs = 0; + + mosi=1; #1200 mosi = 0; #200 // input address: 1111110 + mosi=0; #200 //write + mosi=1; #200 mosi=0; #200; mosi=1; #200 mosi=0; #400 mosi=1; #600 // input data: 10100111 + $display("Write '10100111' to addess '1111110'"); + + cs = 1; mosi = 0; #2000 + cs = 0; + + mosi=1; #1200 mosi = 0; #200 // input address: 1111110 + mosi=1; #200 // read + mosi=0; + #400 data[7]=miso;#200 data[6]=miso;#200 data[5]=miso;#200 data[4]=miso; + #200 data[3]=miso;#200 data[2]=miso;#200 data[1]=miso;#200 data[0]=miso;// read data + $display("Input address | Output Data | Expected Result"); + $display("1111110 | %b | 10100111", data); + + cs = 1; mosi = 0; #2000 + cs = 0; + + mosi=1; #400 mosi=0; #600 mosi=1; #200 mosi=0; #200 // input address: 1100010 + mosi=0; #200 //write + mosi=0; #200 mosi=1; #200 mosi=0; #800 mosi=1; #400 // input data: 01000011 + $display("Write '01000011' to addess '1100010'"); + + cs = 1; mosi = 0; #2000 + cs = 0; + + mosi=1; #1200 mosi = 0; #200 // input address: 1111110 + mosi=1; #200 // read + mosi=0; + #400 data[7]=miso;#200 data[6]=miso;#200 data[5]=miso;#200 data[4]=miso; + #200 data[3]=miso;#200 data[2]=miso;#200 data[1]=miso;#200 data[0]=miso;// read data + $display("1111110 | %b | 10100111", data); + + cs = 1; mosi = 0; #2000 + cs = 0; + + mosi=1; #400 mosi=0; #600 mosi=1; #200 mosi=0; #200 // input address: 1100010 + mosi=1; #200 // read + mosi=0; + #400 data[7]=miso;#200 data[6]=miso;#200 data[5]=miso;#200 data[4]=miso; + #200 data[3]=miso;#200 data[2]=miso;#200 data[1]=miso;#200 data[0]=miso;// read data + $display("1100010 | %b | 01000011", data); + + cs = 1; mosi = 0; #2000 + cs = 0; + + mosi=1; #1400 // input address: 1111111 + mosi=1; #200 // read + mosi=0; + #200 data[7]=miso;#200 data[6]=miso;#200 data[5]=miso;#200 data[4]=miso; + #200 data[3]=miso;#200 data[2]=miso;#200 data[1]=miso;#200 data[0]=miso;// read data + $display("1111111 | %b | xxxxxxxx", data); + + cs = 1; + $display("End test"); + + end + +endmodule \ No newline at end of file diff --git a/spimemory.v b/spimemory.v index c6ed4f7..ec40dce 100644 --- a/spimemory.v +++ b/spimemory.v @@ -1,8 +1,17 @@ //------------------------------------------------------------------------ // SPI Memory //------------------------------------------------------------------------ +`include "register.v" +`include "shiftregister.v" +`include "inputconditioner.v" +`include "datamemory.v" +`include "fsm.v" module spiMemory +#( + parameter width = 8, + parameter addresswidth = 7 +) ( input clk, // FPGA clock input sclk_pin, // SPI clock @@ -10,8 +19,33 @@ module spiMemory output miso_pin, // SPI master in slave out input mosi_pin, // SPI master out slave in output [3:0] leds // LEDs for debugging -) +); + +wire serialin; +wire clkedge; +wire needge; +wire chip; +wire serialout; +wire[width-1:0] dataMemOut; +wire[width-1:0] shiftRegOut; +wire[width-1:0] address; +wire DM_WE; +wire ADDR_WE; +wire SR_WE; +wire miso; +inputconditioner mosi(.clk(clk), .noisysignal(mosi_pin), .conditioned(serialin)); +inputconditioner sclk(.clk(clk), .noisysignal(sclk_pin), .positiveedge(clkedge), .negativeedge(nedge)); +inputconditioner cs(.clk(clk), .noisysignal(cs_pin), .conditioned(chip)); +shiftregister shift(.clk(clk), .peripheralClkEdge(clkedge), .parallelLoad(SR_WE), + .parallelDataIn(dataMemOut), .serialDataIn(serialin), + .parallelDataOut(shiftRegOut), .serialDataOut(serialout)); +register dff(.q(miso_pin), .d(serialout), .wrenable(nedge), .clk(clk)); +datamemory memory(.clk(clk), .dataOut(dataMemOut), .address(address[addresswidth:1]), + .writeEnable(DM_WE), .dataIn(shiftRegOut)); +addresslatch latch(.q(address), .d(shiftRegOut), .wrenable(ADDR_WE), .clk(clk)); +fsm spifsm( .lsb(shiftRegOut[0]), .chipSelect(chip), .clk(sclk_pin), + .sr_we(SR_WE), .addr_we(ADDR_WE), .dm_we(DM_WE)); endmodule - + \ No newline at end of file diff --git a/sync.png b/sync.png new file mode 100644 index 0000000..9ad035d Binary files /dev/null and b/sync.png differ diff --git a/testing_parallel_load.png b/testing_parallel_load.png new file mode 100644 index 0000000..c3e92d0 Binary files /dev/null and b/testing_parallel_load.png differ diff --git a/work_plan.txt b/work_plan.txt new file mode 100644 index 0000000..f02c635 --- /dev/null +++ b/work_plan.txt @@ -0,0 +1,26 @@ +Input Conditioning (4.5 hrs) ~10/28 +- draw circuit diagram (0.5 hrs) +- complete module in inputconditioner.v (1.5 hrs) +- make test bench (1 hr) +- waveform (0.5 hrs) +- revise code (1 hr) + +Shift Register (3.5 hrs) ~10/29 +- complete module in shiftregister.v (1.5 hrs) +- make test bench (1 hr) +- revise code (1 hr) + + +Midpoint Check In (1.5 hrs) ~10/25 +- make test (0.5 hts) +- load to FPGA and test (1 hr) + + +SPI Memory (3.5 hrs) ~10/30 +- complete SPI memory (1.5 hrs) +- make test sequence (1 hrs) +- revise code (1 hrs) + +Write Report (1.5 hrs) ~11/1 + +Total 14.5 hrs