gateware

A collection of little open source FPGA hobby projects
git clone http://frotz.net/git/gateware.git
Log | Files | Refs | README

scope.sv (3824B)


      1 // Copyright 2018, Brian Swetland <swetland@frotz.net>
      2 // Licensed under the Apache License, Version 2.0.
      3 
      4 `default_nettype none
      5 
      6 // Captures up to 16K samples of 64 bits while trace_en
      7 // Plays them back over the uart when ~trace_en
      8 
      9 module scope(
     10 	input clk,
     11 	input [63:0]trace_in,
     12 	input trace_en,
     13 	output uart_tx
     14 	);
     15 
     16 wire [63:0]trace_out;
     17 
     18 reg [13:0]trace_waddr = 14'd0;
     19 reg [13:0]trace_waddr_next;
     20 wire [13:0]trace_waddr_incr;
     21 wire trace_wdone;
     22 
     23 assign { trace_wdone, trace_waddr_incr } = { 1'b0, trace_waddr } + 15'd1;
     24 
     25 always_comb begin
     26 	trace_waddr_next = trace_waddr;
     27 	if (trace_en) begin
     28 		if (~trace_wdone)
     29 			trace_waddr_next = trace_waddr_incr;
     30 	end else begin
     31 		trace_waddr_next = 14'd0;
     32 	end
     33 end
     34 
     35 always_ff @(posedge clk) begin
     36 	trace_waddr <= trace_waddr_next;
     37 end
     38 
     39 reg [16:0]trace_raddr = 17'd0;
     40 reg [16:0]trace_raddr_next;
     41 wire [16:0]trace_raddr_incr;
     42 wire trace_rdone;
     43 
     44 assign { trace_rdone, trace_raddr_incr } = { 1'b0, trace_raddr[16:0] } + 18'd1;
     45 
     46 reg [7:0]trace_byte;
     47 
     48 always_comb begin
     49 	case (trace_raddr[2:0])
     50 	3'd0: trace_byte = trace_out[7:0];
     51 	3'd1: trace_byte = trace_out[15:8];
     52 	3'd2: trace_byte = trace_out[23:16];
     53 	3'd3: trace_byte = trace_out[31:24];
     54 	3'd4: trace_byte = trace_out[39:32];
     55 	3'd5: trace_byte = trace_out[47:40];
     56 	3'd6: trace_byte = trace_out[55:48];
     57 	3'd7: trace_byte = trace_out[63:56];
     58 	endcase
     59 end
     60 
     61 reg [4:0]clkcount_next;
     62 reg [4:0]bitcount_next;
     63 reg [12:0]shift_next;
     64 reg reload_next;
     65 
     66 reg [4:0]clkcount = 5'd0;
     67 reg [4:0]bitcount = 5'd0; // IDLE(1) STOP(1) DATA(x) x 8 START(0) -> wire
     68 reg [12:0]shift = 13'd0;
     69 reg reload = 1'b0;
     70 
     71 always_comb begin
     72 	shift_next = shift;
     73 	clkcount_next = clkcount;
     74 	bitcount_next = bitcount;
     75 	trace_raddr_next = trace_raddr;
     76 	reload_next = 1'b0;
     77 
     78 	if (trace_en) begin
     79 		shift_next = 13'h1FFF;
     80 		clkcount_next = 5'd10;
     81 		bitcount_next = 5'd12;
     82 		trace_raddr_next = 17'd0;
     83 	end else begin
     84 		if (reload) begin
     85 			shift_next = { 4'b1111, trace_byte, 1'b0 };
     86 		end
     87 		if (clkcount[4] & (~trace_rdone)) begin
     88 			// underflow! one uart bit time has passed
     89 			clkcount_next = 5'd10;
     90 			if (bitcount[4]) begin
     91 			 	// undeflow! one uart character has been sent
     92 				// bump the read addr, but defer reload to
     93 				// next cycle
     94 				trace_raddr_next = trace_raddr_incr;
     95 				shift_next = { 4'b1111, trace_byte, 1'b0 };
     96 				reload_next = 1'b1;
     97 				bitcount_next = 5'd12;
     98 			end else begin
     99 				shift_next = { 1'b1, shift[12:1] };
    100 				bitcount_next = bitcount - 5'd1;
    101 			end
    102 		end else begin
    103 			clkcount_next = clkcount - 5'd1;
    104 		end
    105 	end
    106 end
    107 
    108 always_ff @(posedge clk) begin
    109 	shift <= shift_next;
    110 	clkcount <= clkcount_next;
    111 	bitcount <= bitcount_next;
    112 	trace_raddr <= trace_raddr_next;
    113 end
    114 
    115 assign uart_tx = shift[0];
    116 
    117 wire trace_we = trace_en;
    118 wire [13:0]trace_addr = trace_we ? trace_waddr : trace_raddr[16:3];
    119 
    120 spram tram0(
    121 	.clk(clk),
    122 	.addr(trace_addr),
    123 	.wr_data(trace_in[63:48]),
    124 	.rd_data(trace_out[63:48]),
    125 	.wr_en(trace_we)
    126 	);
    127 spram tram1(
    128 	.clk(clk),
    129 	.addr(trace_addr),
    130 	.wr_data(trace_in[47:32]),
    131 	.rd_data(trace_out[47:32]),
    132 	.wr_en(trace_we)
    133 	);
    134 spram tram2(
    135 	.clk(clk),
    136 	.addr(trace_addr),
    137 	.wr_data(trace_in[31:16]),
    138 	.rd_data(trace_out[31:16]),
    139 	.wr_en(trace_we)
    140 	);
    141 spram tram3(
    142 	.clk(clk),
    143 	.addr(trace_addr),
    144 	.wr_data(trace_in[15:0]),
    145 	.rd_data(trace_out[15:0]),
    146 	.wr_en(trace_we)
    147 	);
    148 
    149 endmodule
    150 
    151 
    152 
    153 module spram(
    154 	input clk,
    155 	input [13:0]addr,
    156 	input [15:0]wr_data,
    157 	output [15:0]rd_data,
    158 	input wr_en
    159 	);
    160 
    161 `ifdef verilator
    162 reg [15:0]mem[0:16383];
    163 reg [15:0]data;
    164 
    165 always_ff @(posedge clk) begin
    166 	if (wr_en)
    167 		mem[addr] <= wr_data;
    168 	else
    169 		data <= mem[addr];
    170 end
    171 
    172 assign rd_data = data;
    173 `else
    174 SB_SPRAM256KA spram_inst(
    175 	.ADDRESS(addr),
    176 	.DATAIN(wr_data),
    177 	.DATAOUT(rd_data),
    178 	.MASKWREN(4'b1111),
    179 	.WREN(wr_en),
    180 	.CHIPSELECT(1'b1),
    181 	.CLOCK(clk),
    182 	.STANDBY(1'b0),
    183 	.SLEEP(1'b0),
    184 	.POWEROFF(1'b1) // active low
    185 	);
    186 `endif
    187 
    188 endmodule
    189 
    190