|
@@ -38,28 +38,36 @@
|
|
|
//
|
|
|
module vjtag_max80
|
|
|
#(
|
|
|
+ parameter sram_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,
|
|
|
+ output reset_cmd,
|
|
|
|
|
|
- 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,
|
|
|
+ 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 reg reset_cmd
|
|
|
- );
|
|
|
+ dram_bus.dstr sdram,
|
|
|
+
|
|
|
+ // SRAM interface
|
|
|
+ output [sram_bits-1:2] sram_addr,
|
|
|
+ input [31:0] sram_rdata,
|
|
|
+ output [31:0] sram_wdata,
|
|
|
+ output sram_read,
|
|
|
+ output sram_write
|
|
|
+ );
|
|
|
|
|
|
wire v_tdi;
|
|
|
- wire v_tdo;
|
|
|
+ reg v_tdo;
|
|
|
wire [4:0] v_ir;
|
|
|
wire v_tck;
|
|
|
wire v_st_cdr;
|
|
@@ -104,17 +112,13 @@ module vjtag_max80
|
|
|
localparam cmd_cpustatus = 4'b1111;
|
|
|
|
|
|
reg jtag_bypass;
|
|
|
- reg [31:0] jtag_shr;
|
|
|
+ wire jtag_out;
|
|
|
reg tdi_s;
|
|
|
+ wire tdo_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;
|
|
|
|
|
|
always @(posedge v_tck)
|
|
|
begin
|
|
@@ -122,20 +126,15 @@ module vjtag_max80
|
|
|
tdi_s <= v_tdi;
|
|
|
ir_cmd <= v_ir[4:1];
|
|
|
ir_ro <= v_ir[0];
|
|
|
- st_cdr_s <= v_st_cdr;
|
|
|
- st_sdr_s <= v_st_sdr;
|
|
|
- st_xdr_s <= v_st_sdr|v_st_e1dr|v_st_e2dr|v_st_pdr;
|
|
|
- st_udr_s <= v_st_udr;
|
|
|
- st_uir_s <= v_st_uir;
|
|
|
end
|
|
|
|
|
|
- assign v_tdo = jtag_bypass ? tdi_s : jtag_shr[0];
|
|
|
+ assign v_tdo = jtag_bypass ? tdi_s : tdo_s;
|
|
|
|
|
|
// Sync incoming JTAG signals. Only tck needs an actual
|
|
|
// synchronizer; the rest just need holding registers (see above)
|
|
|
// as the delay of tck will guarantee the others are stable.
|
|
|
wire tck_s;
|
|
|
- synchronizer #(.width(1)) tck_sync
|
|
|
+ synchronizer #(.width(1), .stages(3)) tck_sync
|
|
|
(
|
|
|
.rst_n ( rst_n ),
|
|
|
.clk ( sys_clk ),
|
|
@@ -144,13 +143,17 @@ module vjtag_max80
|
|
|
);
|
|
|
|
|
|
// Mask of memaddr bits that are not settable: the top bits
|
|
|
- // and the bottom two bits (byte within dword)
|
|
|
- localparam [31:0] memaddr_mask = (1'b1 << sdram_bits) - 3'b100;
|
|
|
+ // and the bottom two bits (byte within dword), and the
|
|
|
+ // sram/dram select bit
|
|
|
+ localparam [31:0] memaddr_mask = ((1'b1 << sdram_bits) - 3'b100)
|
|
|
+ | sdram_base_addr;
|
|
|
|
|
|
function logic [31:0] maskaddr (input [31:0] addr);
|
|
|
- maskaddr = (addr & memaddr_mask) | sdram_base_addr;
|
|
|
+ maskaddr = addr & memaddr_mask;
|
|
|
endfunction
|
|
|
|
|
|
+ wire is_dram = |(mem_addr & sdram_base_addr); // Really just one bit
|
|
|
+
|
|
|
reg jtag_cpu_irq = 1'b0;
|
|
|
reg jtag_cpu_halt = 1'b0;
|
|
|
reg jtag_reset_cmd = 1'b0;
|
|
@@ -168,13 +171,15 @@ module vjtag_max80
|
|
|
reg mem_write;
|
|
|
reg [31:0] mem_addr;
|
|
|
wire [31:0] mem_addr_next = maskaddr(mem_addr + 3'h4);
|
|
|
- wire [31:0] mem_rdata;
|
|
|
+ wire [31:0] sdram_rdata;
|
|
|
reg [31:0] mem_wdata;
|
|
|
- wire mem_ready;
|
|
|
+ wire sdram_ready;
|
|
|
+ reg sram_ready;
|
|
|
reg mem_done;
|
|
|
reg mem_error; // Memory underrun
|
|
|
reg advance_mem_addr;
|
|
|
reg mem_header_done;
|
|
|
+ reg mem_do_write;
|
|
|
|
|
|
reg tck_q;
|
|
|
reg tck_stb;
|
|
@@ -184,14 +189,18 @@ module vjtag_max80
|
|
|
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;
|
|
|
|
|
|
- wire [31:0] jtag_shr_in =
|
|
|
- ir_cmd[3] ? { tdi_s : jtag_shr[31:1] } :
|
|
|
+ // Main data shift register.
|
|
|
+ reg [31:0] jtag_shr;
|
|
|
+ wire [31:0] jtag_shr_in = ir_cmd[3]
|
|
|
+ ? { tdi_s, jtag_shr[31:1] } :
|
|
|
{ 30'bx, tdi_s, jtag_shr[1] };
|
|
|
+ assign tdo_s = jtag_shr[0];
|
|
|
|
|
|
always @(posedge sys_clk)
|
|
|
begin
|
|
@@ -202,22 +211,30 @@ module vjtag_max80
|
|
|
|
|
|
if ( tck_stb )
|
|
|
begin
|
|
|
- if ( st_sdr_s )
|
|
|
+ if ( v_st_sdr )
|
|
|
jtag_shr <= jtag_shr_in;
|
|
|
|
|
|
- if ( st_cdr_s )
|
|
|
+ if ( v_st_cdr )
|
|
|
case ( ir_cmd )
|
|
|
- cmd_halt: jtag_shr[0] <= jtag_cpu_halt;
|
|
|
+ cmd_halt: begin
|
|
|
+ jtag_shr[0] <= jtag_cpu_halt;
|
|
|
+ end
|
|
|
cmd_memerr: begin
|
|
|
jtag_shr[0] <= mem_error;
|
|
|
if ( ~ir_ro ) mem_error <= 1'b0;
|
|
|
end
|
|
|
- cmd_mem0, cmd_memaddr, cmd_memread, cmd_memwrite:
|
|
|
- jtag_shr <= jtag_memaddr;
|
|
|
- cmd_cpucmd, cmd_cpucmd_irq:
|
|
|
- jtag_shr <= jtag_cpucmd;
|
|
|
- cmd_cpuinfo: jtag_shr <= jtag_cpuinfo;
|
|
|
- cmd_cpustatus: jtag_shr <= jtag_cpustatus;
|
|
|
+ cmd_mem0, cmd_memaddr, cmd_memread, cmd_memwrite: begin
|
|
|
+ jtag_shr <= jtag_memaddr;
|
|
|
+ end
|
|
|
+ cmd_cpucmd, cmd_cpucmd_irq: begin
|
|
|
+ jtag_shr <= jtag_cpucmd;
|
|
|
+ end
|
|
|
+ cmd_cpuinfo: begin
|
|
|
+ jtag_shr <= jtag_cpuinfo;
|
|
|
+ end
|
|
|
+ cmd_cpustatus: begin
|
|
|
+ jtag_shr <= jtag_cpustatus;
|
|
|
+ end
|
|
|
default: ;
|
|
|
endcase // case ( ir_cmd )
|
|
|
|
|
@@ -233,24 +250,23 @@ module vjtag_max80
|
|
|
// suppress the update until we know that the user will
|
|
|
// be reading the fetched data.
|
|
|
|
|
|
+ mem_do_write <= 1'b0;
|
|
|
+
|
|
|
if ( ir_cmd[3:1] == cmd_memwr )
|
|
|
begin
|
|
|
- if ( st_cdr_s )
|
|
|
+ if ( v_st_cdr )
|
|
|
begin
|
|
|
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;
|
|
|
+ mem_addr <= jtag_memaddr;
|
|
|
sdr_ctr <= 5'b0;
|
|
|
+ mem_do_write <= 1'b0;
|
|
|
end
|
|
|
|
|
|
- if ( st_sdr_s )
|
|
|
+ if ( v_st_sdr )
|
|
|
begin
|
|
|
sdr_ctr <= sdr_ctr + 1'b1;
|
|
|
|
|
@@ -266,74 +282,91 @@ module vjtag_max80
|
|
|
// Write
|
|
|
if ( jtag_shr_in == VJTAG_WRITE_PREFIX )
|
|
|
mem_header_done <= 1'b1;
|
|
|
- sdr_ctr <= 5'b0;
|
|
|
+ else
|
|
|
+ sdr_ctr <= 5'b0;
|
|
|
end
|
|
|
end
|
|
|
|
|
|
// Memory access underrun?
|
|
|
- if ( &sdr_ctr )
|
|
|
+ if ( sdr_ctr == 5'd31 )
|
|
|
mem_error <= mem_error | mem_valid;
|
|
|
|
|
|
if ( ~mem_write )
|
|
|
- // Read
|
|
|
- case ( sdr_ctr )
|
|
|
- 5'd2: begin
|
|
|
- // For a read, make sure we are committed
|
|
|
- // to reading the new word
|
|
|
- if ( ~ir_ro )
|
|
|
- jtag_memaddr <= mem_addr;
|
|
|
-
|
|
|
- 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
|
|
|
- default: ;
|
|
|
- endcase // case ( sdr_ctr )
|
|
|
+ begin
|
|
|
+ // Read
|
|
|
+ case ( sdr_ctr )
|
|
|
+ 5'd2: begin
|
|
|
+ // For a read, make sure we are committed
|
|
|
+ // to reading the new word
|
|
|
+ if ( ~ir_ro )
|
|
|
+ jtag_memaddr <= mem_addr;
|
|
|
+
|
|
|
+ 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 <= is_dram ? sdram_rdata : sram_rdata;
|
|
|
+ end
|
|
|
+ default: ;
|
|
|
+ endcase // case ( sdr_ctr )
|
|
|
+ end // if ( ~mem_write )
|
|
|
else
|
|
|
- // Write
|
|
|
- if ( &sdr_ctr )
|
|
|
- begin
|
|
|
- mem_wdata <= jtag_shr_in;
|
|
|
- mem_valid <= 1'b1;
|
|
|
- mem_done <= 1'b0;
|
|
|
- advance_mem_addr <= 1'b1;
|
|
|
- if ( ~ir_ro )
|
|
|
- jtag_memaddr <= mem_addr_next;
|
|
|
- end
|
|
|
+ begin
|
|
|
+ // Write
|
|
|
+ mem_do_write <= &sdr_ctr;
|
|
|
+ end // else: !if( ~mem_write )
|
|
|
end // if ( st_sdr_s )
|
|
|
end // if ( ir_cmd[3:1] == cmd_memwr )
|
|
|
-
|
|
|
- if ( st_uir_s )
|
|
|
+
|
|
|
+ if ( mem_do_write )
|
|
|
+ begin
|
|
|
+ mem_wdata <= jtag_shr_in;
|
|
|
+ mem_valid <= 1'b1;
|
|
|
+ mem_done <= 1'b0;
|
|
|
+ advance_mem_addr <= 1'b1;
|
|
|
+ if ( ~ir_ro )
|
|
|
+ jtag_memaddr <= mem_addr_next;
|
|
|
+ end
|
|
|
+
|
|
|
+ if ( v_st_uir )
|
|
|
jtag_cpu_irq <= ir_cmd == cmd_irq;
|
|
|
- else if ( st_udr_s )
|
|
|
+ else if ( v_st_udr )
|
|
|
jtag_cpu_irq <= ir_cmd == cmd_cpucmd_irq;
|
|
|
|
|
|
- if ( st_uir_s )
|
|
|
+ if ( v_st_uir )
|
|
|
jtag_reset_cmd <= jtag_reset_cmd | (ir_cmd == cmd_reset);
|
|
|
|
|
|
- if ( st_udr_s & ~ir_ro )
|
|
|
+ if ( v_st_udr & ~ir_ro )
|
|
|
case ( ir_cmd )
|
|
|
- cmd_halt: jtag_cpu_halt <= jtag_shr[0];
|
|
|
- cmd_memaddr: jtag_memaddr <= maskaddr(jtag_shr);
|
|
|
- cmd_cpucmd, cmd_cpucmd_irq:
|
|
|
- jtag_cpucmd <= jtag_shr;
|
|
|
+ cmd_halt: begin
|
|
|
+ jtag_cpu_halt <= jtag_shr_in[0];
|
|
|
+ end
|
|
|
+ cmd_memaddr: begin
|
|
|
+ jtag_memaddr <= maskaddr(jtag_shr_in);
|
|
|
+ end
|
|
|
+ cmd_cpucmd, cmd_cpucmd_irq: begin
|
|
|
+ jtag_cpucmd <= jtag_shr_in;
|
|
|
+ end
|
|
|
default: /* nothing */ ;
|
|
|
endcase // case ( ir_cmd )
|
|
|
end // if ( tck_stb )
|
|
|
|
|
|
// Increment the temporary address register if applicable,
|
|
|
// but only after the previous transaction is done...
|
|
|
- if ( mem_valid & mem_ready )
|
|
|
+ if ( mem_valid )
|
|
|
begin
|
|
|
- mem_valid <= 1'b0;
|
|
|
- mem_done <= 1'b1;
|
|
|
+ if (is_dram ? sdram_ready : sram_ready)
|
|
|
+ begin
|
|
|
+ mem_valid <= 1'b0;
|
|
|
+ mem_done <= 1'b1;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ sram_ready <= ~is_dram;
|
|
|
end
|
|
|
if ( advance_mem_addr & ~mem_valid )
|
|
|
begin
|
|
@@ -347,15 +380,20 @@ module vjtag_max80
|
|
|
.bus ( sdram ),
|
|
|
.prio ( 2'd2 ),
|
|
|
.addr ( mem_addr ),
|
|
|
- .valid ( mem_valid ),
|
|
|
+ .valid ( mem_valid & is_dram ),
|
|
|
.wd ( mem_wdata ),
|
|
|
.wstrb ( {4{mem_write}} ),
|
|
|
- .ready ( mem_ready ),
|
|
|
- .rd ( mem_rdata )
|
|
|
+ .ready ( sdram_ready ),
|
|
|
+ .rd ( sdram_rdata )
|
|
|
);
|
|
|
|
|
|
+ assign sram_addr = mem_addr[sram_bits-1:2];
|
|
|
+ assign sram_wdata = mem_wdata;
|
|
|
+ assign sram_read = mem_valid & ~is_dram & ~mem_write;
|
|
|
+ assign sram_write = mem_valid & ~is_dram & mem_write;
|
|
|
+
|
|
|
wire [7:0] cpustatus_new =
|
|
|
- ( tck_stb & st_cdr_s & ~ir_ro & (ir_cmd == cmd_cpustatus) )
|
|
|
+ ( tck_stb & v_st_cdr & ~ir_ro & (ir_cmd == cmd_cpustatus) )
|
|
|
? 'b0 : jtag_cpustatus;
|
|
|
|
|
|
always @(negedge rst_n or posedge sys_clk)
|