From 6a1a76db352d708c71435f293da85f73448b1acd Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Fri, 21 Jul 2023 23:01:37 -0700 Subject: [PATCH] Implement basic SPI controller --- hw/efinix_fpga/simulation/Makefile | 2 +- hw/efinix_fpga/simulation/spi_controller | 448 ++++++++++++++++++ .../simulation/spi_controller_tb.sv | 33 ++ hw/efinix_fpga/spi_controller.sv | 25 +- 4 files changed, 501 insertions(+), 7 deletions(-) create mode 100755 hw/efinix_fpga/simulation/spi_controller diff --git a/hw/efinix_fpga/simulation/Makefile b/hw/efinix_fpga/simulation/Makefile index ebaffce..c3b0f2e 100644 --- a/hw/efinix_fpga/simulation/Makefile +++ b/hw/efinix_fpga/simulation/Makefile @@ -6,7 +6,7 @@ all: $(TARGETS) timer: timer_tb.sv iverilog -g2005-sv -s sim -o $@ $@_tb.sv ../$@.sv -spi_controller: spi_controller_tb.sv +spi_controller: spi_controller_tb.sv ../spi_controller.sv iverilog -g2005-sv -s sim -o $@ $@_tb.sv ../$@.sv interrupt_controller: interrupt_controller_tb.sv diff --git a/hw/efinix_fpga/simulation/spi_controller b/hw/efinix_fpga/simulation/spi_controller new file mode 100755 index 0000000..c2ed4e5 --- /dev/null +++ b/hw/efinix_fpga/simulation/spi_controller @@ -0,0 +1,448 @@ +#! /usr/bin/vvp +:ivl_version "12.0 (stable)"; +:ivl_delay_selection "TYPICAL"; +:vpi_time_precision - 9; +:vpi_module "/usr/lib64/ivl/system.vpi"; +:vpi_module "/usr/lib64/ivl/vhdl_sys.vpi"; +:vpi_module "/usr/lib64/ivl/vhdl_textio.vpi"; +:vpi_module "/usr/lib64/ivl/v2005_math.vpi"; +:vpi_module "/usr/lib64/ivl/va_math.vpi"; +:vpi_module "/usr/lib64/ivl/v2009.vpi"; +S_0x55defa4f97e0 .scope package, "$unit" "$unit" 2 1; + .timescale 0 0; +S_0x55defa4f9970 .scope module, "sim" "sim" 3 1; + .timescale -8 -9; +v0x55defa5217a0_0 .var "_spi_device_data", 7 0; +v0x55defa5218a0_0 .var "clk_50", 0 0; +v0x55defa521960_0 .var "data", 7 0; +v0x55defa521a20_0 .var "i_addr", 1 0; +v0x55defa521ae0_0 .var "i_clk", 0 0; +v0x55defa521bd0_0 .var "i_cs", 0 0; +v0x55defa521c70_0 .var "i_data", 7 0; +v0x55defa521d10_0 .var "i_rst", 0 0; +v0x55defa521db0_0 .var "i_rwb", 0 0; +v0x55defa521e50_0 .var "i_spi_miso", 0 0; +v0x55defa521f20_0 .net "o_data", 7 0, v0x55defa520590_0; 1 drivers +v0x55defa521ff0_0 .net "o_spi_clk", 0 0, L_0x55defa4e9b80; 1 drivers +v0x55defa5220c0_0 .net "o_spi_cs", 0 0, L_0x55defa4e84f0; 1 drivers +v0x55defa522190_0 .net "o_spi_mosi", 0 0, L_0x55defa4e09c0; 1 drivers +E_0x55defa4f0300 .event edge, v0x55defa520670_0; +S_0x55defa4b6270 .scope module, "dut" "spi_controller" 3 22, 4 1 0, S_0x55defa4f9970; + .timescale 0 0; + .port_info 0 /INPUT 1 "i_clk"; + .port_info 1 /INPUT 1 "i_rst"; + .port_info 2 /INPUT 1 "i_cs"; + .port_info 3 /INPUT 1 "i_rwb"; + .port_info 4 /INPUT 2 "i_addr"; + .port_info 5 /INPUT 8 "i_data"; + .port_info 6 /OUTPUT 8 "o_data"; + .port_info 7 /OUTPUT 1 "o_spi_cs"; + .port_info 8 /OUTPUT 1 "o_spi_clk"; + .port_info 9 /OUTPUT 1 "o_spi_mosi"; + .port_info 10 /INPUT 1 "i_spi_miso"; +L_0x55defa4e84f0 .functor NOT 1, L_0x55defa522260, C4<0>, C4<0>, C4<0>; +L_0x55defa4e9b80 .functor BUFZ 1, v0x55defa520dd0_0, C4<0>, C4<0>, C4<0>; +L_0x55defa4e09c0 .functor BUFZ 1, v0x55defa520d10_0, C4<0>, C4<0>, C4<0>; +v0x55defa4e8690_0 .net *"_ivl_1", 0 0, L_0x55defa522260; 1 drivers +v0x55defa4e9d20_0 .var "active", 0 0; +v0x55defa4e0b20_0 .var "count", 2 0; +v0x55defa4e11c0_0 .net "i_addr", 1 0, v0x55defa521a20_0; 1 drivers +v0x55defa4e14a0_0 .net "i_clk", 0 0, v0x55defa521ae0_0; 1 drivers +v0x55defa4dfca0_0 .net "i_cs", 0 0, v0x55defa521bd0_0; 1 drivers +v0x55defa4e0660_0 .net "i_data", 7 0, v0x55defa521c70_0; 1 drivers +v0x55defa520350_0 .net "i_rst", 0 0, v0x55defa521d10_0; 1 drivers +v0x55defa520410_0 .net "i_rwb", 0 0, v0x55defa521db0_0; 1 drivers +v0x55defa5204d0_0 .net "i_spi_miso", 0 0, v0x55defa521e50_0; 1 drivers +v0x55defa520590_0 .var "o_data", 7 0; +v0x55defa520670_0 .net "o_spi_clk", 0 0, L_0x55defa4e9b80; alias, 1 drivers +v0x55defa520730_0 .net "o_spi_cs", 0 0, L_0x55defa4e84f0; alias, 1 drivers +v0x55defa5207f0_0 .net "o_spi_mosi", 0 0, L_0x55defa4e09c0; alias, 1 drivers +v0x55defa5208b0_0 .var "r_baud_rate", 7 0; +v0x55defa520990_0 .var "r_clock_counter", 8 0; +v0x55defa520a70_0 .var "r_control", 7 0; +v0x55defa520b50_0 .var "r_input_data", 7 0; +v0x55defa520c30_0 .var "r_output_data", 7 0; +v0x55defa520d10_0 .var "r_spi_mosi", 0 0; +v0x55defa520dd0_0 .var "spi_clk", 0 0; +E_0x55defa4f2fe0/0 .event anyedge, v0x55defa4e11c0_0, v0x55defa5208b0_0, v0x55defa520b50_0, v0x55defa4e9d20_0; +E_0x55defa4f2fe0/1 .event anyedge, v0x55defa520a70_0; +E_0x55defa4f2fe0 .event/or E_0x55defa4f2fe0/0, E_0x55defa4f2fe0/1; +E_0x55defa4f1160 .event negedge, v0x55defa4e14a0_0; +L_0x55defa522260 .part v0x55defa520a70_0, 0, 1; +S_0x55defa521050 .scope task, "read_reg" "read_reg" 3 40, 3 40 0, S_0x55defa4f9970; + .timescale -8 -9; +v0x55defa521220_0 .var "_addr", 2 0; +v0x55defa521320_0 .var "_data", 7 0; +E_0x55defa4da3a0 .event posedge, v0x55defa4e14a0_0; +TD_sim.read_reg ; + %wait E_0x55defa4f1160; + %pushi/vec4 1, 0, 1; + %assign/vec4 v0x55defa521bd0_0, 0; + %load/vec4 v0x55defa521220_0; + %pad/u 2; + %assign/vec4 v0x55defa521a20_0, 0; + %pushi/vec4 1, 0, 1; + %assign/vec4 v0x55defa521db0_0, 0; + %pushi/vec4 255, 0, 8; + %assign/vec4 v0x55defa521c70_0, 0; + %wait E_0x55defa4da3a0; + %load/vec4 v0x55defa521f20_0; + %assign/vec4 v0x55defa521320_0, 0; + %wait E_0x55defa4f1160; + %pushi/vec4 0, 0, 1; + %assign/vec4 v0x55defa521bd0_0, 0; + %pushi/vec4 1, 0, 1; + %assign/vec4 v0x55defa521db0_0, 0; + %end; +S_0x55defa521400 .scope task, "write_reg" "write_reg" 3 27, 3 27 0, S_0x55defa4f9970; + .timescale -8 -9; +v0x55defa5215e0_0 .var "_addr", 2 0; +v0x55defa5216c0_0 .var "_data", 7 0; +TD_sim.write_reg ; + %wait E_0x55defa4f1160; + %pushi/vec4 1, 0, 1; + %assign/vec4 v0x55defa521bd0_0, 0; + %load/vec4 v0x55defa5215e0_0; + %pad/u 2; + %assign/vec4 v0x55defa521a20_0, 0; + %pushi/vec4 0, 0, 1; + %assign/vec4 v0x55defa521db0_0, 0; + %pushi/vec4 255, 0, 8; + %assign/vec4 v0x55defa521c70_0, 0; + %wait E_0x55defa4da3a0; + %load/vec4 v0x55defa5216c0_0; + %assign/vec4 v0x55defa521c70_0, 0; + %wait E_0x55defa4f1160; + %pushi/vec4 0, 0, 1; + %assign/vec4 v0x55defa521bd0_0, 0; + %pushi/vec4 1, 0, 1; + %assign/vec4 v0x55defa521db0_0, 0; + %end; + .scope S_0x55defa4b6270; +T_2 ; + %wait E_0x55defa4f1160; + %load/vec4 v0x55defa520350_0; + %flag_set/vec4 8; + %jmp/0xz T_2.0, 8; + %pushi/vec4 1, 0, 8; + %assign/vec4 v0x55defa5208b0_0, 0; + %pushi/vec4 0, 0, 8; + %assign/vec4 v0x55defa520b50_0, 0; + %pushi/vec4 0, 0, 8; + %assign/vec4 v0x55defa520c30_0, 0; + %pushi/vec4 0, 0, 8; + %assign/vec4 v0x55defa520a70_0, 0; + %pushi/vec4 0, 0, 9; + %assign/vec4 v0x55defa520990_0, 0; + %pushi/vec4 0, 0, 3; + %assign/vec4 v0x55defa4e0b20_0, 0; + %pushi/vec4 0, 0, 1; + %assign/vec4 v0x55defa520dd0_0, 0; + %pushi/vec4 0, 0, 1; + %assign/vec4 v0x55defa4e9d20_0, 0; + %jmp T_2.1; +T_2.0 ; + %load/vec4 v0x55defa520410_0; + %inv; + %load/vec4 v0x55defa4dfca0_0; + %and; + %flag_set/vec4 8; + %jmp/0xz T_2.2, 8; + %load/vec4 v0x55defa4e11c0_0; + %dup/vec4; + %pushi/vec4 0, 0, 2; + %cmp/u; + %jmp/1 T_2.4, 6; + %dup/vec4; + %pushi/vec4 1, 0, 2; + %cmp/u; + %jmp/1 T_2.5, 6; + %dup/vec4; + %pushi/vec4 2, 0, 2; + %cmp/u; + %jmp/1 T_2.6, 6; + %dup/vec4; + %pushi/vec4 3, 0, 2; + %cmp/u; + %jmp/1 T_2.7, 6; + %vpi_call/w 4 52 "$warning", "value is unhandled for priority or unique case statement" {0 0 0}; + %jmp T_2.8; +T_2.4 ; + %load/vec4 v0x55defa4e0660_0; + %assign/vec4 v0x55defa5208b0_0, 0; + %jmp T_2.8; +T_2.5 ; + %jmp T_2.8; +T_2.6 ; + %load/vec4 v0x55defa4e0660_0; + %assign/vec4 v0x55defa520c30_0, 0; + %pushi/vec4 1, 0, 1; + %assign/vec4 v0x55defa4e9d20_0, 0; + %jmp T_2.8; +T_2.7 ; + %load/vec4 v0x55defa4e0660_0; + %assign/vec4 v0x55defa520a70_0, 0; + %jmp T_2.8; +T_2.8 ; + %pop/vec4 1; +T_2.2 ; + %load/vec4 v0x55defa4e9d20_0; + %flag_set/vec4 8; + %jmp/0xz T_2.9, 8; + %load/vec4 v0x55defa520c30_0; + %parti/s 1, 7, 4; + %assign/vec4 v0x55defa520d10_0, 0; + %load/vec4 v0x55defa520990_0; + %addi 1, 0, 9; + %assign/vec4 v0x55defa520990_0, 0; + %load/vec4 v0x55defa5208b0_0; + %pad/u 9; + %load/vec4 v0x55defa520990_0; + %cmp/u; + %flag_or 5, 4; + %jmp/0xz T_2.11, 5; + %pushi/vec4 0, 0, 9; + %assign/vec4 v0x55defa520990_0, 0; + %load/vec4 v0x55defa520dd0_0; + %inv; + %assign/vec4 v0x55defa520dd0_0, 0; + %load/vec4 v0x55defa520dd0_0; + %cmpi/e 0, 0, 1; + %jmp/0xz T_2.13, 4; + %load/vec4 v0x55defa520c30_0; + %ix/load 4, 1, 0; + %flag_set/imm 4, 0; + %shiftl 4; + %assign/vec4 v0x55defa520c30_0, 0; + %load/vec4 v0x55defa4e0b20_0; + %addi 1, 0, 3; + %assign/vec4 v0x55defa4e0b20_0, 0; +T_2.13 ; + %load/vec4 v0x55defa520dd0_0; + %cmpi/e 1, 0, 1; + %jmp/0xz T_2.15, 4; + %load/vec4 v0x55defa520b50_0; + %parti/s 7, 0, 2; + %load/vec4 v0x55defa5204d0_0; + %concat/vec4; draw_concat_vec4 + %assign/vec4 v0x55defa520b50_0, 0; + %load/vec4 v0x55defa4e0b20_0; + %cmpi/e 0, 0, 3; + %jmp/0xz T_2.17, 4; + %pushi/vec4 0, 0, 1; + %assign/vec4 v0x55defa4e9d20_0, 0; +T_2.17 ; +T_2.15 ; +T_2.11 ; +T_2.9 ; +T_2.1 ; + %jmp T_2; + .thread T_2; + .scope S_0x55defa4b6270; +T_3 ; +Ewait_0 .event/or E_0x55defa4f2fe0, E_0x0; + %wait Ewait_0; + %load/vec4 v0x55defa4e11c0_0; + %dup/vec4; + %pushi/vec4 0, 0, 2; + %cmp/u; + %jmp/1 T_3.0, 6; + %dup/vec4; + %pushi/vec4 1, 0, 2; + %cmp/u; + %jmp/1 T_3.1, 6; + %dup/vec4; + %pushi/vec4 2, 0, 2; + %cmp/u; + %jmp/1 T_3.2, 6; + %dup/vec4; + %pushi/vec4 3, 0, 2; + %cmp/u; + %jmp/1 T_3.3, 6; + %vpi_call/w 4 88 "$warning", "value is unhandled for priority or unique case statement" {0 0 0}; + %jmp T_3.4; +T_3.0 ; + %load/vec4 v0x55defa5208b0_0; + %store/vec4 v0x55defa520590_0, 0, 8; + %jmp T_3.4; +T_3.1 ; + %load/vec4 v0x55defa520b50_0; + %store/vec4 v0x55defa520590_0, 0, 8; + %jmp T_3.4; +T_3.2 ; + %jmp T_3.4; +T_3.3 ; + %load/vec4 v0x55defa4e9d20_0; + %load/vec4 v0x55defa520a70_0; + %parti/s 7, 0, 2; + %concat/vec4; draw_concat_vec4 + %store/vec4 v0x55defa520590_0, 0, 8; + %jmp T_3.4; +T_3.4 ; + %pop/vec4 1; + %jmp T_3; + .thread T_3, $push; + .scope S_0x55defa4f9970; +T_4 ; + %delay 10, 0; + %load/vec4 v0x55defa5218a0_0; + %pushi/vec4 0, 0, 1; + %cmp/e; + %flag_get/vec4 6; + %store/vec4 v0x55defa5218a0_0, 0, 1; + %jmp T_4; + .thread T_4; + .scope S_0x55defa4f9970; +T_5 ; + %delay 1000, 0; + %load/vec4 v0x55defa521ae0_0; + %pushi/vec4 0, 0, 1; + %cmp/e; + %flag_get/vec4 6; + %store/vec4 v0x55defa521ae0_0, 0, 1; + %jmp T_5; + .thread T_5; + .scope S_0x55defa4f9970; +T_6 ; + %vpi_call/w 3 55 "$dumpfile", "spi_controller.vcd" {0 0 0}; + %vpi_call/w 3 56 "$dumpvars", 32'sb00000000000000000000000000000000, S_0x55defa4f9970 {0 0 0}; + %end; + .thread T_6; + .scope S_0x55defa4f9970; +T_7 ; + %pushi/vec4 1, 0, 1; + %assign/vec4 v0x55defa521d10_0, 0; + %pushi/vec4 5, 0, 32; +T_7.0 %dup/vec4; + %pushi/vec4 0, 0, 32; + %cmp/s; + %jmp/1xz T_7.1, 5; + %jmp/1 T_7.1, 4; + %pushi/vec4 1, 0, 32; + %sub; + %wait E_0x55defa4da3a0; + %jmp T_7.0; +T_7.1 ; + %pop/vec4 1; + %pushi/vec4 0, 0, 1; + %assign/vec4 v0x55defa521bd0_0, 0; + %pushi/vec4 1, 0, 1; + %assign/vec4 v0x55defa521db0_0, 0; + %pushi/vec4 0, 0, 2; + %assign/vec4 v0x55defa521a20_0, 0; + %pushi/vec4 0, 0, 1; + %assign/vec4 v0x55defa521d10_0, 0; + %pushi/vec4 5, 0, 32; +T_7.2 %dup/vec4; + %pushi/vec4 0, 0, 32; + %cmp/s; + %jmp/1xz T_7.3, 5; + %jmp/1 T_7.3, 4; + %pushi/vec4 1, 0, 32; + %sub; + %wait E_0x55defa4da3a0; + %jmp T_7.2; +T_7.3 ; + %pop/vec4 1; + %pushi/vec4 3, 0, 3; + %store/vec4 v0x55defa5215e0_0, 0, 3; + %pushi/vec4 1, 0, 8; + %store/vec4 v0x55defa5216c0_0, 0, 8; + %fork TD_sim.write_reg, S_0x55defa521400; + %join; + %pushi/vec4 2, 0, 3; + %store/vec4 v0x55defa5215e0_0, 0, 3; + %pushi/vec4 170, 0, 8; + %store/vec4 v0x55defa5216c0_0, 0, 8; + %fork TD_sim.write_reg, S_0x55defa521400; + %join; + %pushi/vec4 128, 0, 8; + %store/vec4 v0x55defa521960_0, 0, 8; +T_7.4 ; + %load/vec4 v0x55defa521960_0; + %pad/u 32; + %pushi/vec4 128, 0, 32; + %and; + %or/r; + %flag_set/vec4 8; + %jmp/0xz T_7.5, 8; + %pushi/vec4 3, 0, 3; + %store/vec4 v0x55defa521220_0, 0, 3; + %fork TD_sim.read_reg, S_0x55defa521050; + %join; + %load/vec4 v0x55defa521320_0; + %store/vec4 v0x55defa521960_0, 0, 8; + %jmp T_7.4; +T_7.5 ; + %pushi/vec4 3, 0, 3; + %store/vec4 v0x55defa5215e0_0, 0, 3; + %pushi/vec4 0, 0, 8; + %store/vec4 v0x55defa5216c0_0, 0, 8; + %fork TD_sim.write_reg, S_0x55defa521400; + %join; + %pushi/vec4 1, 0, 3; + %store/vec4 v0x55defa521220_0, 0, 3; + %fork TD_sim.read_reg, S_0x55defa521050; + %join; + %load/vec4 v0x55defa521320_0; + %store/vec4 v0x55defa521960_0, 0, 8; + %load/vec4 v0x55defa521960_0; + %cmpi/e 85, 0, 8; + %jmp/0xz T_7.6, 4; + %jmp T_7.7; +T_7.6 ; + %vpi_call/w 3 79 "$error" {0 0 0}; +T_7.7 ; + %pushi/vec4 50, 0, 32; +T_7.8 %dup/vec4; + %pushi/vec4 0, 0, 32; + %cmp/s; + %jmp/1xz T_7.9, 5; + %jmp/1 T_7.9, 4; + %pushi/vec4 1, 0, 32; + %sub; + %wait E_0x55defa4da3a0; + %jmp T_7.8; +T_7.9 ; + %pop/vec4 1; + %vpi_call/w 3 83 "$finish" {0 0 0}; + %end; + .thread T_7; + .scope S_0x55defa4f9970; +T_8 ; + %pushi/vec4 85, 0, 8; + %assign/vec4 v0x55defa5217a0_0, 0; + %end; + .thread T_8; + .scope S_0x55defa4f9970; +T_9 ; + %wait E_0x55defa4f0300; + %load/vec4 v0x55defa5220c0_0; + %cmpi/e 0, 0, 1; + %jmp/0xz T_9.0, 4; + %load/vec4 v0x55defa521ff0_0; + %cmpi/e 1, 0, 1; + %jmp/0xz T_9.2, 4; + %load/vec4 v0x55defa5217a0_0; + %parti/s 1, 7, 4; + %assign/vec4 v0x55defa521e50_0, 0; +T_9.2 ; + %load/vec4 v0x55defa521ff0_0; + %cmpi/e 0, 0, 1; + %jmp/0xz T_9.4, 4; + %load/vec4 v0x55defa5217a0_0; + %ix/load 4, 1, 0; + %flag_set/imm 4, 0; + %shiftl 4; + %assign/vec4 v0x55defa5217a0_0, 0; +T_9.4 ; +T_9.0 ; + %jmp T_9; + .thread T_9; +# The file index is used to find the file name in the following table. +:file_names 5; + "N/A"; + ""; + "-"; + "spi_controller_tb.sv"; + "../spi_controller.sv"; diff --git a/hw/efinix_fpga/simulation/spi_controller_tb.sv b/hw/efinix_fpga/simulation/spi_controller_tb.sv index 37c1ae3..daeddd3 100644 --- a/hw/efinix_fpga/simulation/spi_controller_tb.sv +++ b/hw/efinix_fpga/simulation/spi_controller_tb.sv @@ -56,14 +56,47 @@ begin $dumpvars(0,sim); end +logic [7:0] data; + initial begin i_rst <= '1; repeat(5) @(posedge i_clk); + i_cs <= '0; + i_rwb <= '1; + i_addr <= '0; i_rst <= '0; repeat(5) @(posedge i_clk); + write_reg(3, 1); + write_reg(2, 8'hAA); + data = (1 << 7); + while(data & (1 << 7)) begin + read_reg(3, data); + end + write_reg(3, 0); + read_reg(1, data); + assert(data == 8'h55); + + repeat(50) @(posedge i_clk); + $finish(); end + +logic [7:0] _spi_device_data; + +initial begin + _spi_device_data <= 8'h55; +end + +always @(edge o_spi_clk) begin + if (o_spi_cs == '0) begin + if (o_spi_clk == '1) + i_spi_miso <= _spi_device_data[7]; + if (o_spi_clk == '0) + _spi_device_data <= _spi_device_data << 1; + end +end + endmodule \ No newline at end of file diff --git a/hw/efinix_fpga/spi_controller.sv b/hw/efinix_fpga/spi_controller.sv index 9b806f7..2d085e4 100644 --- a/hw/efinix_fpga/spi_controller.sv +++ b/hw/efinix_fpga/spi_controller.sv @@ -28,18 +28,25 @@ logic [7:0] r_control; logic [8:0] r_clock_counter; logic active; +logic [2:0] count; logic spi_clk; logic r_spi_mosi; -always @(posedge i_clk) begin +assign o_spi_cs = ~r_control[0]; +assign o_spi_clk = spi_clk; +assign o_spi_mosi = r_spi_mosi; + +always @(negedge i_clk) begin if (i_rst) begin - r_baud_rate <= 8'h10; + r_baud_rate <= 8'h1; r_input_data <= '0; r_output_data <= '0; r_control <= '0; r_clock_counter <= '0; + count <= '0; spi_clk <= '0; + active <= '0; end else begin if (~i_rwb & i_cs) begin unique case (i_addr) @@ -54,16 +61,22 @@ always @(posedge i_clk) begin end if (active) begin - r_spi_mosi <= r_output_data[0]; + r_spi_mosi <= r_output_data[7]; r_clock_counter <= r_clock_counter + 9'b1; if (r_clock_counter >= r_baud_rate) begin r_clock_counter <= '0; spi_clk <= ~spi_clk; + // rising edge if (spi_clk == '0) begin - r_output_data <= r_output_data >> 1; + r_output_data <= r_output_data << 1; + count <= count + 1; end + // falling edge if (spi_clk == '1) begin - r_input_data <= {r_input_data[7:1], i_spi_miso}; + r_input_data <= {r_input_data[6:0], i_spi_miso}; + if (count == '0) begin + active <= '0; + end end end @@ -76,7 +89,7 @@ always_comb begin 0: o_data = r_baud_rate; 1: o_data = r_input_data; 2:; - 3: o_data = r_control; + 3: o_data = {active, r_control[6:0]}; endcase end