0% found this document useful (0 votes)
55 views16 pages

Architecture Verilog An Extended Example: Always @ (Posedge CLK) Begin

The document contains a Verilog code example for a RISC processor architecture. It is divided into multiple sections and modules: 1) The code defines modules for the register file, program counter (PC), and main datapath. 2) The register file module models a 32-location register file with two read ports and one write port. 3) The PC module calculates the next PC value based on the current PC, branch offset, and jump address. It outputs the current PC and PC+4. 4) The datapath module interfaces with the other modules, handling operations like ALU, memory access, and register reads and writes. It is the core computational unit of the processor pipeline.

Uploaded by

Sudeep Kh
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
55 views16 pages

Architecture Verilog An Extended Example: Always @ (Posedge CLK) Begin

The document contains a Verilog code example for a RISC processor architecture. It is divided into multiple sections and modules: 1) The code defines modules for the register file, program counter (PC), and main datapath. 2) The register file module models a 32-location register file with two read ports and one write port. 3) The PC module calculates the next PC value based on the current PC, branch offset, and jump address. It outputs the current PC and PC+4. 4) The datapath module interfaces with the other modules, handling operations like ALU, memory access, and register reads and writes. It is the core computational unit of the processor pipeline.

Uploaded by

Sudeep Kh
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 16

Architecture Verilog An Extended Example

always @(posedge clk) begin

ILL JT O dr P XA L4 SE PC 3

1 PC

0 00

on cti tru ry Ins emo M A D

+4

1> 5:2 : <2 EL Rc 2S RA 1> 5:1 0 1 : <1 D EF Rb WR A2 W > R 6 0:1 WE ter : <2 2 gis Ra RD Re ile L F SE RA1 WA A W WA 1 1 RD JT EL XP:21> BS 5 0 + 0 : <2 Rc 1 Wr Z ) :0> R/W C: (<15 0 WD T ry 1 (C) SX mo XT EL Me 4*S ta AS B Da +4+ Z RD PC U Adr IRQ ic AL og A lL tro on L C N SE UF PC SEL AL 2 RA EL AS L E BS SEL L D WD FN W SE +4 U PC 2 AL r 01 W RF WE EL AS W

assign pcinc = pc + 4; for (i=0; i < 31; i = i+1) begin

6.371 Fall 2002

09/11/02

Inpu

:0] m t [31

en dm

od ul e

; data em_

If (done) $finish;

mo du l eb eta ( clk ,re se t,ir q,

L03 More Verilog 1

Reprise: Why use an HDL?


Want an executable functional specification
Document exact behavior of all the modules and their interfaces Executable models can be tested & refined until they do what you want

Too much detail at the transistor and mask levels


Cant debug 1M transistors as individual analog components Abstract away unnecessary details Play by the rules: dont break abstraction with clever hacks

HDL description is first step in a mostly automated process to build an implementation directly from the behavioral model
Gate netlist

Verilog

Logic Synthesis
HDL logic map to target library optimize speed, area

Place & route


create floorplan blocks place cells in block route interconnect optimize (iterate!)

Mask

6.371 Fall 2002

09/11/02

L03 More Verilog 2

Beta redux!
ILL XAdr OP

JT
2 1 0

I thought I already did 6.004


00

PCSEL

PC

Instruction Memory
D

+4

Ra: <20:16>

Rb: <15:11>
0 1

Rc: <25:21>
RA2SEL

+
XP

WASEL 1

RA1 WA WA RD1

Rc: <25:21> 0
Z

Register File
JT

RA2 WD RD2 WE WERF

PC+4+4*SXT(C) IRQ Z

C: SXT(<15:0>)

ASEL

BSEL

Control Logic
PCSEL RA2SEL ASEL BSEL WDSEL ALUFN Wr WERF WASEL

A ALUFN

ALU

B WD R/W

Wr

Data Memory
Adr RD

PC+4
0 1 2

WDSEL

6.371 Fall 2002

09/11/02

L03 More Verilog 3

Goals for the Verilog description


Readable, correct code that clearly captures the architecture diagram correct by inspection Partition the design into regions appropriate for different implementation strategies. Big issue: wires are bad since they take up area and have capacitance (impacting speed and power).
Memories: very dense layouts, structured wires pretty much route themselves, just a few base cells to design & verify Datapaths: each cell contains necessary wiring, so replicating cells (for N bits of datapath) also replicates wiring. Data flows between columnar functional units on horizontal busses and control flows vertically. Random logic: interconnect is random but library of cells can be designed ahead of time and characterized. Think about physical partition: wires that cross boundaries can take lots of area; blocks have to fit into the floorplan without wasteful gaps. Themes: draw as few fets as possible; maximize use of design techniques that offer good wire management strategies; use special tools for each type of layout
6.371 Fall 2002 09/11/02 L03 More Verilog 4

Hey! What happened to abstraction?


Wasnt the plan to abstractaway the physical details so we could concentrate on getting the functionality right? Why are we worrying about wires and floorplans at this stage? Because life is short! If you have the luxury of writing two models (the first to experiment with function, the second to describe the actual partition you want to have), by all means! But with a little experience you can tackle both problems at once.

6.371 Fall 2002

09/11/02

L03 More Verilog 5

Helping the Tools*


In an ideal world it shouldnt matter how you write the Verilog optimization in the CAD tools will find the best solution. But the world is not ideal (yet) Tools work best on smaller problems Need to partition real problem into pieces for you and the tools (its hard to think about 1M gates at one time). Decompose large problems into smaller problems and then connect the solutions Hierarchy in Verilog partitions in physical layout Tools use your code as a starting point. Your structure isnt completed eliminated (this is good) Little optimization will be done between top-level blocks Structure of the problem is often important Finding a good way to think about the problem is key Like optimizing compilers for C, tools are good for local optimizations but dont expect them to rewrite your code and change your algorithm. With practice youll learn what works and what doesnt
*adapted from a Stanford EE271 lecture by Mark Horowitz 6.371 Fall 2002 09/11/02 L03 More Verilog 6

Divide and conquer


ILL XAdr OP

JT
2 1 0

PCSEL

1
A

PC

00

Instruction Memory
D

Step 1: identify memories Step 2: identify datapaths Whats left is random logic
Ra: <20:16> Rb: <15:11>
0 WASEL 1

+4

Rc: <25:21>
RA2SEL

2 PC

+
XP

Rc: <25:21> 0
Z

RA1 WA WA RD1

Register File
JT

RA2 WD RD2 WE

1
WERF

PC+4+4*SXT(C) IRQ Z

C: SXT(<15:0>)

ASEL

BSEL

Control Logic
PCSEL RA2SEL ASEL BSEL WDSEL ALUFN Wr WERF WASEL

A ALUFN

ALU

B WD R/W

Wr

Data Memory
Adr RD

PC+4

1
0 1 2

Main Datapath
6.371 Fall 2002

2
09/11/02

WDSEL

L03 More Verilog 7

Choosing the right style


Structural Verilog
Use for hierarchy (instantiating other modules) Floorplanning tools often require that modules which include structural verilog not include other styles. In other words the leafs of the hierarchy are dataflow/behavioral modules, all other modules are pure structural verilog.

Dataflow Verilog: assign target = expression


Use for (most) combinational logic Avoids problems with activation list omissions These two styles are often mixed in a single module

Behavioral Verilog: always @() begin end

Use to model state elements (e.g., registers) Sometimes useful for combinational logic expressed using for or case statements Simulates much faster than dataflow statements since no waveforms are produced for signals internal to behavioral block. Heres where you can make the tradeoff between simulation speed and debugability.
6.371 Fall 2002 09/11/02

L03 More Verilog 8

Beta Module Hierarchy


beta control regfile pc datapath dp_misc dp_alu dp_addsub dp_boole dp_shift dp_cmp dp_mux dp_wdata [random logic] [memory] [datapath] [datapath] [datapath] [datapath] [datapath] [datapath] [datapath] [datapath]

Beta verilog can be found in /mit/6.371/examples/beta.vl or Handouts webpage Beta verilog can be found in /mit/6.371/examples/beta.vl or Handouts webpage
6.371 Fall 2002 09/11/02 L03 More Verilog 9

Register File
// 2-read, 1-write 32-location register file module regfile(ra1,rd1,ra2,rd2,clk,werf,wa,wd); input [4:0] ra1; // address for read port 1 (Reg[RA]) output [31:0] rd1; // read data for port 1 input [4:0] ra2; // address for read port 2 (Reg[RB], Reg[RC] for ST) output [31:0] rd2; // read data for port 2 input clk; input werf; // write enable, active high input [4:0] wa; // address for write port (Reg[RC]) input [31:0] wd; // write data reg [31:0] registers[31:0]; // the register file itself (local)

// read paths are combinational // logic to ensure R31 reads as zero is in main datapath assign rd1 = registers[ra1]; assign rd2 = registers[ra2]; // write port is active only when WERF is asserted always @(posedge clk) if (werf) registers[wa] <= wd; endmodule

6.371 Fall 2002

09/11/02

L03 More Verilog 10

= vs. <= inside begin end


A
module main; reg a,b,clk; always @(posedge clk) begin always @(posedge clk) begin aa == b; b; // blocking assignment // blocking assignment bb == a; // execute sequentially a; // execute sequentially end end always @(posedge clk) begin always @(posedge clk) begin aa <= b; // non-blocking assignment <= b; // non-blocking assignment bb <= a; // eval all RHSs first <= a; // eval all RHSs first end end always @(posedge clk) aa == b; always @(posedge clk) b; always @(posedge clk) bb == a; always @(posedge clk) a; always @(posedge clk) aa <= b; always @(posedge clk) <= b; always @(posedge clk) bb <= a; always @(posedge clk) <= a; always @(posedge clk) begin always @(posedge clk) begin aa <= b; <= b; bb == a; a; // urk! Be consistent! // urk! Be consistent! end end

C
initial begin clk = 0; a = 0; b = 1; D #10 clk = 1; #10 $display("a=%d b=%d\n",a,b); $finish; E end endmodule

Rule: always change state using <= (e.g., inside always @(posedge clk))) Rule: always change state using <= (e.g., inside always @(posedge clk)
6.371 Fall 2002 09/11/02 L03 More Verilog 11

module pc(clk,reset,pcsel,offset,jump_addr, branch_addr,pc,pc_plus_4); input clk; input reset; // forces PC to 0x80000000 input [2:0] pcsel; // selects source of next PC input [15:0] offset; // inst[15:0] input [31:0] jump_addr; // from Reg[RA], used in JMP instruction output [31:0] branch_addr; // send to datapath for LDR instruction output [31:0] pc; // used as address for instruction fetch output [31:0] pc_plus_4; // saved in regfile during branches, JMP, traps

PC

reg [31:0] pc; wire [30:0] pcinc; wire [31:0] npc; // the Beta PC increments by 4, but wont change supervisor bit assign pcinc = pc + 4; assign pc_plus_4 = {pc[31],pcinc}; // branch address = PC + 4 + 4*sxt(offset) assign branch_addr = {0,pcinc + {{13{offset[15]}},offset[15:0],2'b00}}; assign npc = reset ? 32'h80000000 : (pcsel == 0) ? {pc[31],pcinc} : // normal (pcsel == 1) ? {pc[31],branch_addr[30:0]} : // branch (pcsel == 2) ? {pc[31] & jump_addr[31],jump_addr[30:0]} : // jump (pcsel == 3) ? 32'h80000004 : 32'h80000008; // illop, trap // pc register, pc[31] is supervisor bit and gets special treatment always @(posedge clk) pc <= npc; endmodule
09/11/02

6.371 Fall 2002

L03 More Verilog 12

module datapath(inst,rd1,rd2,pc_plus_4,branch_addr,mem_data, rd1zero,rd2zero,asel,bsel,wdsel,alufn, wdata,mem_addr,mem_wdata,z); input [15:0] inst; // constant field from instruction input [31:0] rd1; // Reg[RA] from register file input [31:0] rd2; // Reg[RB] from register file (Reg[RC] for ST) input [31:0] pc_plus_4; // incremented PC input [31:0] branch_addr; // PC + 4 + 4*sxt(inst[15:0]) input [31:0] mem_data; // memory read data (for LD) input rd1zero; // RA == R31, so treat RD1 as 0 input rd2zero; // RB/RC == R31, so treat RD2 as 0 input asel; // select A operand for ALU input bsel; // select B operand for ALU input [1:0] wdsel; // select regfile write data input [5:0] alufn; // operation to be performed by alu output [31:0] wdata; // regfile write data (output of WDSEL mux) output [31:0] mem_addr; // alu output, doubles as data memory address output [31:0] mem_wdata; // data memory write data output z; // true if Reg[RA] is zero, used during branches wire [31:0] alu_a,alu_b; // A and B inputs to ALU

Main Datapath

// compute A and B inputs into alu, also Z bit for control logic dp_misc misc(rd1zero,rd2zero,asel,bsel,inst,rd1,rd2,branch_addr, alu_a,alu_b,mem_wdata,z); // where all the heavy-lifting happens dp_alu alu(alufn,alu_a,alu_b,mem_addr); // select regfile write data from PC+4, alu output, and memory data dp_wdata wdata(wdsel,mem_data,mem_addr,pc_plus_4,wdata); endmodule
6.371 Fall 2002 09/11/02 L03 More Verilog 13

module dp_addsub(fn,alu_a,alu_b,result,n,v,z); input fn; // 0 for add, 1 for subtract input [31:0] alu_a; // A operand input [31:0] alu_b; // B operand output [31:0] result; // result output n,v,z; // condition codes computed from result reg n,v,z; reg [31:0] result;

Adder

Whats wrong with: Whats wrong with: assign result == fn ?? aa bb :: aa ++ b; assign result fn b;

always @(fn or alu_a or alu_b) begin: ripple integer i; // FOR loop index, not in hardware reg cin,p,g; // expanded at compile time into many signals reg [31:0] xb; // hold's complement of ALU_B during subtract // simple ripple-carry adder for now xb = fn ? ~alu_b : alu_b; // a - b == a + ~b + 1 cin = fn; // carry-in is 0 for add, 1 for sub // remember: this FOR is expanded at *compile* time for (i = 0; i < 32; i = i + 1) begin p = alu_a[i] ^ xb[i]; // carry propagate g = alu_a[i] & xb[i]; // carry generate result[i] = p ^ cin; cin = g | (p & cin); // carry into next stage end n = result[31]; // negative z = ~|result; // zero v = (alu_a[31] & xb[31] & !n) | (~alu_a[31] & ~xb[31] & n); end endmodule
6.371 Fall 2002 09/11/02

// overflow

L03 More Verilog 14

reg [17:0] ctl; // local always @(inst or interrupt) begin if (interrupt) ctl = 16'b0100100000000000; else case (inst[31:26]) // ppp aaaaaaww // bcccw lllllldd // tsssaabuuuuuuss // eeeesssffffffeex // sllleeennnnnnllw // t210lll54321010r default: ctl = 16'b0011100000000000; 6'b011000: ctl = 16'b0000001000000100; 6'b011001: ctl = 16'b0000001000000101; 6'b011011: ctl = 16'b0010000000000000; 6'b111101: ctl = 16'b0000001100001010; 6'b111110: ctl = 16'b0000001100011010; endcase end assign assign assign assign assign assign assign assign

// control rom // interrupt

Instruction decode (fragment)

// // // //

illegal opcode LD ST JMP

// SHRC // SRAC

werf = ~ctl[0]; mem_we = !reset & ctl[0]; wdsel = ctl[2:1]; alufn = ctl[8:3]; bsel = ctl[9]; asel = ctl[10]; wa = ctl[11] ? 5'b11110 : inst[25:21]; pcsel = ((ctl[14:12] == 3'b001) & (ctl[15] ^ z)) ? 3'b000 : ctl[14:12];
09/11/02 L03 More Verilog 15

6.371 Fall 2002

module main; reg clk,reset,irq; wire [31:0] inst_addr,inst_data; wire [31:0] mem_addr,mem_rd_data,mem_wr_data; wire mem_we; reg [31:0] memory[1023:0]; beta beta(clk,reset,irq,inst_addr,inst_data, mem_addr,mem_rd_data,mem_we,mem_wr_data); // main memory (2 async read ports, 1 sync write port) assign inst_data = memory[inst_addr[13:2]]; assign mem_rd_data = memory[mem_addr[13:2]]; always @(posedge clk) if (mem_we) memory[mem_addr[13:2]] <= mem_wr_data; always #5 clk = ~clk; initial begin $dumpfile("beta_checkoff.vcd"); $dumpvars; $readmemh("beta_checkoff",memory); clk = 0; irq = 0; reset = 1; #10 reset = 0; #3000 // 300 cycles $finish; end endmodule
6.371 Fall 2002 09/11/02

Test Jig

About 20 megabytes for 300 cycles! @0 // starting address @0 // starting address 77df000a 77df000a 77ff0003 77ff0003 6ffe0000 6ffe0000 c3e00000 c3e00000 77fffffe 77fffffe d01e0004 d01e0004 77e00002 77e00002
L03 More Verilog 16

You might also like