某些时候,我们在使用Altera FPGA的时候,尤其是涉及SoC系统的时候,通常需要一个串口与PC交互。使用Altera的USB-Blaster免去了外接一个串口。我们可以使用下面所述的IP核通过USB-Blaster将PC的字符传入FPGA或者从FPGA将字符数据发送至PC。
1 alt_jtag_atlantic jtag_uart_alt_jtag_atlantic 2 ( 3 .clk (clk), 4 .r_dat (r_dat), 5 .r_ena (r_ena), 6 .r_val (r_val), 7 .rst_n (rst_n), 8 .t_dat (t_dat), 9 .t_dav (t_dav), 10 .t_ena (t_ena), 11 .t_pause (t_pause) 12 ); 13 14 defparam jtag_uart_alt_jtag_atlantic.INSTANCE_ID = 0, 15 jtag_uart_alt_jtag_atlantic.LOG2_RXFIFO_DEPTH = 6, 16 jtag_uart_alt_jtag_atlantic.LOG2_TXFIFO_DEPTH = 6, 17 jtag_uart_alt_jtag_atlantic.SLD_AUTO_INSTANCE_INDEX = "YES";
下面贴出一个Wishbone接口的JTAG UART的代码描述:
1 // synthesis translate_off 2 `timescale 1ns / 1ps 3 // synthesis translate_on 4 5 module wb_jtag_uart ( 6 input clk_i, 7 input rst_i, 8 9 input wb_stb_i, 10 input wb_cyc_i, 11 output wb_ack_o, 12 input wb_adr_i, 13 input wb_we_i, 14 input [31:0] wb_dat_i, 15 output [31:0] wb_dat_o, 16 output wb_irq_o 17 ); 18 19 /* synthesis ALTERA_ATTRIBUTE = "SUPPRESS_DA_RULE_INTERNAL="R101,C106,D101,D103"" */ 20 21 reg ac; 22 wire activity; 23 wire av_irq; 24 wire [ 31: 0] av_readdata; 25 wire [ 31: 0] av_writedata; 26 reg av_waitrequest; 27 reg fifo_AE; 28 reg fifo_AF; 29 wire fifo_EF; 30 wire fifo_FF; 31 wire fifo_clear; 32 wire fifo_rd; 33 wire [ 7: 0] fifo_rdata; 34 wire [ 7: 0] fifo_wdata; 35 reg fifo_wr; 36 reg ien_AE; 37 reg ien_AF; 38 wire ipen_AE; 39 wire ipen_AF; 40 reg pause_irq; 41 wire [ 7: 0] r_dat; 42 wire r_ena; 43 reg r_val; 44 wire rd_wfifo; 45 reg read_0; 46 wire rfifo_full; 47 wire [ 5: 0] rfifo_used; 48 reg rvalid; 49 reg sim_r_ena; 50 reg sim_t_dat; 51 reg sim_t_ena; 52 reg sim_t_pause; 53 wire [ 7: 0] t_dat; 54 reg t_dav; 55 wire t_ena; 56 wire t_pause; 57 wire wfifo_empty; 58 wire [ 5: 0] wfifo_used; 59 reg woverflow; 60 wire wr_rfifo; 61 wire clk; 62 wire rst_n; 63 wire av_read_n; 64 wire av_write_n; 65 wire av_address; 66 wire av_chipselect; 67 68 assign clk = clk_i; 69 assign rst_n = ~rst_i; 70 assign av_address = wb_adr_i; 71 assign wb_dat_o = av_readdata; 72 assign av_writedata = wb_dat_i; 73 assign wb_irq_o = av_irq; 74 assign wb_ack_o = ~av_waitrequest; 75 assign av_read_n = ~(wb_cyc_i & wb_stb_i & (~wb_we_i)); 76 assign av_write_n = ~(wb_cyc_i & wb_stb_i & wb_we_i); 77 assign av_chipselect = wb_cyc_i & wb_stb_i; 78 79 //avalon_jtag_slave, which is an e_avalon_slave 80 assign rd_wfifo = r_ena & ~wfifo_empty; 81 assign wr_rfifo = t_ena & ~rfifo_full; 82 assign fifo_clear = ~rst_n; 83 wb_jtag_uart_scfifo_w jtag_uart_scfifo_w 84 ( 85 .clk (clk), 86 .fifo_FF (fifo_FF), 87 .fifo_clear (fifo_clear), 88 .fifo_wdata (fifo_wdata), 89 .fifo_wr (fifo_wr), 90 .r_dat (r_dat), 91 .rd_wfifo (rd_wfifo), 92 .wfifo_empty (wfifo_empty), 93 .wfifo_used (wfifo_used) 94 ); 95 96 wb_jtag_uart_scfifo_r jtag_uart_scfifo_r 97 ( 98 .clk (clk), 99 .fifo_EF (fifo_EF), 100 .fifo_clear (fifo_clear), 101 .fifo_rd (fifo_rd), 102 .fifo_rdata (fifo_rdata), 103 .rfifo_full (rfifo_full), 104 .rfifo_used (rfifo_used), 105 .rst_n (rst_n), 106 .t_dat (t_dat), 107 .wr_rfifo (wr_rfifo) 108 ); 109 110 assign ipen_AE = ien_AE & fifo_AE; 111 assign ipen_AF = ien_AF & (pause_irq | fifo_AF); 112 assign av_irq = ipen_AE | ipen_AF; 113 assign activity = t_pause | t_ena; 114 always @(posedge clk or negedge rst_n) 115 begin 116 if (rst_n == 0) 117 pause_irq <= 1'b0; 118 else // only if fifo is not empty... 119 if (t_pause & ~fifo_EF) 120 pause_irq <= 1'b1; 121 else if (read_0) 122 pause_irq <= 1'b0; 123 end 124 125 126 always @(posedge clk or negedge rst_n) 127 begin 128 if (rst_n == 0) 129 begin 130 r_val <= 1'b0; 131 t_dav <= 1'b1; 132 end 133 else 134 begin 135 r_val <= r_ena & ~wfifo_empty; 136 t_dav <= ~rfifo_full; 137 end 138 end 139 140 141 always @(posedge clk or negedge rst_n) 142 begin 143 if (rst_n == 0) 144 begin 145 fifo_AE <= 1'b0; 146 fifo_AF <= 1'b0; 147 fifo_wr <= 1'b0; 148 rvalid <= 1'b0; 149 read_0 <= 1'b0; 150 ien_AE <= 1'b0; 151 ien_AF <= 1'b0; 152 ac <= 1'b0; 153 woverflow <= 1'b0; 154 av_waitrequest <= 1'b1; 155 end 156 else 157 begin 158 fifo_AE <= {fifo_FF,wfifo_used} <= 8; 159 fifo_AF <= (7'h40 - {rfifo_full,rfifo_used}) <= 8; 160 fifo_wr <= 1'b0; 161 read_0 <= 1'b0; 162 av_waitrequest <= ~(av_chipselect & (~av_write_n | ~av_read_n) & av_waitrequest); 163 if (activity) 164 ac <= 1'b1; 165 // write 166 if (av_chipselect & ~av_write_n & av_waitrequest) 167 // addr 1 is control; addr 0 is data 168 if (av_address) 169 begin 170 ien_AF <= av_writedata[0]; 171 ien_AE <= av_writedata[1]; 172 if (av_writedata[10] & ~activity) 173 ac <= 1'b0; 174 end 175 else 176 begin 177 fifo_wr <= ~fifo_FF; 178 woverflow <= fifo_FF; 179 end 180 // read 181 if (av_chipselect & ~av_read_n & av_waitrequest) 182 begin 183 // addr 1 is interrupt; addr 0 is data 184 if (~av_address) 185 rvalid <= ~fifo_EF; 186 read_0 <= ~av_address; 187 end 188 end 189 end 190 191 192 assign fifo_wdata = av_writedata[7 : 0]; 193 assign fifo_rd = (av_chipselect & ~av_read_n & av_waitrequest & ~av_address) ? ~fifo_EF : 1'b0; 194 assign av_readdata = read_0 ? { {9{1'b0}},rfifo_full,rfifo_used,rvalid,woverflow,~fifo_FF,~fifo_EF,1'b0,ac,ipen_AE,ipen_AF,fifo_rdata } : { {9{1'b0}},(7'h40 - {fifo_FF,wfifo_used}),rvalid,woverflow,~fifo_FF,~fifo_EF,1'b0,ac,ipen_AE,ipen_AF,{6{1'b0}},ien_AE,ien_AF }; 195 196 //synthesis read_comments_as_HDL on 197 // alt_jtag_atlantic jtag_uart_alt_jtag_atlantic 198 // ( 199 // .clk (clk), 200 // .r_dat (r_dat), 201 // .r_ena (r_ena), 202 // .r_val (r_val), 203 // .rst_n (rst_n), 204 // .t_dat (t_dat), 205 // .t_dav (t_dav), 206 // .t_ena (t_ena), 207 // .t_pause (t_pause) 208 // ); 209 // 210 // defparam jtag_uart_alt_jtag_atlantic.INSTANCE_ID = 0, 211 // jtag_uart_alt_jtag_atlantic.LOG2_RXFIFO_DEPTH = 6, 212 // jtag_uart_alt_jtag_atlantic.LOG2_TXFIFO_DEPTH = 6, 213 // jtag_uart_alt_jtag_atlantic.SLD_AUTO_INSTANCE_INDEX = "YES"; 214 // 215 // 216 //synthesis read_comments_as_HDL off 217 218 endmodule 219 220 module wb_jtag_uart_scfifo_w ( 221 // inputs: 222 clk, 223 fifo_clear, 224 fifo_wdata, 225 fifo_wr, 226 rd_wfifo, 227 228 // outputs: 229 fifo_FF, 230 r_dat, 231 wfifo_empty, 232 wfifo_used 233 ); 234 235 output fifo_FF; 236 output [ 7: 0] r_dat; 237 output wfifo_empty; 238 output [ 5: 0] wfifo_used; 239 input clk; 240 input fifo_clear; 241 input [ 7: 0] fifo_wdata; 242 input fifo_wr; 243 input rd_wfifo; 244 245 wire fifo_FF; 246 wire [ 7: 0] r_dat; 247 wire wfifo_empty; 248 wire [ 5: 0] wfifo_used; 249 250 //synthesis read_comments_as_HDL on 251 // scfifo wfifo 252 // ( 253 // .aclr (fifo_clear), 254 // .clock (clk), 255 // .data (fifo_wdata), 256 // .empty (wfifo_empty), 257 // .full (fifo_FF), 258 // .q (r_dat), 259 // .rdreq (rd_wfifo), 260 // .usedw (wfifo_used), 261 // .wrreq (fifo_wr) 262 // ); 263 // 264 // defparam wfifo.lpm_hint = "RAM_BLOCK_TYPE=AUTO", 265 // wfifo.lpm_numwords = 64, 266 // wfifo.lpm_showahead = "OFF", 267 // wfifo.lpm_type = "scfifo", 268 // wfifo.lpm_width = 8, 269 // wfifo.lpm_widthu = 6, 270 // wfifo.overflow_checking = "OFF", 271 // wfifo.underflow_checking = "OFF", 272 // wfifo.use_eab = "ON"; 273 // 274 //synthesis read_comments_as_HDL off 275 276 endmodule 277 278 module wb_jtag_uart_scfifo_r ( 279 // inputs: 280 clk, 281 fifo_clear, 282 fifo_rd, 283 rst_n, 284 t_dat, 285 wr_rfifo, 286 287 // outputs: 288 fifo_EF, 289 fifo_rdata, 290 rfifo_full, 291 rfifo_used 292 ); 293 output fifo_EF; 294 output [ 7: 0] fifo_rdata; 295 output rfifo_full; 296 output [ 5: 0] rfifo_used; 297 input clk; 298 input fifo_clear; 299 input fifo_rd; 300 input rst_n; 301 input [ 7: 0] t_dat; 302 input wr_rfifo; 303 304 wire fifo_EF; 305 wire [ 7: 0] fifo_rdata; 306 wire rfifo_full; 307 wire [ 5: 0] rfifo_used; 308 309 //synthesis read_comments_as_HDL on 310 // scfifo rfifo 311 // ( 312 // .aclr (fifo_clear), 313 // .clock (clk), 314 // .data (t_dat), 315 // .empty (fifo_EF), 316 // .full (rfifo_full), 317 // .q (fifo_rdata), 318 // .rdreq (fifo_rd), 319 // .usedw (rfifo_used), 320 // .wrreq (wr_rfifo) 321 // ); 322 // 323 // defparam rfifo.lpm_hint = "RAM_BLOCK_TYPE=AUTO", 324 // rfifo.lpm_numwords = 64, 325 // rfifo.lpm_showahead = "OFF", 326 // rfifo.lpm_type = "scfifo", 327 // rfifo.lpm_width = 8, 328 // rfifo.lpm_widthu = 6, 329 // rfifo.overflow_checking = "OFF", 330 // rfifo.underflow_checking = "OFF", 331 // rfifo.use_eab = "ON"; 332 // 333 //synthesis read_comments_as_HDL off 334 335 endmodule
关于这个IP核(alt_jtag_atlantic)的寄存器的说明,在Altera的文档中有所说明。其实非常简单,只有两个32位的寄存器。