4 Simulacion de radicador con program, y scoreboa - EDA Playground
Warning! This exercise has been opened in another tab; autosave has been disabled. Close this tab or refresh to reactivate.

 Languages & Libraries

 Tools & Simulators

 Examples

205


200
 
1
class Bus;
2
  rand logic [7:0] valor;
3
  constraint impares    {valor[0] == 1'b1;}
4
  constraint pares {valor[0] == 1'b0;}
5
endclass
6
`timescale 1ns/1ps
7
interface test_if (
8
  input  bit        reloj  , 
9
  input   bit      rst);
10
  logic       empieza      ;
11
  logic       termina    ;
12
  logic [7:0] data_in  ;
13
  logic  [3:0] data_out;
14
15
  clocking md @(posedge reloj);
16
    input #1ns data_out;
17
    input #1ns data_in;
18
    input #1ns empieza;
19
    input #1ns termina;
20
   endclocking:md;
21
22
  clocking sd @(posedge reloj);
23
    input #2ns  data_out;
24
    output #2ns data_in;
25
    input #2ns  termina;
26
    output #2ns empieza; 
27
  endclocking:sd;
28
29
30
31
    modport monitor (clocking md);
32
    modport test (clocking sd);
33
    modport duv (
34
        input           reloj      ,
35
        input           rst      ,
36
        output           termina  ,
37
        input           empieza   ,
38
        input           data_in  ,
39
        output          data_out
40
        );
41
42
endinterface
43
class Scoreboard;
44
  reg [3:0] cola_targets   [$];
45
  reg [3:0] target,pretarget,salida_obtenida;
46
  reg FINAL;
47
  virtual test_if.monitor mports;
48
  
49
  function new (virtual test_if.monitor mpuertos);
50
  begin
51
    this.mports = mpuertos;
52
  end
53
  endfunction
54
   
55
 task monitor_input;
56
   begin
57
     while (1)
58
       begin       
59
         @(mports.md);
60
         if (mports.md.empieza==1'b1)
61
           begin
62
             pretarget=$floor($sqrt(int'(mports.md.data_in)));//funcion ideal de obtencion e raiz cuadrada
63
             cola_targets={pretarget,cola_targets};//meto el valor deseado en la cola
64
           end
65
        end
66
   end
67
 endtask
68
  task monitor_output;
69
   begin
70
     while (1)
71
       begin       
72
         @(mports.md);
73
         if (mports.md.termina==1'b1)
74
           begin
75
            FINAL=mports.md.termina;
76
            target= cola_targets.pop_back();
77
            salida_obtenida=mports.md.data_out;
78
             assert (salida_obtenida==target) else $error("operacion mal realizada: la raiz cuadrada de %d es %d y tu diste %d",mports.md.data_in,target,salida_obtenida);
79
           end
80
        end
81
   end
82
 endtask 
83
  
84
    
85
    
86
endclass 
87
    
88
89
90
program estimulos
91
  (test_if.test testar,
92
   test_if.monitor monitorizar  
93
  );
94
  
95
96
 
97
//esto nos permitirá utilziar el operador ## para los ciclcos de reloj
98
  
99
covergroup valores_X;    
100
  idea1:coverpoint  monitorizar.md.data_in;
101
  idea2:coverpoint  monitorizar.md.data_in
102
    {
103
    bins cero ={8'h00};
104
    bins extremo = {8'h80};
105
  }
106
107
endgroup;                       
108
//declaraciones de tres objetos
109
  Bus busInst; //objeto de la clase para RSCG
110
  valores_X veamos; //objeto del covergroup
111
  Scoreboard sb;//objeto de la clase scoreboard
112
113
  initial
114
begin
115
    busInst = new;//construimos la case de valores random
116
    veamos=new;//construimos el covergroup
117
    sb=new(monitorizar); //construimos el scoreboard
118
    fork
119
      sb.monitor_input; //lanzo el procedimiento de monitorizacion cambio entrada y calculo del valor target
120
      sb.monitor_output;//lanzo el procedimiento de monitorizacion cambio salida y comparacion ideal
121
    join_none
122
    testar.sd.empieza <= 1'b0;
123
    testar.sd.data_in <= 8'd25;
124
    repeat(3) @(testar.sd);
125
    testar.sd.empieza <= 1'b1;
126
    @(testar.sd);
127
    testar.sd.empieza <= 1'b0;
128
  @(negedge testar.sd.termina);
129
  while ( veamos.get_coverage()<40)
130
    begin
131
       busInst.pares.constraint_mode(0);
132
       $display("pruebo con impares");
133
       assert (busInst.randomize()) else    $fatal("randomization failed");
134
        testar.sd.data_in<= busInst.valor;  
135
        veamos.sample();
136
            @(testar.sd);
137
       testar.sd.empieza <= 1'b1;
138
        @(testar.sd);
139
       testar.sd.empieza <= 1'b0;
140
      @(negedge testar.sd.termina);
141
   end
142
  while ( veamos.get_coverage()<90)
143
    begin
144
       busInst.impares.constraint_mode(0);
145
       busInst.pares.constraint_mode(1);
146
       $display("pruebo con pares");
147
       assert (busInst.randomize()) else    $fatal("randomization failed");
148
        testar.sd.data_in <= busInst.valor; 
149
        veamos.sample();  
150
        @(testar.sd);
151
        testar.sd.empieza <= 1'b1;
152
        @(testar.sd);
153
       testar.sd.empieza <= 1'b0;
154
      @(negedge testar.sd.termina);
155
   end
156
   $stop;
157
end
158
endprogram
159
160
161
module prueba_radicador();
162
// constants                                           
163
// general purpose registers
164
reg CLK;
165
reg RESET;
166
167
//instanciacion del interfaz
168
test_if interfaz(.reloj(CLK),.rst(RESET));
169
170
//instanciación del disenyo                  
171
 top_duv duv (.bus(interfaz));
172
            
173
//instanciacion del program  
174
estimulos estim1 (.testar(interfaz),.monitorizar(interfaz));  
175
176
// CLK
177
always
178
begin
179
    CLK = 1'b0;
180
    CLK = #50 1'b1;
181
    #50;
182
end 
183
184
// RESET
185
initial
186
begin
187
  RESET=1'b1;
188
  # 1  RESET=1'b0;
189
    #99 RESET = 1'b1;
190
end 
191
192
//volcado de valores para el visualizados
193
  
194
initial begin
195
  $dumpfile("radicador.vcd");
196
  $dumpvars(1,prueba_radicador.duv.radicador_duv.X);
197
  $dumpvars(1,prueba_radicador.duv.radicador_duv.COUNT);
198
end  
199
endmodule
200
302
 
1
//empezamos con el top donde se unen los elementos del data-path y e control-path
2
3
module top_duv (test_if.duv bus) ; 
4
5
6
sed  radicador_duv(
7
  .CLK   (bus.reloj),     // Clock input
8
.RESET  (bus.rst),     // Active LOW ASINCRONOUS reset
9
.X      (bus.data_in), // Data input
10
.COUNT     (bus.data_out),// Data Output
11
.START    (bus.empieza),   // duv empieza
12
 .FIN    (bus.termina)     //duv termina
13
);
14
15
endmodule
16
17
18
module sed(
19
    CLK,
20
    START,
21
    RESET,
22
    X,
23
    FIN,
24
    COUNT
25
);
26
27
28
input wire  CLK;
29
input wire  START;
30
input wire  RESET;
31
input wire  [7:0] X;
32
output wire FIN;
33
output wire [3:0] COUNT;
34
35
wire    ENA_C;
36
wire    ENA_R;
37
wire    LOAD_R;
38
wire  LOAD_C;
39
wire    [9:0] PROD;
40
wire    [4:0] VALUE;
41
wire [3:0] entrada_contador;
42
wire    [8:0] X_E;
43
wire    [3:0] SYNTHESIZED_WIRE_0;
44
wire    [3:0] SYNTHESIZED_WIRE_1;
45
wire    SYNTHESIZED_WIRE_2;
46
wire    SYNTHESIZED_WIRE_3;
47
wire    [8:0] SYNTHESIZED_WIRE_4;
48
wire    SYNTHESIZED_WIRE_5;
49
wire    [0:3] SYNTHESIZED_WIRE_6;
50
reg DFF_inst3;
51
wire    SYNTHESIZED_WIRE_7;
52
wire    SYNTHESIZED_WIRE_8;
53
reg DFF_inst2;
54
55
assign  COUNT = SYNTHESIZED_WIRE_0;
56
assign  SYNTHESIZED_WIRE_2 = 0;
57
assign  SYNTHESIZED_WIRE_3 = 1;
58
assign  SYNTHESIZED_WIRE_5 = 0;
59
assign  SYNTHESIZED_WIRE_6 = 0;
60
assign  SYNTHESIZED_WIRE_8 = 1;
61
62
63
64
65
lpm_add_sub_0   incrementador(
66
    
67
    .dataa(SYNTHESIZED_WIRE_0),
68
    .datab(SYNTHESIZED_WIRE_1),
69
    .cout(VALUE[4]),
70
    .result(VALUE[3:0]));
71
72
assign  X_E[8] = SYNTHESIZED_WIRE_2;
73
74
75
76
77
78
REGGEN  REG(
79
    .CLK(CLK),
80
    .CLRN(SYNTHESIZED_WIRE_3),
81
    .ENA(ENA_R),
82
    .DATA(PROD[8:0]),
83
    .Q(SYNTHESIZED_WIRE_4));
84
85
86
87
lpm_compare_1    compararador(
88
    .dataa(SYNTHESIZED_WIRE_4),
89
    .datab(X_E),
90
    
91
    
92
    .agb(SYNTHESIZED_WIRE_7)
93
    
94
    
95
    );
96
97
98
lpm_constant_2  b2v_2(
99
    .result(SYNTHESIZED_WIRE_1));
100
101
102
103
assign entrada_contador=VALUE[3:0];
104
assign LOAD_C =ENA_C|LOAD_R;
105
    
106
COUNTER CONT(
107
    .CLK(CLK),
108
    .CLRN(SYNTHESIZED_WIRE_3),
109
    .SR(LOAD_R),
110
    .ENA(LOAD_C),
111
    .DATA(entrada_contador),
112
    .COUNT(SYNTHESIZED_WIRE_0));
113
114
115
116
lpm_mult_3  elevador_cuadrado(
117
    .dataa(VALUE),
118
    .datab(VALUE),
119
    .result(PROD));
120
121
assign  X_E[7:0] = X;
122
123
124
125
FSM control_path(
126
    .clk(CLK),
127
    .reset(DFF_inst3),
128
    .mayor(SYNTHESIZED_WIRE_7),
129
    .start(START),
130
    .ena_r(ENA_R),
131
    .ena_c(ENA_C),
132
    .clear_c(LOAD_R),
133
    .fin(FIN));
134
135
136
always@(posedge CLK or negedge RESET)
137
begin
138
if (!RESET)
139
    begin
140
    DFF_inst2 <= 0;
141
    end
142
else
143
    begin
144
    DFF_inst2 <= SYNTHESIZED_WIRE_8;
145
    end
146
end
147
148
149
always@(posedge CLK or negedge RESET)
150
begin
151
if (!RESET)
152
    begin
153
    DFF_inst3 <= 0;
154
    end
155
else
156
    begin
157
    DFF_inst3 <= DFF_inst2;
158
    end
159
end
160
161
162
endmodule
163
164
//empezamos con los elementos del DATA-PATH 
165
166
//los puramente combinacionales
167
168
//en primer lugar el incrementador combinacional, que es utilizado dos veces
169
//uno para la operación incrementar del estado regist
170
//otro para la operación incrementar del estado inc, lo cual hace que en esa situación 
171
//la variable  CONT implementado por el registro se comporte como un contador  
172
module lpm_add_sub_0(dataa,datab,cout,result);
173
/* synthesis black_box */
174
175
input [3:0] dataa;
176
input [3:0] datab;
177
output cout;
178
output [3:0] result;
179
assign {cout,result}=dataa+datab;
180
181
endmodule
182
183
//comparador combinacional
184
module lpm_compare_1(dataa,datab,agb);
185
/* synthesis black_box */
186
187
input [8:0] dataa;
188
input [8:0] datab;
189
output agb;
190
assign agb=(dataa>datab);
191
endmodule
192
193
//constante uno para el incrementador
194
module lpm_constant_2(result);
195
/* synthesis black_box */
196
197
output [3:0] result;
198
assign result=4'b0001;
199
endmodule
200
201
//elevador al cuadradado combinacional
202
module lpm_mult_3(dataa,datab,result);
203
/* synthesis black_box */
204
205
input [4:0] dataa;
206
input [4:0] datab;
207
output [9:0] result;
208
assign result=dataa*dataa;
209
endmodule
210
211
//continuamos con los elementos secuenciales del data-path
212
213
//registro  que utilizaremos para la variable CONT: tiene los modos de operacion sincronos
214
//reset 
215
//cargar . si DATA es el incrementado se convierte en incrementar
216
//mantener
217
module COUNTER
218
#(parameter WIDTH=4)
219
(
220
    input CLK, ENA, CLRN,LOAD,SR,
221
    input [WIDTH-1:0] DATA,
222
    output reg [WIDTH-1:0] COUNT
223
);
224
225
    // Reset if needed, or increment if counting is enabled
226
    always_ff @ (posedge CLK or negedge CLRN)
227
    begin
228
        if (!CLRN)
229
            COUNT <= 0;
230
        else if  (ENA==1'b1) begin
231
                                if (SR)
232
                                    COUNT<='0;
233
                                else 
234
                                    COUNT<=DATA;
235
                        end
236
    end
237
238
endmodule
239
240
//registro simple que utilizaremos para la variable REG:tiene los modos de operacion sincronos
241
//cargar
242
//mantener
243
module REGGEN
244
#(parameter WIDTH=9)
245
(
246
    input CLK, ENA, CLRN,
247
    input [WIDTH-1:0] DATA,
248
    output reg [WIDTH-1:0] Q
249
);
250
251
    // Reset if needed, or increment if counting is enabled
252
    always_ff @ (posedge CLK or negedge CLRN)
253
    begin
254
        if (!CLRN)
255
            Q <= '0;
256
        else if (ENA == 1'b1)
257
                    Q<=DATA;
258
    end
259
260
endmodule
261
262
//FINALMENTE  EL CONTROL-PATH realizado con el estilo de dos procesos
263
264
module FSM (input clk, reset,  mayor, start, output logic ena_c,clear_c, ena_r, fin);
265
enum logic [5:0] { idle = 6'b0, init = 6'b000011, regist = 6'b000101, comp = 6'b001001, inc= 6'b010001, finall= 6'b100001 } state;
266
267
268
  always_ff@(posedge clk or negedge reset) begin
269
    if(!reset)
270
state <= idle;
271
else
272
case(state)
273
idle: if (start) state <= init;
274
init: state <= regist;
275
regist: state <= comp;
276
comp: if (mayor) 
277
            state <= finall;
278
        else
279
            state<=inc;
280
inc: state <= regist;
281
finall: if (!start) state<=idle;
282
endcase
283
end
284
285
286
always_comb begin
287
clear_c=0;
288
ena_c=0;
289
ena_r=0;
290
fin=0;
291
case(state)
292
init: clear_c=1;
293
regist: ena_r=1;
294
inc: ena_c=1;
295
finall: fin=1;
296
endcase
297
end
298
299
endmodule
300
301
302
2075 views and 0 likes     
 
Un radicador realizado con un control-path y un data-path:
    1) En el data-path destaca el reaprovechamiento del incrementador 
    2) En el control-path se ha hecho con un estilo de Moore de dos procesos
Un banco de pruebas realizado con:
        1) RSCG para los valores de entrada,
        2) con cobertura de los valores de entrada probados y una aserción inmediata de comparación con una radicador ideal
        3) Introduzco los estimulos y la comprobacion de resultados con un program
        4) introduzco un clocking block para sincronizar y lo establezo como bloque de reloj por defecto, con lo cual ya puedo utilizar  el operador ##
        5) Mejoro el scoreboard con dos procedimientos de monitorizacion, uno de entrada y otro de salida y lo encapsulo todo en una clase
        6) Utilizo interface con dos modport e introduzco todo lo relativo al clocking en su interior
Instrucciones de uso
      1) si quieres ver las formas de onda activa "Open EPwave afer run"
      2) si manejas questasim como simulador, activa "Use run.do Tcl file" y podrás verr con detalle grados de cobertura de aserciones y de covergroups

Un radicador realizado con un control-path y un data-path:
1) En el data-path destaca el reaprovechamiento del incrementador
2) En el control-path se ha hecho con un estilo de Moore de dos procesos
Un banco de pruebas realizado con:
1) RSCG para los valores de entrada,
2) con cobertura de los valores de entrada probados y una aserción inmediata de comparación con una radicador ideal
3) Introduzco los estimulos y la comprobacion de resultados con un program
4) introduzco un clocking block para sincronizar y lo establezo como bloque de reloj por defecto, con lo cual ya puedo utilizar el operador ##
5) Mejoro el scoreboard con dos procedimientos de monitorizacion, uno de entrada y otro de salida y lo encapsulo todo en una clase
6) Utilizo interface con dos modport e introduzco todo lo relativo al clocking en su interior

Instrucciones de uso
1) si quieres ver las formas de onda activa "Open EPwave afer run"
2) si manejas questasim como simulador, activa "Use run.do Tcl file" y podrás verr con detalle grados de cobertura de aserciones y de covergroups

141880:0