summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2021-12-20 12:59:45 +0300
committerPavel V. Shatov (Meister) <meisterpaul1@yandex.ru>2021-12-20 12:59:45 +0300
commit436020ce4e4f62ffab9051f433b0e8517e20c5e1 (patch)
treea16b8c356f915f02f7233b63048e23ff54893e0a
parent9ecc9e83e8d182b7dbc3e21f3ba7870747c81e92 (diff)
Improved MKM reference design.
-rw-r--r--mkm_refdes/src/mkm_refdes.v205
1 files changed, 205 insertions, 0 deletions
diff --git a/mkm_refdes/src/mkm_refdes.v b/mkm_refdes/src/mkm_refdes.v
new file mode 100644
index 0000000..22e9918
--- /dev/null
+++ b/mkm_refdes/src/mkm_refdes.v
@@ -0,0 +1,205 @@
+module mkm_refdes
+(
+ output [3:0] leds, // {blue, red, yellow, green}
+
+ input mkm_cs_n, mkm_sclk, mkm_di,
+ output mkm_do,
+
+ input btn_panic
+);
+
+ //
+ // Internal High-Speed Oscillator
+ //
+ wire clk_osc_lf; // 48 MHz
+ SB_LFOSC SB_LFOSC_inst
+ (
+ .CLKLFPU (1'b1),
+ .CLKLFEN (1'b1),
+ .CLKLF (clk_osc_lf)
+ ) /* synthesis ROUTE_THROUGH_FABRIC = 0 */;
+
+
+ //
+ // Blinking Green LED
+ //
+ reg [13:0] led_cnt = 14'd0;
+ reg led_green = 1'b0;
+
+ always @(posedge clk_osc_lf) begin
+ led_cnt <= led_cnt + 1'b1;
+ led_green <= &led_cnt[13:12];
+ end
+
+
+ //
+ // "Panic" Red LED
+ //
+ reg led_red = 1'b0;
+
+ always @(posedge clk_osc_lf)
+ led_red <= btn_panic;
+
+
+ //
+ // Blue LED to indicate MKM access over SPI
+ //
+ reg led_blue = 1'b0;
+
+ reg mkm_cs_n_sync1 = 1'b1;
+ reg mkm_cs_n_sync2 = 1'b1;
+
+ always @(posedge clk_osc_lf)
+ {mkm_cs_n_sync1, mkm_cs_n_sync2} <=
+ {mkm_cs_n, mkm_cs_n_sync1};
+
+ reg [12:0] spi_cnt = 13'd0;
+
+ always @(posedge clk_osc_lf)
+ //
+ if (spi_cnt > 13'd0)
+ spi_cnt <= spi_cnt - 13'd1;
+ else if (!mkm_cs_n_sync2)
+ spi_cnt <= {13{1'b1}};
+
+ always @(posedge clk_osc_lf)
+ //
+ led_blue <= spi_cnt[10];
+
+
+ //
+ // serial memory follows
+ //
+
+
+ //
+ // operation mode
+ //
+ reg [1:0] opmode = 2'b00;
+
+
+ //
+ // bit counter
+ //
+ localparam integer BIT_CNT_W = 16;
+ localparam [BIT_CNT_W-1:0] bit_cnt_zero = {BIT_CNT_W{1'b0}};
+ reg [BIT_CNT_W-1:0] bit_cnt = bit_cnt_zero;
+ wire [BIT_CNT_W-1:0] bit_cnt_next = bit_cnt + 16'd1;
+
+ always @(posedge mkm_sclk or posedge mkm_cs_n)
+ //
+ if (mkm_cs_n) bit_cnt <= bit_cnt_zero;
+ else bit_cnt <= bit_cnt_next;
+
+
+ //
+ // input shifter
+ //
+ reg [15:0] di_shreg;
+ always @(posedge mkm_sclk)
+ //
+ if (!mkm_cs_n) di_shreg <= {di_shreg[14:0], mkm_di};
+
+
+ //
+ // instruction decoder
+ //
+ reg [7:0] instr_latch;
+
+ wire instr_is_read = instr_latch == 8'b0000_0011;
+ wire instr_is_write = instr_latch == 8'b0000_0010;
+ wire instr_is_rdsr = instr_latch == 8'b0000_0101;
+ wire instr_is_wrsr = instr_latch == 8'b0000_0001;
+
+ always @(posedge mkm_sclk)
+ //
+ if (bit_cnt == 7) instr_latch <= {di_shreg[6:0], mkm_di};
+
+ //
+ // address latch
+ //
+ reg [15:0] addr_latch;
+
+ always @(posedge mkm_sclk) begin
+ //
+ if (bit_cnt == 23) addr_latch <= {di_shreg[14:0], mkm_di};
+ //
+ if ((bit_cnt >= 31) && (bit_cnt[2:0] == 3'b111) & instr_is_write) begin
+ //
+ if (opmode == 2'b10) // page mode
+ addr_latch[4:0] <= addr_latch[4:0] + 1'b1;
+ else if (opmode == 2'b01) // seq mode
+ addr_latch[7:0] <= addr_latch[7:0] + 1'b1;
+ //
+ end
+ //
+ if ((bit_cnt >= 24) && (bit_cnt[2:0] == 3'b000) && instr_is_read) begin
+ //
+ if (opmode == 2'b10) // page
+ addr_latch[4:0] <= addr_latch[4:0] + 1'b1;
+ else if (opmode == 2'b01) // seq
+ addr_latch[7:0] <= addr_latch[7:0] + 1'b1;
+ end
+ //
+ end
+
+
+ //
+ // mode change
+ //
+ always @(posedge mkm_sclk)
+ //
+ if ((bit_cnt == 15) && instr_is_wrsr && (di_shreg[4:0] == {5{1'b0}}))
+ //
+ opmode <= di_shreg[6:5];
+
+
+ //
+ // memory
+ //
+ localparam MEM_ADDR_W = 6; // 64 bytes
+
+ reg [7:0] sram[0:2**MEM_ADDR_W-1] /* synthesis syn_ramstyle="registers" */;
+
+
+ //
+ // write logic
+ //
+ always @(posedge mkm_sclk)
+ //
+ if ((bit_cnt >= 31) && (bit_cnt[2:0] == 3'b111) & instr_is_write)
+ //
+ sram[addr_latch[MEM_ADDR_W-1:0]] <= {di_shreg[6:0], mkm_di};
+
+
+ //
+ // serial output
+ //
+ reg [7:0] do_shreg;
+ assign mkm_do = do_shreg[7];
+
+ always @(negedge mkm_sclk)
+ //
+ if (bit_cnt[2:0] == 3'b000) begin
+ //
+ if ((bit_cnt >= 24) && instr_is_read)
+ //
+ do_shreg <= sram[addr_latch[MEM_ADDR_W:0]];
+ //
+ else if ((bit_cnt > 7) && instr_is_rdsr)
+ do_shreg <= {opmode, 5'b00000, 1'b1};
+ //
+ end else
+ do_shreg <= {do_shreg[6:0], 1'bX};
+
+
+ //
+ // Map LEDs
+ //
+ assign leds[0] = led_green; //
+ assign leds[1] = 1'b0; // unused (yellow)
+ assign leds[2] = led_red; //
+ assign leds[3] = led_blue; //
+
+
+endmodule