PolyPoint and the First Steps Towards Ubiquitous Localization
CSE 141L: Introduction to Computer Architecture Lab
SystemVerilog II
Copyright By PowCoder代写 加微信 powcoder
Pat Pannuto, UC San SE 141L
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Milestone 1 is due in 48 hours [before class Wed]
What to submit?
M1 is graded for completion, not accuracy
The purpose of milestones is to help you manage large, long-term project
TAs will use gradescope “grades” to help give feedback
Recall: Only Milestone 4 (final submission) is actual grade*
*With exceptions for things such as skipping milestones altogether
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Today’s Objectives:
Learning more about SystemVerilog
We’ll get through ~half+ these slides today, and the rest on Wednesday
Treat these slides as a reference
It’ll go kind of fast, goal is to expose to you things you can learn more about on your own
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Logistics Updates — Course Modality Poll
Not matter what, remote attendance will be an option all quarter
Will always stream via Zoom and recordings in Canvas
Current guidance is that we can resume in-person instruction next week
We are also permitted up to 5 weeks to shift modality
And this class does not meet during week 10 [all project hours]
POLL: Would you come to CENTR 115 M/W from 12-1 every day?
A: Definitely Yes
B: Maybe leaning Yes
C: Maybe leaning No
D: Definitely No
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Synthesizable System Verilog I – Fundamentals
[Picking this back up from week 1]
module adder( input [3:0] A, B,
output cout,
output [3:0] S );
wire c0, c1, c2;
FA fa0( A[0], B[0], 1’b0, c0, S[0] );
FA fa1( A[1], B[1], c0, c1, S[1] );
FA fa2( A[2], B[2], c1, c2, S[2] );
FA fa3( A[3], B[3], c2, cout, S[3] );
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
A module’s behaviour can be described in many different ways but it should not matter from outside
Example: mux4
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
module mux4( input a_i, b_i, c_i, d_i,
input [1:0] sel_i,
output z_o );
logic t0, t1;
assign z_o = ~((t0 | sel_i[0]) & (t1 | ~sel_i[0]));
assign t1 = ~((sel_i[1] & d_i) | (~sel_i[1] & b_i));
assign t0 = ~((sel_i[1] & c_i) | (~sel_i[1] & a_i));
Using continuous assignments to generate combinational logic
The order of these continuous assign statements in the source code does not affect functionality – they are just specifying a bunch of gates – a combinational cloud.
Any time an input to the combinational cloud changes, it propagates through the cloud of gates and the outputs are updated. (Be careful not to create combinational cycles!)
A couple of combinational
trees that
connect to each
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
should show parse tree turning into logic tree
// Four input multiplexer
module mux4( input a_i, b_i, c_i, d_i,
input [1:0] sel_i,
output z_o);
assign z_o = ( sel_i == 0 ) ? a_i :
( sel_i == 1 ) ? b_i :
( sel_i == 2 ) ? c_i :
( sel_i == 3 ) ? d_i : 1’bx;
If sel_i is X or Z, without the 1’bX condition, it would get d_i in behavioural simulation but maybe not in timing. Bad!
Having the 1’bx will help make sure your timing simulation looks the same as your behavioural.
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
should show construction of tree
Using combinational always_comb or always @(*) block
module mux4( input a_i, b_i, c_i, d_i,
input [1:0] sel_i,
output logic z_o );
logic t0, t1;
always_comb // system verilog; replaces always @(*)
t0 = (sel_i[1] & c_i) | (~sel_i[1] & a_i);
t1 = ~((sel_i[1] & d_i) | (~sel_i[1] & b_i));
t0 = ~t0;
z_o = ~( (t0 | sel_i[0]) & (t1 | ~sel_i[0]) );
Within the always_comb block, the synthesis tool synthesizes the lines in order.
Each L-value (variable to the left of =) creates a name for the wire that is at the top of a logic tree. If a variable is assigned again (like t0), then the mapping is updated – no cycles are created.
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Should add “t0 pointer update” diagram.
always_comb permits more advanced combinational idioms
if (sel_i == 2’d0 )
z_o = a_i;
else if (sel_i == 2’d1)
z_o = b_i;
else if (sel_i == 2’d2)
z_o = c_i;
else if (sel_i == 2’d3)
z_o = d_i;
z_o = 1’bx;
always_comb
case ( sel_i )
2’d0 : z_o = a_i;
2’d1 : z_o = b_i;
2’d2 : z_o = c_i;
2’d3 : z_o = d_i;
default: z_o = 1’bX;
module mux4( input a_i,b_i,c_i,d_i
input [1:0] sel_i,
output logic z_o);
Good idea for avoiding behavioral versus timing mismatches.
If none of these match, behavioral will just use last value. Timing will give you an X probably.
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Synthesis of if/else
logic t0, t1, sel;
always_comb
t0 = t1+1;
t1 = t0+1;
Note: a mux is created for every L-value written by all branches of the if/else or case statement.
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Synthesis of if/else
logic t0, t1, sel;
always_comb
t0 = 1’b1;
t0 = t0+1;
t1 = t0+1;
Note: no L-value should be undefined on any path; behavior is undefined; Verilog will create a latch (ugh)!
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Synthesis of if/else
logic t0, t1, sel;
always_comb
t0 = 1’b1;
t0 = t0+1;
Is this example okay?
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
What happens if the case statement is not complete?
module mux3( input a_i, b_i, c_i,
input [1:0] sel_i,
output logic z_o );
always @( * )
case ( sel_i )
2’d0 : z_o = a_i;
2’d1 : z_o = b_i;
2’d2 : z_o = c_i;
What have we created?
If sel = 3, mux will output
the previous value!
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
What happens if the case statement is not complete?
module mux3( input a_i, b_i, c_i
input [1:0] sel_i,
output logic z_o );
always @( * )
case ( sel_i )
2’d0 : z_o = a_i;
2’d1 : z_o = b_i;
2’d2 : z_o = c_i;
default : z_o = 1’bx;
We CAN prevent creating a latch with a default statement
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
What happens if the case statement is not complete?
module mux3( input a_i, b_i, c_i
input [1:0] sel_i,
output logic z_o );
always @( * )
always_comb
case ( sel_i )
2’d0 : z_o = a_i;
2’d1 : z_o = b_i;
2’d2 : z_o = c_i;
default : z_o = 1’bx;
SystemVerilog will protect you!
Be wary, many examples online are still plain ol’ Verilog, and will work fine … until they don’t
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Parameterized mux4
module mux4 #( parameter width_p = 1 )
( input[width_p-1:0] a_i, b_i, c_i, d_i,
input [1:0] sel_i,
output[width_p-1:0] z_o );
wire [width_p-1:0] t0, t1;
assign t0 = (sel_i[1]? c_i : a_i);
assign t1 = (sel_i[1]? d_i : b_i);
assign z_o = (sel_i[0]? t0 : t1);
Instantiation
mux4#(.width_p(32)) alu_mux
( .a_i (op1),
.b_i (op2),
.c_i (op3),
.d_i (op4),
.sel_i(alu_mux_sel),
.z_o(alu_mux_out) );
default value
Parameterization is a good practice for reusable modules
Writing a muxn is challenging, but can be done with “idiomatic” verilog.
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
SV Fundamentals
What is System Verilog?
Data types
Structural SV
Combinational Logic
Sequential Logic
module adder( input [3:0] A, B,
output cout,
output [3:0] S );
wire c0, c1, c2;
FA fa0( A[0], B[0], 1’b0, c0, S[0] );
FA fa1( A[1], B[1], c0, c1, S[1] );
FA fa2( A[2], B[2], c1, c2, S[2] );
FA fa3( A[3], B[3], c2, cout, S[3] );
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
logic q_r, q_n;
always_ff @( posedge clk )
q_r <= q_n;
Sequential Logic: Creating a flip flop
1) This line simply creates two signals, one called q_r and the other called q_n.
2) always_ff keyword indicates our intent to create registers; you could use the always keyword instead, but this makes it clear what you want!
3) @( posedge clk ) indicates that we want these registers to be triggered on the positive edge of the clk clock signal.
4) Combined with 2) and 3), the <= creates a register whose input is wired to q_n and whose output is wired to q_r. Use _r to indicate a wire that comes directly out of a register, and _n (i.e., next) to indicate a wire that goes directly into one, and becomes the new output on the next cycle.
note: always use <= with always_ff and = with always_comb
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Sequential Logic: flip-flop idioms
module FF (input clk, input d_i,
input en_i, output logic q_r_o);
always_ff @( posedge clk )
if ( en_i )
q_r_o <= d_i;
module FF0 (input clk, input d_i,
output logic q_r_o);
always_ff @( posedge clk )
q_r_o <= d_i;
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
idiom: flip-flops with reset
always_ff @( posedge clk)
if (reset)
else if ( enable )
synchronous reset
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Register (i.e. a vector of parallel flip-flops)
module register#(parameter width_p = 1)
input clk,
input [width_p-1:0] d_i,
input en_i,
output logic [width_p-1:0] q_r_o
always_ff @( posedge clk )
q_r_o <= d_i;
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Implementing Wider Registers
module register2
(input clk,
input [1:0] d_i,
input en_i,
output logic [1:0] q_r_o
always_ff @(posedge clk)
q_r_o <= d_i;
module register2
( input clk,
input [1:0] d_i,
input en_i,
output logic [1:0] q_r_o
FF ff0 (.clk(clk),
.d_i(d_i[0]),
.en_i(en_i),
.q_r_o(q_r_o[0]));
FF ff1 (.clk(clk),
.d_i(d_i[1]),
.en_i(en_i),
.q_r_o(q_r_o[1]));
Do they behave the same?
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Syntactic Sugar: always_ff allows you to combine combinational and sequential logic; but this can be confusing.
module accum #(parameter width_p=1)
( input clk,
input data_i,
input en_i,
output logic [width_p-1:0] sum_o;
logic [width_p-1:0] sum_r;
assign sum_o = sum_r;
always_ff @(posedge clk)
sum_r <= sum_r + data_i;
module accum #(parameter width_p=1)
( input clk,
input data_i,
input en_i,
output logic [width_p-1:0] sum_o;
logic [width_p-1:0] sum_r, sum_next;
assign sum_o = sum_r;
always_comb
sum_next = sum_r;
sum_next = sum_r + data_i;
always_ff @(posedge clk)
sum_r <= sum_next;
more clear
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Syntactic Sugar: You can always convert an always_ff that combines combinational and sequential logic into two separate always_ff and always_comb blocks.
module accum #(parameter width_p=1)
( input clk,
input data_i,
input en_i,
output logic [width_p-1:0] sum_o;
logic [width_p-1:0] sum_r;
assign sum_o = sum_r;
always_ff @(posedge clk)
sum_r <= sum_r + data_i;
module accum #(parameter width_p=1)
( input clk,
input data_i,
input en_i,
output logic [width_p-1:0] sum_o;
reg [width_p-1:0] sum_r, sum_next;
assign sum_o = sum_r;
always_comb
sum_next = sum_r;
sum_next = sum_r + data_i;
always_ff @(posedge clk)
sum_r <= sum_next;
When in doubt, use the version on the right.
To go from the left-hand version to the right one:
1. For each register xxx_r, introduce a temporary variable that
holds the input to each register (e.g. xxx_next)
2. Extract the combinational part of the always_ff block into an always_comb block:
a. change xxx_r <= to xxx_next =
b. add xxx_next = xxx_r; to beginning of block for default case
3. Extract the sequential part of the always_ff by creating a separate always_ff that does xxx_r <= xxx_next;
more clear
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Register array: we recommend you retain the en_i idiom in the always_ff block – could reduce # of ports.
always_ff @(posedge clk)
sum_r[wr_i] <= foo + far;
always_comb
sum_cond_next = foo + far;
always_ff @(posedge clk)
sum_r[wr_i] <= sum_cond_next;
more clear
always_ff @(posedge clk)
sum_r[wr_i] <= foo + far;
always_comb
sum_cond_next =
en_i ? (foo + far) : sum_r[wr_i];
always_ff @(posedge clk)
sum_r[wr_i] <= sum_cond_next;
extra ports? not so good.
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Bit Manipulations
logic [15:0] x;
logic [31:0] x_sext;
logic [31:0] hi, lo;
logic [63:0] hilo;
// concatenation
assign hilo = { hi, lo};
assign { hi, lo } = { 32’b0, 32’b1 };
// duplicate bits (16 copies of x[15] + bits 15..0 of x)
assign x_sext = {{16 { x[15] }}, x[15:0]};
// select top_p bits starting at 0 (same as [top_p-1:0])
assign foo = x[0+:top_p];
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Beware of assignment shortcuts
logic [15:0] x;
assign x = y;
logic [15:0] x = y;
wire [15:0] x = y;
“initialization”
non-synthesizable
“continuous assignment”
synthesizable
“Unlike nets, a variable cannot have an implicit continuous assignment as part of its declaration. An assignment as part of the declaration of a variable is a variable initialization, not a continuous assignment.”
IEEE 1800-2009 (SystemVerilog Standard) p. 50
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
unique and priority for case and if
unique exactly one branch or case item must execute; otherwise it is an error.
priority choices must be evaluated in order, and that one branch must execute.
Synopsys VCS: Does not generate X output, just says:
RT Warning: No condition matches in 'unique case' statement.
"system.v", line 20, for testbench.dut.cu, at time 100.
So, using 1’bX as the default condition still has some purpose, since it shows up in the waveform viewer. On the other hand, this tells you when the issue happens.
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Note: Our SV Subset
SV is a big language with many features not concerned with synthesizing hardware.
The code you write for your processor should contain only the language structures discussed in these slides.
Anything else is not synthesizable, although it will simulate fine.
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
System Verilog II –
Design examples
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Verilog can be used at several levels
automatic tools to synthesize a low-level gate-level model
High-Level Behavioral
Register Transfer Level
Gate Level
A common approach is to use C/C++ for initial behavioral modeling, and for building test rigs
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Use continuous assignments (assign)
assign c_i = b_o + 1;
Use always_comb blocks with blocking assignments (=)
always_comb
out = 2’d0;
if (in1 == 1)
out = 2’d1;
else if (in2 == 1)
out = 2’d2;
Every variable should have a default value to avoid inadvertent introduction of latches
Don’t assign to same variable from more than one always block. Race conditions in behavioral sim, synthesizes incorrectly.
Recap: Combinational logic
always blocks allow more expressive control structures, though not all will synthesize
default value
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Recap: Sequential Logic
Use always_ff @(posedge clk) only with non-blocking assignment operator (<=)
always_ff @( posedge clk )
c_o <= c_i;
Careful when mixing pos-edge & neg-edge triggered flip-flops
Do not assign the same variable from more than one always block. Race condition in behavioral simulation; synthesizes incorrectly.
Do not mix blocking and non-blocking assignments
only use non-blocking assignments (<=) for sequential logic.
only use block assignments (=) for combinational logic.
Like in software engineering, express your design as a module hierarchy that corresponds to logical boundaries in the design. Also, separate datapath and control (more later).
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
An Example: Good Style
logic a_n, b_n, c_n;
logic a_r, b_r, c_r;
always_ff @( posedge clk )
a_r <= a_n;
b_r <= b_n;
c_r <= c_n;
assign b_n = a_r + 1;
assign c_n = b_r + 1;
Readable, combinational and sequential logic are separated.
Consistent naming: A_r is the output of the register and A_n (or A_n) is the input.
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
An Example: Good Style
logic a_n;
logic b_n, c_n;
logic a_r, b_r, c_r;
always_ff @( posedge clk )
a_r <= a_n; // list in any order
b_r <= b_n;
c_r <= c_n;
always_comb
b_n = a_r + 1; // triggers when a_r or b_r changes
c_n = b_r + 1;
Readable, combinational and sequential logic are separated.
CC BY-NC-ND Pat Pannuto – Content derived from materials from , , , and others
Alternate implementation?
logic a_n, b_n, c_n;
logic a_r, b_r, c_r;
always_ff @( posedge clk )
a_r <= a_n;
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com