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