Programmable Control Logic • Microsequencers • Example: building the micro8 • Hardware/Software tradeoff 6.111 Fall 2009 1 Lecture 13 Lab #5 due Thursday, project abstract next Monday Digital Systems = FSMs + Datapath FSM Datapath: data regs memories muxes ALUs control status But what if my FSM has hundreds or thousands of states? That’s a BIG case statement! 6.111 Fall 2009 2 Lecture 13 Microsequencers Program Counter ROM or Logic +1 Control Signals Step 1: use a counter for the state Program Counter ROM or Logic +1 Control Signals Step 2: add a conditional branch mechanism f status Branch destination Branch condition 6.111 Fall 2009 3 Lecture 13 Microsequencers (cont’d.) Program Counter ROM or Logic +1 Control Signals Step 3: add a (small) call/return stack to support “subroutines” f status Call/Branch destination Opcode: Call/Return/Branch condition stack push pop Subroutine call: select destination as new PC, push PC+1 onto stack Subroutine return: select top of stack as new PC, pop stack 6.111 Fall 2009 4 Lecture 13Xilinx PicoBlaze™ • 8-bit data path • internal memory - 1K 18-bit insts - 31-locn stack - 16 8-bit registers - 64-locn local mem • external 8-bit ports - 256 in, 256 out • small: only 96 slices + inst mem • fast: 2 cycles/inst [IF!EXE] 200MHz (100MIPS) on labkit 6.111 Fall 2009 5 Lecture 13 PicoBlaze Instructions Conditional and unconditional flow of control Access to external devices 8-bit ALU: <r1> <op>= <r2> <r1> <op>= const Access to 64-locn local mem Interrupt management 6.111 Fall 2009 6 Lecture 13 Example: building the micro8 • Let’s build a PicoBlaze-compatible clone using standard Verilog (the Xilinx implementation is a netlist of Xilinx CLB macros). • Approach: incremental featurism – Go through instruction set adding datapath elements and control logic necessary for each instruction – Goal: see how close we can come to 96 slices and 100MHz… 6.111 Fall 2009 7 Lecture 13 Preliminaries • Instruction formats: 18-bits w/ 5-bit opcode – ooooo ccc aaaaaaaaaa condition, 10-bit address – ooooo 1 xxxx yyyy 0000 two registers ( R[x] = R[x] op R[y]) – ooooo 0 xxxx kkkkkkkk register, 8-bit const (R[x] = R[x] op k) • So – Dispatch on opcode of current inst., i.e., case (inst[17:13]) to determine what control signals should be – Use a three port register file • 16 locations => 4-bit addresses • 2 combinational read ports, addresses of xxxx and yyyy • 1 clocked write port written at end of cycles (use xxxx as addr) • Make each instruction execute in one clock cycle – Instruction latched every "clk, state changes (eg, register writes, status bits) latched at next "clk – Start fetch of next instruction from BRAM on #clk, so instruction data available at "clk 6.111 Fall 2009 8 Lecture 13Initial Verilog template module micro8( input wire clk,reset,interrupt, input wire [17:0] instruction, input wire in_port[7:0], output wire [7:0] address, output wire [7:0] port_id,out_port, output wire read_strobe,writestrobe, output wire interrupt_ack ); reg [17:0] inst; always @(posedge clk) inst <= instruction; // datapath elements here… // control logic always @* begin // default ctl sig values here… … if (reset) … else (irq) … else case (inst[17:13]) … endcase end endmodule 6.111 Fall 2009 9 Lecture 13 Sequential Instruction Fetch • The program counter (PC) register holds the address of the current instruction • Usually the next instruction comes from location PC+1 in the instruction memory (ie, the next instruction in the sequence) // address of current instruction reg [9:0] pc; wire [9:0] pc_inc = pc + 1; // multiplexer for selecting address // of next inst reg [1:0] pcsel; localparam pc_next = 2'b00; … always @* case (pcsel) pc_next: address = pc_inc; default: address = 10'hxxx; endcase always @(posedge clk) pc <= address; // control logic always @* begin // default ctl sig values here pcsel = pc_next; … end 6.111 Fall 2009 10 Lecture 13 JUMP: transfer of control • JUMP chooses another instruction as the next to be executed – Unconditional jumps always transfer control – Conditional jumps transfer only if condition is true, otherwise have no effect – Conditions Z, ~Z, C, ~C // address of current instruction reg [9:0] pc; wire [9:0] pc_inc = pc + 1; // multiplexer for selecting address // of next inst reg [1:0] pcsel; localparam pc_next = 2'b00; localparam pc_aaa = 2’b01; … always @* case (pcsel) pc_next: address = pc_inc; pc_aaa: address = inst[9:0]; default: address = 10'hxxx; endcase always @(posedge clk) pc <= address; reg cond; // true if we should branch always @* casez (inst[12:10]) 3’b0??: cond = 1b’1; 3’b100: cond = z; 3’b101: cond = ~z; 3’b110: cond = c; 3’b111: cond = ~c; default: cond = 1’bx; endcase // control logic always @* begin // default ctl sig values pcsel = pc_next; … case (inst[17:13]) … 5'b11010: // JUMP if (cond) pcsel = pc_aaa; … endcase end 6.111 Fall 2009 11 Lecture 13 PC Stack for subroutines • CALL: if (cond) pushes PC+1 onto PC stack, jumps to aaa • RETURN: if (cond) jumps to addr @ top of stack, pops stack // 31 location PC stack (* ram_style = "distributed" *) reg [9:0] stack[31:0]; // the stack itself reg [4:0] sp,sp_inc; // sp points to top of stack reg [1:0] stsel; localparam st_nop = 2'b00; localparam st_push = 2'b01; localparam st_pop = 2'b10; always @* // select increment to sp this cycle case (stsel) st_nop: sp_inc = 5'h00; st_push: sp_inc = 5'h01; st_pop: sp_inc = 5'h1F; default: sp_inc = 5'hxx; endcase wire [4:0] sp_next = sp + sp_inc; always @(posedge clk) begin sp <= reset ? 5'h00 : sp_next; if (stsel == st_push) stack[sp_next] <= pc_inc; end wire [9:0] tos = stack[sp]; // async read of top of PC stack 6.111 Fall 2009 12 Lecture
View Full Document