|
@@ -18,7 +18,9 @@
|
|
|
//
|
|
|
// 1001x - address register (only bits [24:2] settable)
|
|
|
// 1010x - read data from memory
|
|
|
+// returns address before streaming 32-bit data words
|
|
|
// 1011x - write data to memory
|
|
|
+// send VJTAG_WRITE_PREFIX before streaming 32-bit data words
|
|
|
// 1100x - command register to CPU
|
|
|
// 1101x - command register to CPU, trigger IRQ on update_DR
|
|
|
// 1110x - info register from CPU
|
|
@@ -34,40 +36,41 @@
|
|
|
// 2 - CPU status register (rw)
|
|
|
// 3 - CPU status register set bits (rw1)
|
|
|
//
|
|
|
-module vjtag_max80
|
|
|
+module vjtag_max80
|
|
|
#(
|
|
|
- parameter [31:0] sdram_base_addr,
|
|
|
- parameter sdram_bits
|
|
|
+ parameter [31:0] sdram_base_addr,
|
|
|
+ parameter sdram_bits,
|
|
|
+ parameter [31:0] VJTAG_WRITE_PREFIX = 32'hABC80FED
|
|
|
) (
|
|
|
- input rst_n,
|
|
|
- input sys_clk,
|
|
|
-
|
|
|
+ input rst_n,
|
|
|
+ input sys_clk,
|
|
|
+
|
|
|
dram_bus.dstr sdram,
|
|
|
|
|
|
- input cpu_valid,
|
|
|
+ input cpu_valid,
|
|
|
input [6:2] cpu_addr,
|
|
|
input [31:0] cpu_wdata,
|
|
|
input [ 3:0] cpu_wstrb,
|
|
|
output [31:0] cpu_rdata,
|
|
|
- output cpu_irq,
|
|
|
- output cpu_halt,
|
|
|
+ output cpu_irq,
|
|
|
+ output cpu_halt,
|
|
|
|
|
|
- output reg reset_cmd
|
|
|
+ output reg reset_cmd
|
|
|
);
|
|
|
|
|
|
- wire v_tdi;
|
|
|
+ wire v_tdi;
|
|
|
wire v_tdo;
|
|
|
- wire [4:0] v_ir;
|
|
|
- wire v_tck;
|
|
|
- wire v_st_cdr;
|
|
|
- wire v_st_sdr;
|
|
|
- wire v_st_e1dr;
|
|
|
- wire v_st_pdr;
|
|
|
- wire v_st_e2dr;
|
|
|
- wire v_st_udr;
|
|
|
- wire v_st_cir;
|
|
|
- wire v_st_uir;
|
|
|
-
|
|
|
+ wire [4:0] v_ir;
|
|
|
+ wire v_tck;
|
|
|
+ wire v_st_cdr;
|
|
|
+ wire v_st_sdr;
|
|
|
+ wire v_st_e1dr;
|
|
|
+ wire v_st_pdr;
|
|
|
+ wire v_st_e2dr;
|
|
|
+ wire v_st_udr;
|
|
|
+ wire v_st_cir;
|
|
|
+ wire v_st_uir;
|
|
|
+
|
|
|
vjtag vjtag (
|
|
|
.tdi ( v_tdi ),
|
|
|
.tdo ( v_tdo ),
|
|
@@ -100,19 +103,19 @@ module vjtag_max80
|
|
|
localparam cmd_cpuinfo = 4'b1110;
|
|
|
localparam cmd_cpustatus = 4'b1111;
|
|
|
|
|
|
- reg jtag_bypass;
|
|
|
+ reg jtag_bypass;
|
|
|
reg [31:0] jtag_shr;
|
|
|
reg tdi_s;
|
|
|
|
|
|
// Latched information for use in the synchronous state machine
|
|
|
reg [3:0] ir_cmd; // Command part of IR
|
|
|
- reg ir_ro; // Readonly (update suppress)
|
|
|
- reg st_cdr_s;
|
|
|
- reg st_sdr_s;
|
|
|
- reg st_xdr_s; // Any state between CDR and UDR, exclusively
|
|
|
- reg st_udr_s;
|
|
|
- reg st_uir_s;
|
|
|
-
|
|
|
+ reg ir_ro; // Readonly (update suppress)
|
|
|
+ reg st_cdr_s;
|
|
|
+ reg st_sdr_s;
|
|
|
+ reg st_xdr_s; // Any state between CDR and UDR, exclusively
|
|
|
+ reg st_udr_s;
|
|
|
+ reg st_uir_s;
|
|
|
+
|
|
|
always @(posedge v_tck)
|
|
|
begin
|
|
|
jtag_bypass <= v_ir == cmd_bypass;
|
|
@@ -147,10 +150,10 @@ module vjtag_max80
|
|
|
function logic [31:0] maskaddr (input [31:0] addr);
|
|
|
maskaddr = (addr & memaddr_mask) | sdram_base_addr;
|
|
|
endfunction
|
|
|
-
|
|
|
- reg jtag_cpu_irq = 1'b0;
|
|
|
- reg jtag_cpu_halt = 1'b0;
|
|
|
- reg jtag_reset_cmd = 1'b0;
|
|
|
+
|
|
|
+ reg jtag_cpu_irq = 1'b0;
|
|
|
+ reg jtag_cpu_halt = 1'b0;
|
|
|
+ reg jtag_reset_cmd = 1'b0;
|
|
|
|
|
|
assign cpu_irq = jtag_cpu_irq;
|
|
|
assign cpu_halt = jtag_cpu_halt;
|
|
@@ -161,34 +164,36 @@ module vjtag_max80
|
|
|
reg [31:0] jtag_cpuinfo;
|
|
|
reg [ 7:0] jtag_cpustatus;
|
|
|
|
|
|
- reg mem_valid;
|
|
|
+ reg mem_valid;
|
|
|
reg mem_write;
|
|
|
reg [31:0] mem_addr;
|
|
|
wire [31:0] mem_addr_next = maskaddr(mem_addr + 3'h4);
|
|
|
wire [31:0] mem_rdata;
|
|
|
reg [31:0] mem_wdata;
|
|
|
wire mem_ready;
|
|
|
- reg mem_done;
|
|
|
- reg mem_error; // Memory underrun
|
|
|
+ reg mem_done;
|
|
|
+ reg mem_error; // Memory underrun
|
|
|
+ reg advance_mem_addr;
|
|
|
+ reg mem_header_done;
|
|
|
|
|
|
- reg tck_q;
|
|
|
- reg tck_stb;
|
|
|
+ reg tck_q;
|
|
|
+ reg tck_stb;
|
|
|
always @(posedge sys_clk)
|
|
|
begin
|
|
|
tck_q <= tck_s;
|
|
|
tck_stb <= tck_s & ~tck_q;
|
|
|
end
|
|
|
-
|
|
|
+
|
|
|
// Keep a counter to keep track of SDRAM data bit count; this is to
|
|
|
// allow streaming of data to/from SDRAM without leaving the
|
|
|
// SDR state.
|
|
|
reg [4:0] sdr_ctr;
|
|
|
-
|
|
|
+
|
|
|
always @(posedge sys_clk)
|
|
|
begin
|
|
|
if ( ~rst_n )
|
|
|
jtag_reset_cmd <= 1'b0;
|
|
|
-
|
|
|
+
|
|
|
jtag_cpu_irq <= 1'b0;
|
|
|
|
|
|
if ( tck_stb )
|
|
@@ -200,7 +205,7 @@ module vjtag_max80
|
|
|
else
|
|
|
jtag_shr <= { 30'bx, tdi_s, jtag_shr[1] };
|
|
|
end
|
|
|
-
|
|
|
+
|
|
|
if ( st_cdr_s )
|
|
|
case ( ir_cmd )
|
|
|
cmd_halt: jtag_shr[0] <= jtag_cpu_halt;
|
|
@@ -216,7 +221,7 @@ module vjtag_max80
|
|
|
cmd_cpustatus: jtag_shr <= jtag_cpustatus;
|
|
|
default: ;
|
|
|
endcase // case ( ir_cmd )
|
|
|
-
|
|
|
+
|
|
|
// For performance, the SDRAM data can be streamed
|
|
|
// without exiting the shift_DR state, so this is
|
|
|
// based on a counter rather than going to the DR_update
|
|
@@ -236,38 +241,57 @@ module vjtag_max80
|
|
|
mem_done <= 1'b0;
|
|
|
mem_valid <= 1'b0;
|
|
|
mem_write <= ir_cmd[0];
|
|
|
+ advance_mem_addr <= 1'b0;
|
|
|
+ mem_addr <= jtag_memaddr;
|
|
|
end
|
|
|
|
|
|
if ( ~st_xdr_s )
|
|
|
begin
|
|
|
+ mem_header_done <= 1'b0;
|
|
|
sdr_ctr <= 5'b0;
|
|
|
- mem_addr <= jtag_memaddr;
|
|
|
end
|
|
|
|
|
|
- if ( st_sdr_s )
|
|
|
+ if ( st_sdr_s | st_udr_s )
|
|
|
begin
|
|
|
sdr_ctr <= sdr_ctr + 1'b1;
|
|
|
|
|
|
- // Applicable to both read and write
|
|
|
- case ( sdr_ctr )
|
|
|
- 5'd31: begin
|
|
|
- if ( mem_valid )
|
|
|
- mem_error <= 1'b1; // Underrun!
|
|
|
+ if ( ~mem_header_done )
|
|
|
+ begin
|
|
|
+ if ( ~mem_write )
|
|
|
+ begin
|
|
|
+ // Read
|
|
|
+ mem_header_done <= &sdr_ctr;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ // Write
|
|
|
+ if ( jtag_shr == VJTAG_WRITE_PREFIX )
|
|
|
+ mem_header_done <= 1'b1;
|
|
|
+ sdr_ctr <= 5'b0;
|
|
|
+ end
|
|
|
end
|
|
|
- default: ;
|
|
|
- endcase // case ( sdr_ctr )
|
|
|
+
|
|
|
+ // Memory access underrun?
|
|
|
+ if ( &sdr_ctr )
|
|
|
+ mem_error <= mem_error | mem_valid;
|
|
|
|
|
|
if ( ~mem_write )
|
|
|
// Read
|
|
|
case ( sdr_ctr )
|
|
|
- 5'd1: begin
|
|
|
+ 5'd2: begin
|
|
|
// For a read, make sure we are committed
|
|
|
// to reading the new word
|
|
|
if ( ~ir_ro )
|
|
|
jtag_memaddr <= mem_addr;
|
|
|
- mem_valid <= 1'b1;
|
|
|
- mem_done <= 1'b0;
|
|
|
+
|
|
|
+ advance_mem_addr <= mem_header_done;
|
|
|
end
|
|
|
+ 5'd3:
|
|
|
+ begin
|
|
|
+ // After mem_addr advanced
|
|
|
+ mem_valid <= 1'b1;
|
|
|
+ mem_done <= 1'b0;
|
|
|
+ end
|
|
|
5'd31: begin
|
|
|
jtag_shr <= mem_rdata;
|
|
|
end
|
|
@@ -275,16 +299,15 @@ module vjtag_max80
|
|
|
endcase // case ( sdr_ctr )
|
|
|
else
|
|
|
// Write
|
|
|
- case ( sdr_ctr )
|
|
|
- 5'd31: begin
|
|
|
+ if ( &sdr_ctr )
|
|
|
+ begin
|
|
|
mem_wdata <= jtag_shr;
|
|
|
mem_valid <= 1'b1;
|
|
|
mem_done <= 1'b0;
|
|
|
+ advance_mem_addr <= 1'b1;
|
|
|
if ( ~ir_ro )
|
|
|
jtag_memaddr <= mem_addr_next;
|
|
|
end
|
|
|
- default: ;
|
|
|
- endcase // case ( sdr_ctr )
|
|
|
end // if ( st_sdr_s )
|
|
|
end // if ( ir_cmd[3:1] == cmd_memwr )
|
|
|
|
|
@@ -295,7 +318,7 @@ module vjtag_max80
|
|
|
|
|
|
if ( st_uir_s )
|
|
|
jtag_reset_cmd <= jtag_reset_cmd | (ir_cmd == cmd_reset);
|
|
|
-
|
|
|
+
|
|
|
if ( st_udr_s & ~ir_ro )
|
|
|
case ( ir_cmd )
|
|
|
cmd_halt: jtag_cpu_halt <= jtag_shr[0];
|
|
@@ -312,10 +335,14 @@ module vjtag_max80
|
|
|
begin
|
|
|
mem_valid <= 1'b0;
|
|
|
mem_done <= 1'b1;
|
|
|
- mem_addr <= mem_addr_next;
|
|
|
+ end
|
|
|
+ if ( advance_mem_addr & ~mem_valid )
|
|
|
+ begin
|
|
|
+ mem_addr <= mem_addr_next;
|
|
|
+ advance_mem_addr <= 1'b0;
|
|
|
end
|
|
|
end
|
|
|
-
|
|
|
+
|
|
|
dram_port #(32) mem
|
|
|
(
|
|
|
.bus ( sdram ),
|
|
@@ -331,7 +358,7 @@ module vjtag_max80
|
|
|
wire [7:0] cpustatus_new =
|
|
|
( tck_stb & st_cdr_s & ~ir_ro & (ir_cmd == cmd_cpustatus) )
|
|
|
? 'b0 : jtag_cpustatus;
|
|
|
-
|
|
|
+
|
|
|
always @(negedge rst_n or posedge sys_clk)
|
|
|
if (~rst_n)
|
|
|
begin
|
|
@@ -341,7 +368,7 @@ module vjtag_max80
|
|
|
else
|
|
|
begin
|
|
|
jtag_cpustatus <= cpustatus_new;
|
|
|
-
|
|
|
+
|
|
|
if ( cpu_valid )
|
|
|
begin
|
|
|
case ( cpu_addr )
|
|
@@ -363,7 +390,7 @@ module vjtag_max80
|
|
|
endcase // case ( cpu_addr[1:0] )
|
|
|
end // if ( cpu_valid )
|
|
|
end
|
|
|
-
|
|
|
+
|
|
|
always @(*)
|
|
|
casez ( cpu_addr )
|
|
|
5'b00000: cpu_rdata = jtag_cpucmd;
|