From 436020ce4e4f62ffab9051f433b0e8517e20c5e1 Mon Sep 17 00:00:00 2001 From: "Pavel V. Shatov (Meister)" Date: Mon, 20 Dec 2021 12:59:45 +0300 Subject: Improved MKM reference design. --- mkm_refdes/src/mkm_refdes.v | 205 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 mkm_refdes/src/mkm_refdes.v 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 -- cgit v1.2.3