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