]> git.ozlabs.org Git - minimigmac.git/blob - fpga/scope.v
Add GPL v2
[minimigmac.git] / fpga / scope.v
1 /*
2  * Internal signal capture module
3  */
4
5 `define SIGCAP_WIDTH    64
6 `define SIGCAP_DEPTH    2048
7 `define SIGCAP_ADDRBITS 16
8
9 /* Capture RAM module, should infer a block RAM in ISE
10  *
11  * Based on XST example "Dual-Port Block RAM with Different Clocks"
12  */
13 module capram
14 (
15         input                           clka,
16         input                           clkb,
17         input                           wea,
18         input [`SIGCAP_ADDRBITS-1:0]    addra,
19         input [`SIGCAP_ADDRBITS-1:0]    addrb,
20         input [`SIGCAP_WIDTH-1:0]       dia,
21         output [`SIGCAP_WIDTH-1:0]      doa,
22         output [`SIGCAP_WIDTH-1:0]      dob
23 );      
24         reg [`SIGCAP_WIDTH-1:0]         ram [`SIGCAP_DEPTH-1:0];
25         reg [`SIGCAP_ADDRBITS-1:0]      addr_rega;
26         reg [`SIGCAP_ADDRBITS-1:0]      addr_regb;
27
28         always @(posedge clka) begin
29                 if (wea)
30                   ram[addra] <= dia;
31                 addr_rega <= addra;
32         end
33         always @(posedge clkb) begin
34                 addr_regb <= addrb;
35         end
36         assign doa = ram[addr_rega];
37         assign dob = ram[addr_regb];
38 endmodule
39
40 /* WO: Capture control register */
41 `define SIGCAP_REG_CTRL         0
42 `define    SIGCAP_CTRL_RESET    0 /* 8'b00000001 */
43 `define    SIGCAP_CTRL_RUN      1 /* 8'b00000002 */
44
45 /* RO: Total sample count in buffer */
46 `define SIGCAP_REG_COUNT_0      2
47 `define SIGCAP_REG_COUNT_1      3
48
49 /* RW: Read next sample. Write reset read address */
50 `define SIGCAP_REG_DATA         4
51
52 /*
53  * Note about clock domains:
54  * 
55  * sysclk is used for the register interface, capclk for the actual
56  * capture. However, we don't use synchronizers when those domains
57  * collide, as we know that both clocks derive from the same DLL
58  * and shouldn't go metastable. Typically capclk is a multiple of
59  * sysclk
60  */
61 module scope
62 (
63         /* System clock */
64         input                           sysclk,
65         /* Capture clock */
66         input                           capclk,
67         /* System reset */
68         input                           reset,
69         /* Signals to capture */
70         input [`SIGCAP_WIDTH-1:0]       sigs,
71
72         /* Backbus interface */
73         input [5:0]                     bb_addr,
74         input [7:0]                     bb_wdata,
75         output [7:0]                    bb_rdata,
76         input                           bb_strobe,
77         input                           bb_wr
78  );
79         reg                             capturing;
80
81         reg [`SIGCAP_ADDRBITS-1:0]      cap_addr;
82         reg [`SIGCAP_ADDRBITS-1:0]      read_addr;
83         reg [2:0]                       read_byte;      
84         
85         wire [`SIGCAP_WIDTH-1:0]        cap_data;
86         reg [7:0]                       cap_byte;
87         wire [`SIGCAP_WIDTH-1:0]        ram_ignore;
88
89         reg                             do_reset;
90         reg                             do_run;
91
92         wire                            cap_full;
93         wire                            do_reset_combo;
94
95
96         /* Instanciate capture memory */
97         capram capram0(.clka(capclk),
98                        .clkb(sysclk),
99                        .wea(capturing && !cap_full),
100                        .addra(cap_addr),
101                        .addrb(read_addr),
102                        .dia(sigs),
103                        .doa(ram_ignore),
104                        .dob(cap_data));
105
106         /* Capture control logic */
107         always@(posedge capclk or posedge reset) begin
108                 if (reset) begin
109                         cap_addr <= 0;                  
110                 end else begin
111                         if (do_reset) begin
112                                 capturing <= 0;
113                                 cap_addr <= 0;
114                         end else if (!do_run) begin
115                                 capturing <= 0;
116                         end else begin
117                                 capturing <= 1;
118                                 if (capturing && !cap_full) begin
119                                         cap_addr <= cap_addr + 1;
120                                 end                             
121                         end
122                 end
123         end
124         assign cap_full = cap_addr == (`SIGCAP_DEPTH - 1);
125
126         /* Mux memory output */
127         always@(read_byte or cap_data) begin
128                 case (read_byte)
129                         0: cap_byte = cap_data[63:56];
130                         1: cap_byte = cap_data[55:48];
131                         2: cap_byte = cap_data[47:40];
132                         3: cap_byte = cap_data[39:32];
133                         4: cap_byte = cap_data[31:24];
134                         5: cap_byte = cap_data[23:16];
135                         6: cap_byte = cap_data[15:8];
136                         7: cap_byte = cap_data[7:0];
137                         default: cap_byte = cap_data[7:0];
138                 endcase
139         end
140
141         /* Register read */
142         assign bb_rdata = (bb_addr[2:0] == `SIGCAP_REG_COUNT_0) ?
143                                 cap_addr[`SIGCAP_ADDRBITS-1:8] :
144                           (bb_addr[2:0] == `SIGCAP_REG_COUNT_1) ? cap_addr[7:0] :
145                           cap_byte;     
146
147         /* Fifo address counter */
148         assign do_reset_combo = reset | do_reset;
149
150         always@(posedge sysclk or posedge do_reset_combo) begin
151                 if (do_reset_combo) begin
152                         read_addr <= 0;
153                         read_byte <= 0;
154                 end else begin
155                         if (bb_strobe && bb_addr[2:0] == `SIGCAP_REG_DATA) begin
156                                 if (bb_wr) begin
157                                         read_byte <= 0;
158                                         read_addr <= 0;
159                                 end else begin
160                                         read_byte <= read_byte + 1;
161                                         if (read_byte == 3'b111)
162                                           read_addr <= read_addr + 1;
163                                 end                             
164                         end
165                 end
166         end
167         
168         /* Control register write interface */
169         always@(posedge sysclk or posedge reset) begin
170                 if (reset) begin
171                         do_reset <= 1;
172                         do_run <= 0;                    
173                 end else begin
174                         if (bb_strobe && bb_wr && bb_addr[2:0] == `SIGCAP_REG_CTRL) begin
175                                 do_reset <= bb_wdata[`SIGCAP_CTRL_RESET];
176                                 do_run <= bb_wdata[`SIGCAP_CTRL_RUN];
177                         end
178                 end
179         end
180 endmodule
181
182         
183                                 
184                         
185