Digital Design with the Verilog HDL - Chapter 5: Behavioral Model - Part 2

pdf 43 trang Gia Huy 16/05/2022 3070
Bạn đang xem 20 trang mẫu của tài liệu "Digital Design with the Verilog HDL - Chapter 5: Behavioral Model - Part 2", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên

Tài liệu đính kèm:

  • pdfdigital_design_with_the_verilog_hdl_chapter_5_behavioral_mod.pdf

Nội dung text: Digital Design with the Verilog HDL - Chapter 5: Behavioral Model - Part 2

  1. Digital Design with the Verilog HDL Chapter 5: Behavioral Model - part 2 Dr. Phạm Quốc Cường Use some Prof. Mike Schulte’s slides (schulte@engr.wisc.edu) Computer Engineering – CSE – HCMUT 1
  2. Interacting Behaviors [1] • Assignments can trigger other assignments • Nonblocking assignments CAN trigger blocking assignments always @ (posedge clk) always @ (A, C) begin begin A <= B; D = A & C; end end • In hardware, reflects that the output of the A flip flop or register can be the input to combinational logic • When the FF changes value, that change must propagate through the combinational logic it feeds into 2
  3. Interacting Behaviors [2] always @ (posedge clk or posedge rst) // behavior1 if (rst) y1 = 0; //reset else y1 = y2; always @ (posedge clk or posedge rst) // behavior2 if (rst) y2 = 1; // preset example taken from else y2 = y1; Cummings paper! • If behavior1 always first after reset, y1 = y2 = 1 • If behavior2 always first after reset, y2 = y1 = 0. • Results are order dependent, ambiguous – race condition! • This is why we don’t use blocking assigns for flip-flops 3
  4. Interacting Behaviors [3] always @ (posedge clk or posedge rst) if (rst) y1 <= 0; //reset else y1 <= y2; always @ (posedge clk or posedge rst) if (rst) y2 <= 1; // preset example taken from else y2 <= y1; Cummings paper! • Assignments for y1 and y2 occur in parallel • y1 = 1 and y2 = 0 after reset • Values swap each clock cycle after the reset • No race condition! 4
  5. Synchronous/Asynchronous Reset • Synchronous: triggered by clock signal module dff_sync(output reg Q, input D, clk, rst); always @(posedge clk) begin if (rst) Q <= 1’b0; else Q <= D; end endmodule • Asynchronous: also triggered by reset signal module dff_async(output reg Q, input D, clk, rst, en); always @(posedge clk, posedge rst) begin if (rst) Q <= 1’b0; else if (en) Q <= D; end endmodule 5
  6. What Happens Here? module dff_BAD(reg output Q, input D, clk, rst); always @(posedge clk, reset) begin if (rst) Q <= 1’b0; else Q <= D; end endmodule Does this give incorrect behavior? 6
  7. Datatype Categories • Net – Represents a physical wire – Describes structural connectivity – Assigned to in continuous assignment statements – Outputs of primitives and instantiated sub-modules • Variables – Used in Behavioral procedural blocks – Can represent: • Synchronous registers • Combinational logic 7
  8. Variable Datatypes • reg – scalar or vector binary values Not necessarily a • integer – 32 or more bits “register”!!! • time – time values represented in 64 bits (unsigned) • real – double real values in 64 or more bits • realtime - stores time as double real (64-bit +) • Assigned value only within a behavioral block • CANNOT USE AS: – Output of primitive gate or instantiated submodule – LHS of continuous assignment – Input or inout port within a module • real and realtime initialize to 0.0, others to x – Just initialize yourself! 8
  9. Examples Of Variables reg signed [7:0] A_reg; // 8-bit signed vector register reg Reg_Array[7:0]; // array of eight 1-bit registers integer Int_Array[1:100]; // array of 100 integers real B, Real_Array[0:5]; // scalar & array of 6 reals time Time_Array[1:100]; // array of 100 times realtime D, Real_Time[1:5]; // scalar & array of 5 realtimes initial begin A_reg = 8’ha6; // Assigns all eight bits Reg_Array[7] = 1; // Assigns one bit Int_Array[3] = -1; // Assign integer -1 B = 1.23e-4; // Assign real Time_Array[20] = $time; // Assigned by system call D = 1.25; // Assign real time end 9
  10. wire vs. reg • Same “value” used both as ‘wire’ and as ‘reg’ module dff (q, d, clk); output reg q; // reg declaration, input wire d, clk; // wire declarations, since module inputs always @(posedge clk) q <= d; // why is q reg and d wire? endmodule module t_dff; wire q, clk; // now declared as wire reg d; // now declared as reg dff FF(q, d, clk); // why is d reg and q wire? clockgen myclk(clk); initial begin d = 0; #5 d = 1; end endmodule 10
  11. Signed vs. Unsigned • Net types and reg variables unsigned by default – Have to declare them as signed if desired! reg signed [7:0] signedreg; wire signed [3:0] signedwire; • All bit-selects and part-selects are unsigned – A[6], B[5:2], etc. • integer, real, realtime are signed • System calls can force values to be signed or unsigned reg [5:0] A = $unsigned(-4); reg signed [5:0] B = $signed(4’b1101); 11
  12. Operators with Real Operands • Arithmetic – Unary +/- – + - * / • Relational – > >= < <= No others allowed! • Logical No bit-selects! – ! && || • Equality No part-selects! – == != • Conditional – ? : 12
  13. Strings • Strings are stored using properly sized registers reg [12*8: 1] stringvar; // 12 character string stringvar = “Hello World”; // string assignment • Uses ASCII values • Unused characters are filled with zeros • Strings can be copied, compared, concatenated • Most common use of strings is in testbenches 13
  14. Memories • A memory is an array of n-bit registers reg [15:0] mem_name [0:127]; //128 16-bit words reg array_2D [15:0] [0:127]; // 2D array of 1-bit regs • Can only access full word of memory mem_name[122] = 35; // assigns word mem_name[13][5] = 1; // illegal – works in simulation array_2D[122] = 35; // illegal – causes compiler error array_2D[13][5] = 1; // assigns bit • Can use continuous assign to read bits assign mem_val = mem[13]; // get word in slot 13 assign out = mem_val[5]; // get bit in slot 5 of word assign dataout = mem[addr]; assign databit = dataout[bitpos]; 14
  15. Example: Memory module memory(output reg [7:0] out, input [7:0] in, input [7:0] addr, input wr, clk, rst); reg [7:0] mem [0:255]; reg [8:0] initaddr; always @ (posedge clk) begin if (rst) begin for (initaddr = 0; initaddr < 256; initaddr = initaddr + 1) begin mem[initaddr] <= 8’d0; end end else if (wr) mem[addr] <= in; end always @(posedge clk) out <= mem[addr]; endmodule 15
  16. Example: Memory module memory(output reg [7:0] out, input [7:0] in, input [7:0] addr, input wr, clk, rst); reg [7:0] mem [0:255]; reg [8:0] initaddr; always @ (posedge clk) begin if (rst) begin for (initaddr = 0; initaddr < 256; initaddrsynchronous= initaddr reset!+ 1) begin mem[initaddr] <= 8’d0; end end else if (wr) mem[addr] <= in; synchronous write end always @(posedge clk) out <= mem[addr]; synchronous read endmodule 16
  17. Control Statements • Behavioral Verilog looks a lot like software – (risk! – danger and opportunity) • Provides similar control structures – Not all of these actually synthesize, but some non- synthesizable statements are useful in testbenches • What kinds synthesize? – if – case – for loops with constant bounds 17
  18. if else if else • Operator ? : for simple conditional assignments • Sometimes need more complex behavior • Can use if statement! – Does not conditionally “execute” block of “code” – Does not conditionally create hardware! – It makes a multiplexer or similar logic • Generally: – Hardware for all paths is created – All paths produce their results in parallel – One path’s result is selected depending on the condition 18
  19. Potential Issues With if • Can sometimes create long multiplexer chains always @(select, a, b, c, d) begin out = d; if (select == 2’b00) out = a; if (select == 2’b01) out = b; if (select == 2’b10) out = c; end always @(a, b, c, d) begin if (a) begin if (b) begin if (c) out = d; else out = ~d; else out = 1; else out = 0; end 19
  20. if Statement: Flip-Flop Set/Reset module df_sr_behav (q, q_n, data, set, reset, clk); input data, set, clk, reset; output q, q_n; reg q; assign q_n = ~q; // continuous assignment always @ (posedge clk) begin // Flip-flop with synchronous set/reset if (reset) q <= 1’b0; // Active-high set and reset else if (set) q <= 1’b1; else q <= data; end endmodule • Does set or reset have priority? 20
  21. case Statements • Verilog has three types of case statements: – case, casex, and casez • Performs bitwise match of expression and case item – Both must have same bitwidth to match! • case – Can detect x and z! (only in simulation) • casez – Can detect x (In simulation) – Uses z and ? as wildcard bits in case items and expression • casex – Uses x, z, and ? as wildcard bits in case items and expression 21
  22. Using case To Detect x And z • Only use this functionality in a testbench; it won’t synthesize! • Example taken from Verilog-2001 standard; • Cannot be synthesized case (sig) 1’bz: $display(“Signal is floating.”); 1’bx: $display(“Signal is unknown.”); default: $display(“Signal is %b.”, sig); endcase 22
  23. casex Statement • Uses x, z, and ? as single-bit wildcards in case item and expression • Uses only the first match encountered – Inherent priority! • Treats x, z, and ? as don’t care always @ (code) begin casex (code) // case expression 2’b0?: control = 8’b00100110; // case item1 2’b10: control = 8’b11000010; // case item 2 2’b11: control = 8’b00111101; // case item 3 endcase end What is the output for code = 2’b01? What is the output for code = 2’b1x? casex construct is often used to describe logic with priority 23
  24. casez Statement • Uses z, and ? as single-bit wildcards in case item and expression • Use z as don’t care, x is a value says we don’t care what • Uses first match encountered control is in other cases more on this next always @ (code) begin casez (code) 2’b0?: control = 8’b00100110; // item 1 2’bz1: control = 8’b11000010; // item 2 default: control = 8b’xxxxxxxx; // item 3 endcase end Adding a default case What is the output for code = 2b’01? statement is a great way to What is the output for code = 2b’zz? avoid inferring latches and make debugging easier! 24
  25. “Don’t Care” Assignment With case • Sometimes we know not all cases will occur • Can “don’t care” what is assigned always@(state, b) begin case (state) // state is “expression” 2’d0: next_state = 2’d1; // 2’d0 is case item 2’d1: next_state = 2’d2; // ordering implied 2’d2: if (b) next_state = 2’d0; else next_state = 2’d1; default: next_state = 2’dx; // for all other states, endcase // don’t care what is end // assigned 25
  26. “Don’t Care” Assignment With if • Some combinations don’t happen • Can “don’t care” what is assigned – For the real hardware, the actual value assigned is either 1 or 0 (or a vector of 1s and/or 0s), but the synthesizer gets to choose always@(a, b, c) begin if (a && b) d = c; else if (a) d = ~c; else d = 1’bx; end For what inputs does the “don’t care” value of d happen? 26
  27. Inferring Latches • Earlier we saw how to explicitly create latches • We can also implicitly “infer” latches – Often this is unintentional and the result of poor coding, accidentally creating a latch instead of comb. logic – Unintentional latches are a leading cause of simulation and synthesis results not matching! • Two common ways of inferring latches – Failing to fully specify all possible cases when using if/else, case, or conditional assignment when describing combinational logic – Failing to assign values to each variable in all cases 27
  28. Unintended Latches [1] (BAD) • Always use else or provide “default value” when using if to describe combinational logic! always @(en, a, b) begin if (en) c = a + b; // latch! – What about en = 1’b0? end always @(en, a, b) begin c = 8’b0; // Fixed! Assign default value to C if (en) c = a + b; // Will be overwritten if en=1’b1 end always @(en, a, b) begin if (en) c = a + b; // Fixed! Add an Else statement else c = 8’b0; // Could have used a different value end 28
  29. Unintended Latches [2] (BAD) • Make sure that no matter what the value of your case selector is, if a variable is assigned in one case, it must be assigned in EVERY case. always @(sel, a, b) case (sel) 2’b00 : begin out1 = a + b; out2 = a – b; end 2’b01 : out1 = a + b; //Latch! What about out2’s value? 2’b10 : out2 = a – b; //Latch! What about out1’s value? //Latch! What about out1 and out2’s values for sel=2’b11? endcase How could we modify this code to remove the latches? 29
  30. Mux With if else if else module Mux_4_32_if (output [31:0] mux_out, input [31:0] data_3, data_2, data_1, data_0, input [1:0] select, input enable); reg [31: 0] mux_int; // add the enable functionality assign mux_out = enable ? mux_int : 32'bz; // choose between the four inputs always @ ( data_3 or data_2 or data_1 or data_0 or select) if (select == 0) mux_int = data_0; else if (select == 1) mux_int = data_1; else if (select == 2) mux_int = data_2; else mux_int = data_3; endmodule What happens if we forget select in the trigger list? What happens if select is 2’bxx? 30
  31. Mux With case module Mux_4_32_(output [31:0] mux_out, input [31:0] data_3, data_2, data_1, data_0, input [1:0] select, input enable); reg [31: 0] mux_int; // add the enable functionality assign mux_out = enable ? mux_int : 32'bz; // choose between the four inputs always @ ( data_3 or data_2 or data_1 or data_0 or select) case (select) 2’d0: mux_int = data_0; 2’d1: mux_int = data_1; 2’d2: mux_int = data_2; 2’d3: mux_int = data_3; endcase endmodule • Case statement implies priority unless use parallel_case pragma • What happens if select is 2’bxx? 31
  32. Encoder With if else if else module encoder (output reg [2:0] Code, input [7:0] Data); always @ (Data) begin // encode the data if (Data == 8'b00000001) Code = 3’d0; else if (Data == 8'b00000010) Code = 3’d1; else if (Data == 8'b00000100) Code = 3’d2; else if (Data == 8'b00001000) Code = 3’d3; else if (Data == 8'b00010000) Code = 3’d4; else if (Data == 8'b00100000) Code = 3’d5; else if (Data == 8'b01000000) Code = 3’d6; else if (Data == 8'b10000000) Code = 3’d7; else Code = 3'bxxx; // invalid, so don’t care end endmodule 32
  33. Encoder With case module encoder (output reg [2:0] Code, input [7:0] Data); always @ (Data) // encode the data case (Data) 8'b00000001 : Code = 3’d0; 8'b00000010 : Code = 3’d1; 8'b00000100 : Code = 3’d2; 8'b00001000 : Code = 3’d3; 8'b00010000 : Code = 3’d4; 8'b00100000 : Code = 3’d5; 8'b01000000 : Code = 3’d6; 8'b10000000 : Code = 3’d7; default : Code = 3‘bxxx; // invalid, so don’t care endcase endmodule 33
  34. Priority Encoder With casex module priority_encoder (output reg [2:0] Code, output valid_data, input [7:0] Data); assign valid_data = |Data; // "reduction or" operator always @ (Data) // encode the data casex (Data) 8'b1xxxxxxx : Code = 7; 8'b01xxxxxx : Code = 6; 8'b001xxxxx : Code = 5; 8'b0001xxxx : Code = 4; 8'b00001xxx : Code = 3; 8'b000001xx : Code = 2; 8'b0000001x : Code = 1; 8'b00000001 : Code = 0; default : Code = 3'bxxx; // should be at least one 1, don’t care endcase endmodule 34
  35. Seven Segment Display module Seven_Seg_Display (Display, BCD, Blanking); output reg [6: 0]Display; // abc_defg input [3: 0] BCD; input Blanking; parameter BLANK = 7'b111_1111; // active low parameter ZERO = 7'b000_0001; // h01 parameter ONE = 7'b100_1111; // h4f parameter TWO = 7'b001_0010; // h12 parameter THREE = 7'b000_0110; // h06 parameter FOUR = 7'b100_1100; // h4c a parameter FIVE = 7'b010_0100; // h24 f b parameter SIX = 7'b010_0000; // h20 g parameter SEVEN = 7'b000_1111; // h0f e c parameter EIGHT = 7'b000_0000; // h00 parameter NINE = 7'b000_0100; // h04 d Defined constants – can make code more understandable! 35
  36. Seven Segment Display always @ (BCD or Blanking) if (Blanking) Display = BLANK; else case (BCD) 4’d0: Display = ZERO; Using the defined 4’d1: Display = ONE; constants! 4’d2: Display = TWO; 4’d3: Display = THREE; 4’d4: Display = FOUR; 4’d5: Display = FIVE; 4’d6: Display = SIX; 4’d7: Display = SEVEN; 4’d8: Display = EIGHT; 4’d9: Display = NINE; default: Display = BLANK; endcase endmodule 36
  37. Ring Counter module ring_counter (count, enable, clock, reset); output reg [7: 0] count; input enable, reset, clock; always @ (posedge reset or posedge clock) if (reset == 1'b1) count <= 8'b0000_0001; else if (enable == 1’b1) begin case (count) 8’b0000_0001: count <= 8’b0000_0010; 8’b0000_0010: count <= 8’b0000_0100; 8’b1000_0000: count <= 8’b0000_0001; default: count <= 8’bxxxx_xxxx; endcase end endmodule 37
  38. Ring Counter module ring_counter (count, enable, clock, reset); output reg [7: 0] count; input enable, reset, clock; always @ (posedge reset or posedge clock) if (reset == 1'b1) count <= 8'b0000_0001; else if (enable == 1'b1) count <= {count[6: 0], count[7]}; endmodule 38
  39. Register With Parallel Load module Par_load_reg4 (Data_out, Data_in, load, clock, reset); input [3: 0] Data_in; input load, clock, reset; output reg [3: 0] Data_out; always @ (posedge reset or posedge clock) begin if (reset == 1'b1) Data_out <= 4'b0; else if (load == 1'b1) Data_out <= Data_in; else Data_out <= Data_out; end endmodule 39
  40. Rotator module rotator (Data_out, Data_in, load, clock, reset); output reg [7: 0] Data_out; input [7: 0] Data_in; input load, clock, reset; always @ (posedge reset or posedge clock) if (reset == 1'b1) Data_out <= 8'b0; else if (load == 1'b1) Data_out <= Data_in; else Data_out <= {Data_out[6: 0], Data_out[7]}; endmodule 40
  41. Shift Register – Part 1 module Shift_Reg(Data_Out, MSB_Out, LSB_Out, Data_In, MSB_In, LSB_In, s1, s0, clk, rst); output reg [3: 0] Data_Out; output MSB_Out, LSB_Out; input [3: 0] Data_In; input MSB_In, LSB_In; input s1, s0, clk, rst; assign MSB_Out = Data_Out[3]; assign LSB_Out = Data_Out[0]; // continued on next slide 41
  42. Shift Register – Part 2 always @ (posedge clk) begin if (rst) Data_Out <= 0; else case ({s1, s0}) 2’d0: Data_Out <= Data_Out; // Hold 2’d1: Data_Out <= {MSB_In, Data_Out[3:1]}; // Shift from MSB 2’d2: Data_Out <= {Data_Out[2: 0], LSB_In}; // Shift from LSB 2’d3: Data_Out <= Data_In; // Parallel Load endcase end endmodule 42
  43. Register File module Register_File (Data_Out_1, Data_Out_2, Data_in, Read_Addr_1, Read_Addr_2, Write_Addr, Write_Enable, Clock); output [15:0] Data_Out_1, Data_Out_2; input [15:0] Data_in; input [2:0] Read_Addr_1, Read_Addr_2, Write_Addr; input Write_Enable, Clock; reg [15:0] Reg_File [0:15]; // 16-bit by 8-word memory declaration always @ (posedge Clock) begin if (Write_Enable) Reg_File [Write_Addr] <= Data_in; Data_Out_1 <= Reg_File[Read_Addr_1]; Data_Out_2 <= Reg_File[Read_Addr_2]; end endmodule • Are the reads and writes synchronous or asynchronous? 43