Académique Documents
Professionnel Documents
Culture Documents
// +-----------------------------+
`timescale 1 ns / 1 ps
input[63:0] analog_in;
// double-precision representation of a real-valued input port; a fix that enables // analog wires between modules to be coped with in Verilog. // Think of input[63:0] <variable> as the equivalent of MAST's electrical.
output[15:0] digital_out;
reg[15:0] delayed_digitized_signal; reg[15:0] old_analog,current_analog; reg[4:0] changed_bits; reg[19:0] charge; reg charge_ovr; reg reset_charge;
/* SIGNALS:analog_in = 64-bit representation of a real-valued signal analog_signal = real valued signal recovered from analog_in analog_limited = analog_signal, limited to the real-valued input range of the ADC digital_out = digitized 16bit 2's complement quantization of analog_limited */
/* function to convert analog_in to digitized_2s_comp_signal. Takes analog_in values from (+10.0 v - 1LSB) to -10.0 v and converts them to values from +32767 to -32768 respectively */
function[15:0] ADC_16b_10v_bipolar;
input[63:0] analog_in;
reg[15:0] digitized_2s_comp_signal;
begin analog_signal = $bitstoreal (analog_in); if (analog_signal < 0.0) begin analog_abs = -analog_signal; if (analog_abs > max_in_signal) analog_abs = max_in_signal; analog_limited = -analog_abs; end else begin analog_abs = analog_signal; if (analog_abs > max_in_signal) analog_abs = max_in_signal; analog_limited = analog_abs; end if (analog_limited == max_in_signal) digitized_signal = max_pos_digital_value; else digitized_signal = $rtoi (analog_limited * 3276.8); if (digitized_signal < 0) digitized_2s_comp_signal = 65536 - digitized_signal; else digitized_2s_comp_signal = digitized_signal; ADC_16b_10v_bipolar = digitized_2s_comp_signal; end
endfunction
/* This function determines the number of digital bit changes from sample to sample; can be used to determine power consumption if required. Task power_determine not yet implemented */
function[4:0] bit_changes;
input[15:0] old_analog,current_analog;
begin bits_different = 0; for (i=0;i<=15;i=i+1) if (current_analog[i] != old_analog[i]) bits_different = bits_different + 1; bit_changes = bits_different; end
endfunction
/* Block to allow power consumption to be measured (kind of). Reset_charge is used to periodically reset the charge accumulated value (which can be used to determine current consumption and thus power consumption) */
/* This block only triggered when analog_in changes by an amount greater than 1LSB, a crude sort of scheduler */
always @ (ADC_16b_10v_bipolar (analog_in)) begin current_analog = ADC_16b_10v_bipolar (analog_in); // digitized_signal changed_bits = bit_changes (old_analog,current_analog); old_analog = current_analog; charge = charge + (changed_bits * 3); if (charge > charge_limit) charge_ovr = 1; end
/* Block to implement conversion_time tpd; always block use to show difference between block and assign coding style */
endmodule ...
module adder_8bit_1(a,b,cin,out,carry); input input output output reg reg [7:0] [7:0] [7:0] a, cin; out; carry; out; carry; b;
endmodule ...
module s_adder(a,b,c_in,sum,c_out);
parameter length=16; input [length-1:0] a,b; input c_in; output c_out; output [length-1:0] sum; wire [length:1] c; full_adder full_adder full_adder full_adder full_adder full_adder full_adder full_adder full_adder full_adder full_adder full_adder full_adder full_adder full_adder full_adder p0 (a[0],b[0],c_in,sum[0],c[1]); p1 (a[1],b[1],c[1],sum[1],c[2]); p2 (a[2],b[2],c[2],sum[2],c[3]); p3 (a[3],b[3],c[3],sum[3],c[4]); p4 (a[4],b[4],c[4],sum[4],c[5]); p5 (a[6],b[5],c[5],sum[5],c[6]); p6 (a[6],b[6],c[6],sum[6],c[7]); p7 (a[7],b[7],c[7],sum[7],c[8]); p8 (a[8],b[8],c[8],sum[8],c[9]); p9 (a[9],b[9],c[9],sum[9],c[10]); p10 (a[10],b[10],c[10],sum[10],c[11]); p11 (a[11],b[11],c[11],sum[11],c[12]); p12 (a[12],b[12],c[12],sum[12],c[13]); p13 (a[13],b[13],c[13],sum[13],c[14]); p14 (a[14],b[14],c[14],sum[14],c[15]); p15 (a[15],b[15],c[15],sum[15],c_out );
endmodule
...
assign y=add_It_10(a,b);
endmodule ...
module binarytogray (clk, reset, binary_input, gray_output); input input output reg [3:0] [3:0] clk, reset; binary_input; gray_output; gray_output;
always @ (posedge clk or posedge reset) if (reset) begin gray_output <= 4'b0; end else begin gray_output[3] <= binary_input[3];
gray_output[2] <= binary_input[3] ^ binary_input[2]; gray_output[1] <= binary_input[2] ^ binary_input[1]; gray_output[0] <= binary_input[1] ^ binary_input[0]; end endmodule
module cla_8bits(a,b,c0,c8,s); input input output output reg reg reg reg always@(a or b or c0) begin p=a|b; q=a&b; [7:0] [7:0] [7:1] [7:0] [7:0] a,b; c0; c8; s; p,q; c; s; c8;
| | | | |
p[0]&c0; p[1]&q[0] p[2]&q[1] p[3]&q[2] p[4]&q[3] | | | | p[1]&p[0]&c0; p[2]&p[1]&q[0] p[3]&p[2]&q[1] p[4]&p[3]&q[2] | | | p[2]&p[1]&p[0]&c0; p[3]&p[2]&p[1]&q[0] p[4]&p[3]&p[2]&q[1] | | p[3]&p[2]&p[1]&p[0]&c0; p[4]&p[3]&p[2]&p[1]&q[0] |
p[5]&p[4]&p[3]&p[2]&p[1]&q[0] c[7]=q[6] |
p[6]&q[5] |
p[6]&p[5]&p[4]&p[3]&p[2]&q[1] c8 =q[7] |
p[6]&p[5]&p[4]&p[3]&p[2]&p[1]&q[0] | p[7]&p[6]&q[5] |
p[6]&p[5]&p[4]&p[3]&p[2]&p[1]&p[0]&c0; | p[7]&p[6]&p[5]&p[4]&q[3] | |
p[7]&q[6] |
p[7]&p[6]&p[5]&q[4] |
p[7]&p[6]&p[5]&p[4]&p[3]&q[2]
p[7]&p[6]&p[5]&p[4]&p[3]&p[2]&q[1]
p[7]&p[6]&p[5]&p[4]&p[3]&p[2]&p[1]&q[0]
p[7]&p[6]&p[5]&p[4]&p[3]&p[2]&p[1]&p[0]&c0;
endmodule
module compare(a,b,equal);
assign
equal=(a==b)?1:0;
endmodule ...
// // // This is just a little demo of DDS. // or anything.. // module dds ( clk, reset, It doesn't have any cool features
din,
dout );
parameter
W = 12;
clk; reset;
reg [W-1:0]
dout;
reg [W-1:0]
accum;
// Phas Accumulator
if (reset) accum <= 0; else begin accum <= accum + din; end end
endmodule
reg reg reg [11:0] wire [11:0] reg [7:0] din; dout; cosout;
clk; reset;
// Instantiate the DDS with 12-bits. // dds #(12) dds1 (.clk(clk), .reset(reset), .din(din), .dout(dout));
// DDS Phase Accumulator output simply indexes into the Cos lookup table. // always @(dout) cosout <= costable[dout];
// Main test thread. // initial begin $readmemh ("cos.hex", costable); // See the PERL program 'generate_cos_table.pl'
$finish; end
// Let's clock it at 1 MHz initial begin clk = 0; forever begin #500 clk = 1; #500 clk = 0; end end
// Generate VCD file for viewing. initial begin $dumpfile ("dds.vcd"); $dumpvars (0,ddstest); end endmodule
//***
`ifdef WHEN_PERL_IS_A_SUBSET_OF_VERILOG #!/tools2/perl/bin/perl # # # Generate a file of cos data for use by a DDS simulation.
$n
= 4096;
$pi = 3.1415927; $t = 0; for ($i = 1; $i < $n; $i = $i + 1) { $value = ($maxval - $minval)/2 + (($maxval - $minval)/2)*cos($t); $value = int($value); printf "%x\n", $value; $t = $t + 2*$pi / $n; }
`endif ...
assign #1 assign #1 assign #1 assign #2 assign #2 assign #2 assign #2 assign #2 assign #2 assign #2 assign #2
nota = ~a; notb = ~b; notc = ~c; z[0] = nota & notb & notc & en; z[1] = a & notb & notc & en; & notc & en; & notc & en; & en; & en; & en; & en;
z[4] = nota & notb & c z[5] = a & notb & c & c & c
parameter N = 16;
input input input input [N-1:0] a; input [N-1:0] b; output [N-1:0] output [N-1:0] output
clk; resetb; start; // Asynchronous, active low reset. // Pulse this to start the division.
// This is the number we are dividing (the dividend) // This is the 'divisor' q; r; done; // This is the 'quotient' // Here is the remainder. // Will be asserted when q and r are available.
// Registered q
q; done;
Power is a shifting
// '1' that starts at the highest power of 2 and goes all the way down // to ...00001 // reg [N-1:0] power; Shift this until it is zero at which point we stop.
// For each (divisor*2^N) term, we see if we can subtract (divisor*2^N) from the accumulator. // We subtract these terms as long as adding in the term doesn't cause the accumulator // to exceed a. // reg [N-1:0] accum; When we are done, whatever is left in the accumulator is the remainder.
// shifting it all the way to the left, and shifting it 1 bit at a time to the right. // reg [(2*N-1):0] bpower;
// Do this addition here for resource sharing. // ** Note that 'accum' is N bits wide, but bpower is 2*N-1 bits wide ** // wire [2*N-1:0] accum_minus_bpower = accum - bpower;
always @(posedge clk or negedge resetb) begin if (~resetb) begin q <= 0; accum <= 0; power <= 0; bpower <= 0; done <= 0; end else begin if (start) begin // Reinitialize the divide circuit. q accum <= 0; <= a; // Accumulator initially gets the dividend.
power[N-1] <= 1'b1; // We start with highest power of 2 (which is a '1' in MSB) bpower <= b << N-1; // Start with highest bpower, which is (divisor * 2^(N-1))
done <= 0; end else begin // Go until power is zero. // if (power != 0) begin // // Can we add this divisor*2^(power) to the accumulator without going negative? // Just test the MSB of the subtraction. // if ( ~accum_minus_bpower[2*N-1]) begin // Yes! Set this power of 2 in the quotieny and If it is '1', then it must be negative.
// then actually comitt to the subtraction from our accumulator. // q <= q | power;
accum <= accum_minus_bpower; end // Regardless, always go to next lower power of 2. // power <= power >> 1;
bpower <= bpower >> 1; end else begin // We're done. done <= 1; end end end end endmodule Set done flag.
// synopsys translate_off module test_div16; reg reg reg reg [15:0] reg [15:0] wire [15:0] wire [15:0] wire a; b; q; r; done; clk; resetb; start;
integer
num_errors;
div16 div16 ( .clk(clk), .resetb(resetb), .start(start), .a(a), .b(b), .q(q), .r(r), .done(done) );
start = 0;
// Do some divisions where divisor is constrained to 8-bits and dividend is 16-bits $display ("16-bit Dividend, 8-bit divisor"); repeat (25) begin do_divide ($random, $random & 255); end
// Do some divisions where divisor is constrained to 12-bits and dividend is 16-bits $display ("\n16-bit Dividend, 12-bit divisor"); repeat (25) begin do_divide ($random, $random & 4095); end
// Do some divisions where both divisor and dividend is 16-bits $display ("\n16-bit Dividend, 16-bit divisor"); repeat (25) begin do_divide ($random, $random); end
// Special cases $display ("\nSpecial Cases:"); do_divide (16'hFFFF, do_divide (312, do_divide ( 16'hFFFF); // largest possible quotient
1); // divide by 1
do_divide (312,
// That's all.
if (num_errors === 0) begin $display ("\n\nSUCCESS. end else begin $display ("\n\nFAILURE!! end There were %0d Errors.", num_errors); There were %0d Errors.", num_errors);
$finish; end
begin a = arga; b = argb; @(posedge clk); #1 start = 1; @(posedge clk); #1 start = 0; while (~done) @(posedge clk); #1;
$display ("Circuit: %0d / %0d = %0d, rem = %0d \t\t......... Reality: %0d, rem = %0d", arga, argb, q, r, a/b, a%b); if (b !== 0) begin if (q !== a/b) begin $display (" Error! Unexpected Quotient\n\n");
num_errors = num_errors + 1; end if (r !== a % b) begin $display (" Error! Unexpected Remainder\n\n");
end end
endmodule ...
endmodule
...
endmodule
// Synchronous FIFO. //
4 x 16 bit words.
module fifo (clk, rstp, din, writep, readp, dout, emptyp, fullp); input input input [15:0] input input output [15:0] dout; output output emptyp; fullp; din; readp; writep; clk; rstp;
// Defines sizes in terms of bits. // parameter DEPTH = 2, // 2 bits, e.g. 4 words in the FIFO. MAX_COUNT = 2'b11; // topmost address in FIFO.
reg reg
emptyp; fullp;
tail; head;
// is how we figure out things like Empty and Full. // reg [(DEPTH-1):0] count;
// Dout is registered and gets the value that tail points to RIGHT NOW.
// always @(posedge clk) begin if (rstp == 1) begin dout <= 16'h0000; end else begin dout <= fifomem[tail]; end end
// Update FIFO memory. always @(posedge clk) begin if (rstp == 1'b0 && writep == 1'b1 && fullp == 1'b0) begin fifomem[head] <= din; end end
// Update the head register. // always @(posedge clk) begin if (rstp == 1'b1) begin head <= 2'b00; end else begin if (writep == 1'b1 && fullp == 1'b0) begin // WRITE head <= head + 1; end end end
// Update the tail register. // always @(posedge clk) begin if (rstp == 1'b1) begin tail <= 2'b00; end else begin if (readp == 1'b1 && emptyp == 1'b0) begin // READ tail <= tail + 1; end end end
// Update the count regsiter. // always @(posedge clk) begin if (rstp == 1'b1) begin count <= 2'b00; end else begin case ({readp, writep}) 2'b00: count <= count; 2'b01: // WRITE if (count != MAX_COUNT) count <= count + 1; 2'b10: // READ if (count != 2'b00) count <= count - 1; 2'b11: // Concurrent read and write.. no change in count count <= count; endcase end end
// *** Update the flags // // First, update the empty flag. // always @(count) begin if (count == 2'b00) emptyp <= 1'b1; else emptyp <= 1'b0; end
// Update the full flag // always @(count) begin if (count == MAX_COUNT) fullp <= 1'b1; else
endmodule
// synopsys translate_off
reg reg reg [15:0] reg reg wire [15:0] wire wire dout; din;
clk; rstp;
readp; writep;
emptyp; fullp;
reg [15:0]
value;
fifo U1 ( .clk .rstp .din .readp .writep .dout .emptyp .fullp ); (readp), (writep), (dout), (emptyp), (fullp) (rstp), (din), (clk),
task read_word; begin @(negedge clk); readp = 1; @(posedge clk) #5; $display ("Read %0h from FIFO", dout); readp = 0; end endtask
task write_word; input [15:0] begin @(negedge clk); din = value; writep = 1; @(posedge clk); $display ("Write %0h to FIFO", din); #5; din = 16'hzzzz; writep = 0; end endtask value;
initial begin clk = 0; forever begin #10 clk = 1; #10 clk = 0; end end
//test1; test2;
// *** Write a bunch more values write_word (16'h0001); write_word (16'h0002); write_word (16'h0003); write_word (16'h0004); write_word (16'h0005); write_word (16'h0006); write_word (16'h0007); write_word (16'h0008);
// TEST2 // // This test will operate the FIFO in an orderly manner the way it normally works. // 2 threads are forked; a reader and a writer. The writer writes a counter to The reader likewise The result should be that The empty/full flags
// the FIFO and obeys the fullp flag and delays randomly. // obeys the emptyp flag and reads at random intervals.
// fixed number of times and then terminates both threads and kills the sim. // task test2; reg [15:0] writer_counter; begin writer_counter = 16'h0001; din = 16'hzzzz; writep = 0; readp = 0;
fork // Writer begin repeat (500) begin @(negedge clk); if (fullp == 1'b0) begin write_word (writer_counter); #5; writer_counter = writer_counter + 1; end else begin $display ("WRITER is waiting.."); end // Delay a random amount of time between 0ns and 100ns #(50 + ($random % 50)); end $display ("Done with WRITER fork.."); $finish; end
// Reader begin forever begin @(negedge clk); if (emptyp == 1'b0) begin read_word; end
else begin $display ("READER is waiting.."); end // Delay a random amount of time between 0ns and 100ns #(50 + ($random % 50)); end end join end endtask
module fifo(clock,reset,read,write,fifo_in,fifo_out,fifo_empty,fifo_half,fifo_full); input input output output [15:0] [15:0] clock,reset,read,write; fifo_in; fifo_out; fifo_empty,fifo_half,fifo_full;
fifo_empty,fifo_half,fifo_full;
always@(posedge clock) if(reset) begin read_ptr write_ptr counter fifo_out =0; =0; =0; =0;
end else
case({read,write}) 2'b00:counter=counter; 2'b01:begin ram[write_ptr]=fifo_in; counter=counter+1; write_ptr=(write_ptr==15)?0:write_ptr+1; end 2'b10:begin fifo_out=ram[read_ptr]; counter=counter-1; read_ptr=(read_ptr==15)?0:read_ptr+1; end 2'b11:begin if(counter==0) fifo_out=fifo_in; else begin ram[write_ptr]=fifo_in; fifo_out=ram[read_ptr]; write_ptr=(write_ptr==15)?0:write_ptr+1; read_ptr=(read_ptr==15)?0:read_ptr+1; end end endcase
endmodule ...
// data is sent in 188-byte frames which begin with a special SYNC character // defined as 47 hex. Framing must, of course, handle cases where 47s Framer must be able to find
// the period SYNC characters while not be thrown off by spurious SYNCs. // // This circuit uses a modulo-188 counter that serves as a timestamp. // Every received SYNC character causes the current modulo-188 counter // to be pushed onto a little queue. The idea is that the timestamps
If spurious
// false SYNC characters fall in the data, then some of the timestamps // will be different. // // This circuit is something I started to actually have to do, but then // I ended up not using it. It is not tested, so use it only for ideas This is OK as long as there is a clear majority.
// and not as a proven circuit!! // // tom coonan, 12/1999 // module framer (clk, resetb, din, dinstb, dout, doutsync, doutstb, locked); input input input [7:0] input output [7:0] output output output dout; doutsync; doutstb; locked; din; dinstb; clk; resetb;
/* Internals */
// Modulo-188 value when SYNCs are expected once locked. reg [7:0] syncindex;
// 6 deep queue of timestamps of every time a SYNC character is received. // the timestamp is the value of the modulo-188 counter when a SYNC is received. // reg [7:0] reg [7:0] reg [7:0] reg [7:0] reg [7:0] reg [7:0] t0; t1; t2; t3; t4; t5; // Newest timestamp // Oldest timestamp
// Modulo-188 free-running counter. // always @(posedge clk or negedge resetb) begin if (~resetb) begin cnt188 <= 0; end else begin if (dinstb) begin if (cnt188 == 187) begin cnt188 <= 0; end else begin cnt188 <= cnt188 + 1; end end end end
// Timestamp queue. // always @(posedge clk or negedge resetb) begin if (~resetb) begin t0 <= 8'hff; t1 <= 8'hff; t2 <= 8'hff; t3 <= 8'hff; t4 <= 8'hff; t5 <= 8'hff; end else begin if (dinstb && (din == SYNC)) begin // Add new timestamp into our queue. t0 <= t1; t1 <= t2; t2 <= t3; t3 <= t4; t4 <= t5; t5 <= cnt188; end end end // Let's use FF as an invalid indicator, otherwise // we'd potentially get a premature lock..
// Comparators.
wire t0equal = (t0 == cnt188) && (t0 != 8'hFF); wire t1equal = (t1 == cnt188) && (t1 != 8'hFF); wire t2equal = (t2 == cnt188) && (t2 != 8'hFF); wire t3equal = (t3 == cnt188) && (t3 != 8'hFF); wire t4equal = (t4 == cnt188) && (t4 != 8'hFF); wire t5equal = (t5 == cnt188) && (t5 != 8'hFF);
// Count number of matches in all the prior timestamps and current modulo-188 time. wire [3:0] numequal = t0equal + t1equal + t2equal + t3equal + t4equal + t5equal;
// Main sequential process. // always @(posedge clk or negedge resetb) begin if (~resetb) begin locked dout doutstb <= 0; <= 0; <= 0;
doutsync <= 0; syncindex <= 0; end else begin doutstb <= 0; // defaults..
doutstb <= 1; if (locked) begin if (cnt188 == syncindex) begin // We expect the data input to be a SYNC. // immediately drop lock. // if (din == SYNC) begin $display (".. Received expected SYNC .."); doutsync <= 1; end else begin locked <= 0; If it is not, we will
$display (".. Did not receive expected SYNC, dropping lock! "); end end end else begin // The following line is the criteria for declaring LOCK. // says that when a SYNC is recieved we look at the current It
// timestamp, and if this timestamp is present in at least // 4 other times in the queue, than this SYNC is an actual SYNC. // if ((din == SYNC) && (numequal > 3)) begin doutsync <= 1; locked <= 1;
syncindex <= cnt188; $display (".. Received SYNC (cnt188=%0h) and declaring LOCK!", cnt188); end end end end end
endmodule
reg reg reg [7:0] reg wire [7:0] wire wire wire dout; din;
clk; resetb;
dinstb;
// Instantiate the framer framer framer ( .clk(clk), .resetb(resetb), .din(din), .dinstb(dinstb), .dout(dout), .doutsync(doutsync), .doutstb(doutstb), .locked(locked) );
genclock; begin gendata (20); $display ("Done sending good framed data, now sending trash.."); genradomdata (188*3); // 3 frames worth of trash.. should drop lock. Killing simulation.");
// Generate VCD file for viewing. initial begin $dumpfile ("framer.vcd"); $dumpvars (0,test); end
// Just a generic task for watching total cycles. task monitor_cycles; input integer integer begin forever begin @(posedge clk); cycles = cycles + 1; if (cycles > maxcycles) begin $finish; end end end endtask maxcycles; maxcycles; cycles;
// This is the pattern that will be injected into framer. // task monitor_framer_output; integer integer begin numerrors = 0; forever begin @(posedge doutstb); cnt; numerrors;
#1; if (doutsync) begin $display ("Framer says SYNC.."); cnt = 1; repeat (4) begin @(posedge doutstb); #1 $display (" and %h..", dout);
if (dout != cnt) begin numerrors = numerrors + 1; $display ("!! Unexpected data from framer !! (%0d errors)", numerrors); end cnt = cnt + 1; end end end end endtask
task genreset; begin resetb = 0; repeat (2) @(posedge clk); @(negedge clk); resetb = 1; end endtask
task genclock; begin clk = 0; forever begin #10 clk = ~clk; end end endtask
// a simple counting sequence that can then be checked at its output. // task gendata; input numframes;
integer
numframes;
integer begin
cnt;
cnt = $random;
repeat (numframes*188) begin repeat (3) @(posedge clk); if (cnt == 0) begin din = 8'h47; $display ("SYNC.."); end else begin if (cnt < 5) begin din = cnt; end else begin din = $random; if (din == 8'h47) begin $display (" end end end .. Non-SYNC 0x47 embedded in frame data !");
dinstb = 1; @(posedge clk); dinstb = 0; cnt = (cnt + 1) % 188; end end endtask
// This will inject trash (no good framing) into framer. // that it actually drops lock. // task genradomdata; input integer begin repeat (numbytes) begin repeat (3) @(posedge clk); din = $random; dinstb = 1; @(posedge clk); dinstb = 0; end numbytes; numbytes;
end endtask
/ Synchronous FIFO. //
4 x 16 bit words.
module fifo (clk, rstp, din, writep, readp, dout, emptyp, fullp); input input input [15:0] input input output [15:0] dout; output output emptyp; fullp; din; readp; writep; clk; rstp;
// Defines sizes in terms of bits. // parameter DEPTH = 2, // 2 bits, e.g. 4 words in the FIFO. MAX_COUNT = 2'b11; // topmost address in FIFO.
reg reg
emptyp; fullp;
tail; head;
// is how we figure out things like Empty and Full. // reg [(DEPTH-1):0] count;
// Dout is registered and gets the value that tail points to RIGHT NOW. // always @(posedge clk) begin if (rstp == 1) begin dout <= 16'h0000; end else begin dout <= fifomem[tail]; end end
// Update FIFO memory. always @(posedge clk) begin if (rstp == 1'b0 && writep == 1'b1 && fullp == 1'b0) begin fifomem[head] <= din; end end
// Update the head register. // always @(posedge clk) begin if (rstp == 1'b1) begin head <= 2'b00; end else begin if (writep == 1'b1 && fullp == 1'b0) begin // WRITE head <= head + 1; end end end
// Update the tail register. // always @(posedge clk) begin if (rstp == 1'b1) begin tail <= 2'b00; end else begin if (readp == 1'b1 && emptyp == 1'b0) begin // READ tail <= tail + 1; end end
end
// Update the count regsiter. // always @(posedge clk) begin if (rstp == 1'b1) begin count <= 2'b00; end else begin case ({readp, writep}) 2'b00: count <= count; 2'b01: // WRITE if (count != MAX_COUNT) count <= count + 1; 2'b10: // READ if (count != 2'b00) count <= count - 1; 2'b11: // Concurrent read and write.. no change in count count <= count; endcase end end
// *** Update the flags // // First, update the empty flag. // always @(count) begin if (count == 2'b00) emptyp <= 1'b1; else emptyp <= 1'b0; end
// Update the full flag // always @(count) begin if (count == MAX_COUNT) fullp <= 1'b1;
endmodule
// synopsys translate_off
reg reg reg [15:0] reg reg wire [15:0] wire wire dout; din;
clk; rstp;
readp; writep;
emptyp; fullp;
reg [15:0]
value;
fifo U1 ( .clk .rstp .din .readp .writep .dout .emptyp .fullp ); (readp), (writep), (dout), (emptyp), (fullp) (rstp), (din), (clk),
task read_word; begin @(negedge clk); readp = 1; @(posedge clk) #5; $display ("Read %0h from FIFO", dout); readp = 0; end endtask
task write_word; input [15:0] begin @(negedge clk); din = value; writep = 1; @(posedge clk); $display ("Write %0h to FIFO", din); #5; din = 16'hzzzz; writep = 0; end endtask value;
initial begin clk = 0; forever begin #10 clk = 1; #10 clk = 0; end end
//test1; test2;
#50;
// *** Write a bunch more values write_word (16'h0001); write_word (16'h0002); write_word (16'h0003); write_word (16'h0004); write_word (16'h0005); write_word (16'h0006); write_word (16'h0007); write_word (16'h0008);
// TEST2 // // This test will operate the FIFO in an orderly manner the way it normally works. // 2 threads are forked; a reader and a writer. The writer writes a counter to The reader likewise The result should be that
// the FIFO and obeys the fullp flag and delays randomly. // obeys the emptyp flag and reads at random intervals.
// the reader reads the incrementing counter out of the FIFO. // should bounce around depending on the random delays.
// fixed number of times and then terminates both threads and kills the sim. // task test2; reg [15:0] writer_counter; begin writer_counter = 16'h0001; din = 16'hzzzz; writep = 0; readp = 0;
fork // Writer begin repeat (500) begin @(negedge clk); if (fullp == 1'b0) begin write_word (writer_counter); #5; writer_counter = writer_counter + 1; end else begin $display ("WRITER is waiting.."); end // Delay a random amount of time between 0ns and 100ns #(50 + ($random % 50)); end $display ("Done with WRITER fork.."); $finish; end
// Reader begin forever begin @(negedge clk); if (emptyp == 1'b0) begin read_word;
end else begin $display ("READER is waiting.."); end // Delay a random amount of time between 0ns and 100ns #(50 + ($random % 50)); end end join end endtask
endmodule `endif
/////////////////////////////////////////////////////////////////////////////// //This module is used to change the 50Mhz frequency to 20Mhz.///////////////// //Xiaoming,Chen,31,july,2002.///////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
`timescale 1ns/100ps module frequency5x2(in,out,rst); input in,rst; output out; reg out; reg mid; integer counter; parameter delaytime=25; always@(posedge rst )
begin counter=0;
out=0; mid=0; end always@(posedge in) begin if(counter==4) begin mid=~mid; counter=0; end else counter=counter+1; end
always@(negedge in) begin if(counter==4) begin mid=~mid; counter=0; end else counter=counter+1; end
always@(posedge mid ) begin out=~out; #delaytime out=~out; end always@(negedge mid) begin out=~out; #delaytime out=~out; end
endmodule
reg clock,reset;
frequency5x2 t(clock,out,reset);
endmodule ...
//
// Behavioral Verilog for CRC16 and CRC32 for use in a testbench. // // The specific polynomials and conventions regarding bit-ordering etc. // are specific to the Cable Modem DOCSIS protocol, but the general scheme // should be reusable for other types of CRCs with some fiddling. // // This CRC code works for a specific type of network protocol, and it // must do certain byte swappings, etc. // for your protocol. // really want. You may need to play with it
// in a testbench at one point. // // These tasks are crude and rely on some global parameters. // also read from a file, yada yada yada. They should
// with a PLI call, but here it is anyway.. // // The test case includes a golden DOCSIS (Cable Modem) test message that // was captured in a lab. // // tom coonan, 1999. // module test_gencrc;
// *** Buffer for the Golden Message *** reg [7:0] test_packet[0:54];
// *** Global parameter block for the CRC32 calculator. // parameter reg [ 7:0] integer reg [31:0] crc32_result; CRC32_POLY = 32'h04C11DB7; crc32_packet[0:255]; crc32_length;
// *** Global parameter block for the CRC16 calculator. // parameter reg [ 7:0] integer reg [15:0] crc16_result; CRC16_POLY = 16'h1020; crc16_packet[0:255]; crc16_length;
`define TEST_GENCRC `ifdef TEST_GENCRC // Call the main test task and then quit. //
// **************************************************************** // * // * // * // * // * // * // * // * // **************************************************************** // task initialize_test_packet; begin test_packet[00] = 8'hC2; test_packet[01] = 8'h00; test_packet[02] = 8'h00; test_packet[03] = 8'h30; test_packet[04] = 8'hF2; test_packet[05] = 8'hCF; test_packet[06] = 8'h01; test_packet[07] = 8'hE0; test_packet[08] = 8'h2F; test_packet[09] = 8'h00; test_packet[10] = 8'h00; test_packet[11] = 8'h01; test_packet[12] = 8'h00; test_packet[13] = 8'h80; test_packet[14] = 8'h42; test_packet[15] = 8'h42; test_packet[16] = 8'h20; test_packet[17] = 8'h9E; test_packet[18] = 8'h00; test_packet[19] = 8'h1E; test_packet[20] = 8'h00; test_packet[21] = 8'h00; test_packet[22] = 8'h03; test_packet[23] = 8'h01; test_packet[24] = 8'h03; // FC. HCS coverage starts here. The golden message is a DOCSIS frame that was captured off the Broadcom reference design. It is a MAP message. It GOLDEN MESSAGE
// MACPARAM // MAC LEN // MAC LEN. HCS Coverage includes this byte and ends here.
// CRC16 (also known as HCS) // CRC16 cont.. // Start of the IEEE payload. // DA field cont.. // DA field cont.. // DA field cont.. // DA field cont.. // DA field cont.. // SA field // SA field cont.. // SA field cont.. // SA field cont.. // SA field cont.. // SA field cont.. // IEEE LEN field // IEEE LEN field cont. // LLC field. // LLC field cont... // LLC field cont... // LLC field cont... // LLC field cont... This is also the TYPE, which indicates MAP. CRC32 covererage starts here. This is the DA field
test_packet[25] = 8'h00; test_packet[26] = 8'h01; test_packet[27] = 8'h01; test_packet[28] = 8'h02; test_packet[29] = 8'h00; test_packet[30] = 8'h00; test_packet[31] = 8'h18; test_packet[32] = 8'hAA; test_packet[33] = 8'h58; test_packet[34] = 8'h00; test_packet[35] = 8'h18; test_packet[36] = 8'hA8; test_packet[37] = 8'hA0; test_packet[38] = 8'h02; test_packet[39] = 8'h03; test_packet[40] = 8'h03; test_packet[41] = 8'h08; test_packet[42] = 8'hFF; test_packet[43] = 8'hFC; test_packet[44] = 8'h40; test_packet[45] = 8'h00; test_packet[46] = 8'h00; test_packet[47] = 8'h01; test_packet[48] = 8'hC0; test_packet[49] = 8'h14; test_packet[50] = 8'hDD; test_packet[51] = 8'hBF; test_packet[52] = 8'hC1; test_packet[53] = 8'h2E; end endtask
// LLC field cont... // Start of MAP message payload. // MAP message payload.. // MAP message payload.. // MAP message payload.. // MAP message payload.. // MAP message payload.. // MAP message payload.. // MAP message payload.. // MAP message payload.. // MAP message payload.. // MAP message payload.. // MAP message payload.. // MAP message payload.. // MAP message payload.. // MAP message payload.. // MAP message payload.. // MAP message payload.. // MAP message payload.. // MAP message payload.. // MAP message payload.. // MAP message payload.. // MAP message payload.. // MAP message payload.. // Last byte of MAP payload, last byte covered by CRC32. // CRC32 Starts here // CRC32 cont.. // CRC32 cont.. // Last byte of CRC32, last byte of DOCSIS.
// ************************************************************************* // * // * // * // * // * // * // * // ************************************************************************* // task main_test; integer i, j; Use our primary "golden packet". Copy into the generic global Main test task.
variables that the low-level 'gencrc16' and 'gencrc32' tasks use. Comare against the expected values and report SUCCESS or FAILURE.
integer
num_errors;
num_errors = 0;
// **** TEST CRC16 // $display ("Testing CRC16:"); // // Copy golden test_packet into the main crc16 buffer.. for (i=0; i<4; i=i+1) begin crc16_packet[i] = test_packet[i]; end crc16_expected = {test_packet[4], test_packet[5]}; crc16_length = 4; gencrc16; // Must tell test function the length
// Call main test function Actual crc16_result = %h, Expected = %h", crc16_result, crc16_expected);
$display ("
if (crc16_result == crc16_expected) begin $display (" end else begin $display (" ERROR!!!"); Success.");
// **** TEST CRC16 // $display ("Testing CRC32:"); j = 0; for (i=6; i<50; i=i+1) begin crc32_packet[j] = test_packet[i]; j = j + 1; end crc32_expected = {test_packet[50], test_packet[51], test_packet[52], test_packet[53]}; crc32_length = 44; gencrc32; $display (" Actual crc32_result = %h, Expected = %h", crc32_result, crc32_expected);
Success.");
ERROR!!!");
// **************************************************************** // * // * // * // * // * // **************************************************************** These tasks rely on some globals (see front of program). Main working CRC tasks are: gencrc16, gencrc32.
// Generate a (DOCSIS) CRC16. // // Uses the GLOBAL variables: // // // // // // // // // task gencrc16; integer reg reg [7:0] current_byte; byte, bit; msb; Globals modified: reg [15:0] crc16_result; Globals referenced: parameter reg [ 7:0] integer CRC16_POLY = 16'h1020; crc16_packet[0:255]; crc16_length;
reg [15:0] temp; begin crc16_result = 16'hffff; for (byte = 0; byte < crc16_length; byte = byte + 1) begin current_byte = crc16_packet[byte]; for (bit = 0; bit < 8; bit = bit + 1) begin
msb = crc16_result[15]; crc16_result = crc16_result << 1; if (msb != current_byte[bit]) begin crc16_result = crc16_result ^ CRC16_POLY; crc16_result[0] = 1; end end end
// Last step is to "mirror" every bit, swap the 2 bytes, and then complement each bit. // // Mirror: for (bit = 0; bit < 16; bit = bit + 1) temp[15-bit] = crc16_result[bit];
// Generate a (DOCSIS) CRC32. // // Uses the GLOBAL variables: // // // // // // // // // Globals modified: reg [31:0] crc32_result; Globals referenced: parameter reg [ 7:0] integer CRC32_POLY = 32'h04C11DB7; crc32_packet[0:255]; crc32_length;
task gencrc32; integer reg reg [7:0] current_byte; byte, bit; msb;
reg [31:0] temp; begin crc32_result = 32'hffffffff; for (byte = 0; byte < crc32_length; byte = byte + 1) begin current_byte = crc32_packet[byte]; for (bit = 0; bit < 8; bit = bit + 1) begin
msb = crc32_result[31]; crc32_result = crc32_result << 1; if (msb != current_byte[bit]) begin crc32_result = crc32_result ^ CRC32_POLY; crc32_result[0] = 1; end end end
// Last step is to "mirror" every bit, swap the 4 bytes, and then complement each bit. // // Mirror: for (bit = 0; bit < 32; bit = bit + 1) temp[31-bit] = crc32_result[bit];
// Swap and Complement: crc32_result = ~{temp[7:0], temp[15:8], temp[23:16], temp[31:24]}; end endtask
endmodule module half_adder(a,b,out,carry); input a,b; output out,carry; assign {carry,out}=a+b; endmodule ...
module half_adder(a,b,out,carry); input a,b; output out,carry; assign out=a^b; assign carry=a&b; endmodule ...
module half_adder(a,b,out,carry); input a,b; output out,carry; xor n1(out,a,b); and n2(carry,a,b); endmodule ...
module lead_8bits_adder(a,b,cin,sum,cout);
reg reg
[7:0]sum; cout;
always@(a or b or cin) begin sum[0]=(a[0]&b[0])| sum[1]=(a[1]&b[1])| sum[2]=(a[2]&b[2])| sum[3]=(a[3]&b[3])| sum[4]=(a[4]&b[4])| sum[5]=(a[5]&b[5])| sum[6]=(a[6]&b[6])| sum[7]=(a[7]&b[7])| (a[0]| b[0])&cin; (a[1]| b[1])&((a[0]^b[0])^cin); (a[2]| b[2])&((a[1]^b[1])^(a[0]^b[0])^cin); (a[3]| b[3])&((a[2]^b[2])^(a[1]^b[1])^(a[0]^b[0])^cin); (a[4]| b[4])&((a[3]^b[3])^(a[2]^b[2])^(a[1]^b[1])^(a[0]^b[0])^cin); (a[5]| b[5])&((a[4]^b[4])^(a[3]^b[3])^(a[2]^b[2])^(a[1]^b[1])^(a[0]^b[0])^cin); (a[6]| b[6])&((a[5]^b[5])^(a[4]^b[4])^(a[3]^b[3])^(a[2]^b[2])^(a[1]^b[1])^(a[0]^b[0])^cin); (a[7]| b[7])&((a[6]^b[6])^(a[5]^b[5])^(a[4]^b[4])^(a[3]^b[3])^(a[2]^b[2])^(a[1]^b[1])^(a[0]^b[0])^cin);
cout=(a[7]^b[7])^(a[6]^b[6])^(a[5]^b[5])^(a[4]^b[4])^(a[3]^b[3])^(a[2]^b[2])^(a[1]^b[1])^(a[0]^b[0])^cin; end
endmodule
module lead_8bits_adder(a,b,cin,sum,cout); input input output output [7:0]a,b; cin; [7:0]sum; cout;
reg reg
[7:0]sum; cout;
always@(a or b or cin) begin sum[0]=(a[0]&b[0])| sum[1]=(a[1]&b[1])| sum[2]=(a[2]&b[2])| sum[3]=(a[3]&b[3])| sum[4]=(a[4]&b[4])| sum[5]=(a[5]&b[5])| sum[6]=(a[6]&b[6])| sum[7]=(a[7]&b[7])| (a[0]| b[0])&cin; (a[1]| b[1])&(a[0]^b[0]^cin); (a[2]| b[2])&(a[1]^b[1]^a[0]^b[0]^cin); (a[3]| b[3])&(a[2]^b[2]^a[1]^b[1]^a[0]^b[0]^cin); (a[4]| b[4])&(a[3]^b[3]^a[2]^b[2]^a[1]^b[1]^a[0]^b[0]^cin); (a[5]| b[5])&(a[4]^b[4]^a[3]^b[3]^a[2]^b[2]^a[1]^b[1]^a[0]^b[0]^cin); (a[6]| b[6])&(a[5]^b[5]^a[4]^b[4]^a[3]^b[3]^a[2]^b[2]^a[1]^b[1]^a[0]^b[0]^cin); (a[7]| b[7])&(a[6]^b[6]^a[5]^b[5]^a[4]^b[4]^a[3]^b[3]^a[2]^b[2]^a[1]^b[1]^a[0]^b[0]^cin);
cout=a[7]^b[7]^a[6]^b[6]^a[5]^b[5]^a[4]^b[4]^a[3]^b[3]^a[2]^b[2]^a[1]^b[1]^a[0]^b[0]^cin; end
endmodule ...
module mult16(clk,resetb,start,done,ain,bin,yout); parameter N=16; input input input input input [N-1:0] [N-1:0] clk; resetb; start; ain; bin; yout; done; [2*N-1:0] [N-1:0] [2*N-1:0] a; b; yout; done;
always@(posedge clk or negedge resetb) begin if(~resetb) begin a<=0; b<=0; yout<=0; done<=1'b1; end
// Not very well tested, play with testbench, use at your own risk, blah blah blah.. //
// // Unsigned 16-bit multiply (multiply two 16-bit inputs to get a 32-bit output) // // Present data and assert start synchronous with clk. // Assert start for ONLY one cycle. // Wait N cycles for answer (at most). Answer will remain stable until next start.
// You may use DONE signal as handshake. // // Written by tom coonan // module mult16 (clk, resetb, start, done, ain, bin, yout); parameter N = 16; input input input input [N-1:0] input [N-1:0] output [2*N-1:0] output ain; bin; yout; done; clk; resetb; start; // Register the ain and bin inputs (they can change afterwards)
reg [2*N-1:0]
a;
b; yout;
reg
done;
always @(posedge clk or negedge resetb) begin if (~resetb) begin a <= 0; b <= 0; yout <= 0; done <= 1'b1; end else begin // Load will register the input and clear the counter. if (start) begin a b <= ain; <= bin;
yout <= 0; done <= 0; end else begin // Go until b is zero if (~done) begin if (b != 0) begin // If '1' then add a to sum if (b[0]) begin yout <= yout + a; end b <= b >> 1; a <= a << 1; //$display ("a = %b, b = %b, yout = %b", a,b,yout); end else begin done <= 1'b1; end end end end end endmodule
module testmult16; reg clk, resetb, start; reg [15:0] a; reg [15:0] b; wire [31:0] y; wire done;
initial begin clk = 0; forever begin #10 clk = ~clk; end end
#100;
// Do a bunch of random multiplies repeat (MAX_TRIALS) begin test_multiply ($random, $random); end
// Special cases test_multiply ($random, 1); test_multiply (1, $random); test_multiply ($random, 0); test_multiply (0, $random);
$display ("Done.
integer expected_answer;
begin if (~done) begin $display ("Multiplier is Busy!!"); end else begin @(negedge clk); start = 1; a = aarg; b = barg; @(negedge clk) start = 0; @(posedge done); expected_answer = a*b; $display ("%0d * %0d = %0h, Reality = %0h", a, b, y, expected_answer); if (y !== expected_answer) begin $display (" FAILURE!");
module mult_select(a,b,select,out); parameter size=8; input input output reg [size-1:0]a,b; select; [size-1:0]out; [size-1:0]out;
endmodule ...
module mult_piped_8x8_2sC(a,b,clk,reset,y);
always@(posedge clk) begin aR[7] bR[7] yR[7] aR[6] bR[6] yR[6] aR[5] bR[5] yR[5] aR[4] bR[4] yR[4] aR[3] bR[3] yR[3] aR[2] bR[2] yR[2] aR[1] bR[1] yR[1] = = = = = = = = = = = = = = = = = = = = = aR[6]; bR[6]; yR[6]; aR[5]; bR[5]; yR[5]; aR[4]; bR[4]; yR[4]; aR[3]; bR[3]; yR[3]; aR[2]; bR[2]; yR[2]; aR[1]; bR[1]; yR[1]; aR[0]; bR[0]; yR[0]; (a*b) appears after +clk
//muliply result
end
function[15:0] multiply_8x8_2sC; input [7:0] a,b; reg reg reg [7:0] a_mag,b_mag; [14:0] Y_mag; [14:0] Y_neg;
=128-a[6:0];
case
=128-b[6:0];
endcase
assign endmodule
y=yR[7];
`include "oc8051_defines.v"
module oc8051_alu_src1_sel (sel, immediate, acc, ram, ext, des); // // sel // immediate // acc // ram // ext // des // (in) (in) (in) (in) (in) select signals (from decoder, delayd one clock) [oc8051_decoder.src_sel1 -r] immediate operand [oc8051_immediate_sel.out1] accomulator [oc8051_acc.data_out] ram input [oc8051_ram_sel.out_data] external ram input [pin]
input [1:0] sel; input [7:0] immediate, acc, ram, ext; output [7:0] des; reg [7:0] des;
always @(sel or immediate or acc or ram or ext) begin case (sel) `OC8051_ASS_RAM: des= ram; `OC8051_ASS_ACC: des= acc; `OC8051_ASS_XRAM: des= ext; `OC8051_ASS_IMM: des= immediate; default: des= 2'bxx; endcase end
endmodule
reg
[longsize-1:0]out;
always
@(a or b)
/ RANDOM Number generator (hardware friendly) // // LFSR Register for a maximal length P/N sequence of 2^32: // // Taken from XILINX App Note XAPP 052. // // Taps for 32-bit sequence are at: // // // Feed XNOR of tapped bits into LSB of left-shifted register. // // Ideas for testing: // // // // // // // // // // // // // // // // Should print '16'. Do this for as many values as you can think of. 2. grep -c 0000001A myrand.out This write 4096 numbers to the file. repeat 16 times. The 256 element sequence should For example, for the 8-bit sequence, 1. myrand FFF >! myrand.out 31,21,1,0
Searching for 000000FF should yield ZERO, however. For the 32-bit seqence, you don't want to generate 4 billion values. Instead,
generate as many as you can (e.g. myrand 000FFFFF, which will generate 1 million). Open the file in an editor, randomly pick values, and then do the grep for that same value. Grep should print exactly '1' for each such example.
#include <stdio.h>
// Generate a constant array specifying where the TAPs are. // Fill this in from some LFSR Maximal Sequence table, such // as is found in the XILINX app note. // // This particular program is limitied to 32-bit sequences since we are // using simple unsigned long int variable, but can be extended. // Note's table goes up to 168 bits. // The XAPP
// TAPS. //
// Indicate width.
#define WIDTH 32
// XILINX App Note says to use zero. // and should never be reached. //
#define SEED 0
int main (int argc, char *argv[]) { unsigned long int x; int i, j; unsigned long int masks[32]; unsigned long int feedback; unsigned long int n_points; unsigned long int width;
if (argc == 1) { printf ("\n"); printf ("Usage:\n"); printf (" myrand <# points in hex>\n");
printf ("\n"); printf ("Example:\n"); printf (" myrand FFF ; Generate 4096 points\n");
printf ("\n"); printf ("Notes:\n"); printf (" At this time, you must change source code for different lengths..\n");
printf ("\n"); printf ("Currently, Taps are:\n"); for (j = 0; taps[j] != -1; j++) { printf ("%ld ", taps[j]); } printf ("\n"); return 1; }
x = SEED;
// Based on the taps array, generate each XOR term. Remember, -1 signifies the end.
feedback = 0; for (j = 0; taps[j] != -1; j++) {
// FOR Debug: // // printf ("x = %08lx, taps[j] = %ld, masks[taps[j]] = %08lx, (x & masks[taps[j]]) = %l08x\n", x, taps[j], masks[taps[j]], (x & masks[taps[j]]) );
feedback ^= (x & masks[taps[j]]) ? 0x00000001 : 0x00000000; }
// In hardware, this'll be more straight-forward, e.g. for the 32-bit case: // assign feedback = ~^{x[31],x[21],x[1],x[0]};
// //
x &= width;
//
/* Here's the Verilog for reference... // Random Number Generator, 8-bit // // See companion program myrand.c // // (to verify, do the GREP trick described in myrand.c on verilog.out) // module myrand;
// Use TAPS table from XACT 052 to make whatever length sequence you need. assign feedback = ~^{x[7],x[5],x[4],x[3]};
// Shift and input feedback term. always @(posedge clk) begin if (reset) x <= 0; else end
That's it!
// remaining code just testbench... initial begin clk = 0; forever begin #10 clk = ~clk;
end end
initial begin @(negedge reset); repeat (1024) begin @(posedge clk) #1; $display ("%h", x); end $finish; end endmodule
NCO Demo (Numerically controlled Oscillator). // // One type of NCO is based on the idea of a continuously wrapping modulo // counter. The NCO is a programmable modulo counter. For example, if
// the MOD input is set to 10, then it'll count 0,1,2,3,4,5,6,7,8,9,0,1,2 etc. // The STEP input is continuously added to the modulo counter. What's important If
// is not the counter value itself, but the number of times it "wraps".
// you do the math, the counter will wrap at a rate of F*S/M (F is the system // clock frequency, S is the step input, and M is the modulo). // occurance is a little pulse. Every wrap
The pulse output could be used as the clock itself Instead, take the WRAP The TICKS counter will
// pulse signal and use it to increment a TICKS counter. // then count at the programmed frequency. //
// The TICK counter could be used in itself for, say, a TDMA slot counter. // number of TICKS LSB bits can be thrown away to "reduce jitter" but also // reduce the rate.
Any
// so you can pick off whichever TICKS bits you wish for your final FOUT output. // // In an open-loop mode, you program your Modulo and Step inputs and you are done. // If you are tracking some other reference (e.g. like in a PLL style circuit) you // would somehow control STEP via some sort of "phase detector" and loop filter.
// None of this is shown here. // // Anyway, this is just the guts of the NCO, which can be applied in many, many // ways. // // Oh.. And this NCO seems to be off by a small percentage..?!.. // why. It may be the circuit or the testbench. I'm not sure
// to figure it out. // // Written by tom coonan // module nco ( clk, resetb, step, mod, mask, ticks, fout ); // Step input is continuously added to the modulo counter // modulo // Mask is ANDed with ticks and gen ORed to produce fout // Tick counter output // Output.
parameter W_ACCUM = 24; // Width of the Accumulator parameter W_TICK parameter W_STEP parameter W_MOD = 8; // Width of the Tick counter. = 24; = 24;
input input input [W_STEP-1:0] input [W_MOD-1:0] input [W_TICK-1:0] output [W_TICK-1:0] output step; mod; mask; ticks;
clk; resetb;
fout;
// Registered outputs
sum = accum + step; rem = sum - mod; over = (sum >= mod);
always @(posedge clk or negedge resetb) if (~resetb) accum <= 0; else accum <= accum_in;
always @(over or rem or sum) begin if (over) begin // Wrap! accum_in <= rem; // load remainder instead of sum wrap <= 1; end else begin // No wrap, just add accum_in <= sum; wrap <= 0; end end
// *** Tick Counter *** // always @(posedge clk) begin if (~resetb) ticks <= 0; else begin // Whenever Modulo counter wraps, increment the tick counter. if (wrap) ticks <= ticks + 1; end end
endmodule
module ncotest;
clk; resetb;
parameter W_ACCUM = 24; // Width of the Accumulator parameter W_TICK parameter W_STEP parameter W_MOD = 8; // Width of the Tick counter. = 24; = 24;
real
sys_freq;
initial begin step = 0; mod = 0; mask = 8'b00000001; // Final Divider for FOUT
sys_freq = 1000000000.0/(PERIOD_NS);
#300;
// Display the basic such as system clock frequency, etc. // $display ("NCO Test. W_ACCUM, PERIOD_NS, sys_freq ); NCO Accumulator width is %0d bits, system clock period is %0d ns (%fMHz).",
Find the ratio of S/M, integerize it, and reduce to lowest Then, multiply up by a big power of 2 so we can get some
// Let's generate 1Mhz, Fsys*(Step/Mod)/2 = 27777777.777*(S/M)/2 = 1000000 // // mod = 125 << 12; // Shift up so we get resolution.. 9 << 12; // Shift up so we get resolution.. S/M = 0.072 = 72/1000 = 9/125 (9 * 2^12) / (125 * 2^12)
step =
nco_test (mod, step, 1000000); // Run test for specified interval (units are NS)
// Generate 10.24MHz: Fsys*(Step/Mod)/2 = 27777777.777*(S/M)/2 = 10240000 // // mod = 3125 << 10; // Shift up so we get resolution.. S/M = 0.73728 = 73728/100000 = 9216/12500 = 4608/6250 = 2304/3125
step = 2304 << 10; // Shift up so we get resolution.. nco_test (mod, step, 1000000); // Run test for specified interval (units are NS)
// Generate 32.768 KHz using TICKS MSB (divide by 8): // // // mask = 8'b10000000; // Divide by 256 mod = 500 << 12; // Manually Tweaked this to get the right number.. // this is expected since didn't have a good integer // ratio above.. nco_test (mod, step, 1000000); // Run test for specified interval (units are NS) Fsys*(Step/Mod) = 27777777.777*(S/M) = 32768*256 S/M = 0.301989888 =~ 0.302 = 302/1000 = 151/500
$display ("Done.");
$finish; end
// Run a single trial of the NCO test. // task nco_test; input [23:0] mod_arg; input [23:0] step_arg; input interval;
integer integer
interval; start_time;
// Use $time..
integer
fout_edges;
// Count rising edges on FOUT which is the output frequency fout_edges = 0; start_time = $time; // Note our starting time // Loop for at least the specified amount of time while ( ($time - start_time) < interval) begin @(posedge fout); // Wait for an edge on FOUT fout_edges = fout_edges + 1; end
// Done.
$display ("For Mod=%0d(0x%h), Step=%0d(0x%h), Frequency of fout = %f Hz, Expected fout is %f Hz.", mod, mod, step, step, ((fout_edges*1.0)/($time - start_time))*1000000000.0, // measured.. ((step*1.0)/(mod*1.0))*(sys_freq)/(mask*2.0) ); end endtask // expected..
// Let's clock it at about 27 MHz initial begin clk = 0; forever begin #(PERIOD_NS/2) clk = ~clk; end end
initial begin if (DUMP_ON) begin $dumpfile ("nco.vcd"); $dumpvars (0,ncotest); end end endmodule
// Just a little demo of some FSM techniques, including One-Hot and // using 'default' settings and the case statements to selectively // update registers (sort of like J-K flip-flops). // // tom coonan, 12/98. // module onehot (clk, resetb, a, b, x, y);
input clk; input resetb; input [7:0] a; input [7:0] b; output [7:0] x; output [7:0] y;
Declare the register itself (e.g. 'x') and then The 'x_in' bus will
// physically be a wire bus and 'x' will be the flip-flop register ('x_in' must // be declared 'reg' because it's used in an always block. // reg [7:0] x, x_in; reg [7:0] y, y_in;
// Update state.
'state' is the actual flip-flop register and next_state is the combinatorial Check for the ZERO state which means an unexpected
// It is considered good practice by many designers to seperate the combinatorial // and sequential aspects of state registers, and often registers in general. // always @(posedge clk or negedge resetb) begin if (~resetb) state <= 0; else begin if (next_state == 0) begin state <= 16'h0001; end else begin state <= next_state;
always @(posedge clk or negedge resetb) begin if (~resetb) x <= 0; else end x <= x_in;
always @(posedge clk or negedge resetb) begin if (~resetb) y <= 0; else end y <= y_in;
If any particular
// state does NOT need to change a register, then it doesn't have to reference // the register at all. In these cases, the default below takes affect. This
// turns out to be a pretty succinct way to control stuff from the FSM. // x_in <= x; y_in <= y;
// state, then the default would throw state machine back to zero.
// at the sequential 'always' block for state to see how this is handled. // next_state <= 0;
// One-Hot State Machine Encoding. // // *** Using a 1'b1 in the case statement is the trick to doing One-Hot... // DON'T include a 'default' clause within the case because we want to
// //
// Initialization state. // state[0]: begin x_in <= 8'd20; y_in <= 8'd100;
// Just for fun.. Jump through states.. state[1]: next_state[2] <= 1'b1; state[2]: next_state[3] <= 1'b1; state[3]: next_state[4] <= 1'b1; state[4]: next_state[5] <= 1'b1; state[5]: next_state[6] <= 1'b1; state[6]: next_state[7] <= 1'b1;
// Conditionally decrement Y register. state[7]: begin if (a == 1) begin y_in <= y - 1; next_state[1] <= 1'b1; end else begin next_state[8] <= 1'b1; end end
// Just for fun.. Jump through states.. state[8]: next_state[9] state[9]: next_state[10] <= 1'b1; <= 1'b1;
// Conditionally increment X register. state[11]: begin if (b == 1) begin x_in <= x + 1; next_state[1] <= 1'b1;
// Just for fun.. Jump through states.. state[12]: next_state[13] <= 1'b1; state[13]: next_state[14] <= 1'b1; state[14]: next_state[15] <= 1'b1; state[15]: next_state[1] endcase end endmodule <= 1'b1; // Don't go back to our initialization state, but state following that one.
// synopsys translate_off module test_onehot; reg clk, resetb; reg [7:0] a; reg [7:0] b; wire [7:0] x; wire [7:0] y;
// Instantiate module. // onehot onehot ( .clk(clk), .resetb(resetb), .a(a), .b(b), .x(x), .y(y) );
// Generate clock. // initial begin clk = 0; forever begin #10 clk = ~clk; end end
// Reset..
// Here's the test. // // Should see X and Y get initially loaded with their starting values. // As long as a and b are zero, nothing should change. // When a is asserted, Y should slowly decrement. // slowly increment. // initial begin a = 0; b = 0; repeat (64) @(posedge clk); #1 That's it. When b is asserted, X should
$finish; end
// Monitor the module. // initial begin forever begin @(posedge clk); #1; $display ("a = %b, b = %b, x = %0d, y = %0d", a,b,x,y); end end
endmodule
module shifter(in,clock,reset,out);
input
in,clock,reset;
always@(posedge clock) begin if(reset) out=8'b0000; else begin out=out<<1; out[0]=in; end end endmodule
///////////////////////////////////////////////////////////////// ////////Module name:sequence_detect ////////Function ////////Author ////////Date :detect the sequence :Xiaoming Chen :18/12/2002 101110 in the data stream//////// //////// //////// ////////
/////////////////////////////////////////////////////////////////
`timescale 1ns/100ps module sequence_dectect(in, //the input data stream out, clock, reset); //the output signal when detect a 101110 sequence //clock signal //reset signal
parameter
START=3'b000, A B C D E
//the initial state =3'b001, =3'b010, =3'b011, =3'b100, =3'b101, //state A //state B //state C //state D //state E
=3'b110;
//state F
assign out=(state==E&&in==0)?1:0;
always@(posedge clock or negedge reset) if(!reset) begin state<=START; end else casex(state) START : if(in==1) state<=A;
default:state=START; endcase
endmodule
Demonstrate how to display strings for a particular signal. // This allows you to see a text string for a bus, which at times, might // help out in debugging. This is not intended for synthesis, of course.
// Keep these funny "string" signals seperate so we can disable them // at synthesis time and so they never impact the circuit. // //
module test;
// Declare a register with enough bits for the ASCII string. // synopsys translate_off reg [9*8-1:0] string_signal; // **** FOR TESTING // synopsys translate_on
// Here's the real circuit always @(posedge clk) if (reset) shift_register <= 4'b0001; else shift_register <= {shift_register[2:0], shift_register[3]};
// Now we assign to our string signal based on the real signal. // Disable this code when synthesizing. // // synopsys translate_off always @(shift_register) case (shift_register) 4'b0001: string_signal <= "BIT 4'b0010: string_signal <= "BIT 4'b0100: string_signal <= "BIT ZERO"; ONE"; TWO";
4'b1000: string_signal <= "BIT THREE"; default: string_signal <= "?????????"; endcase // synopsys translate_on
end
// Generate VCD file for viewing. // // Once we are in the Waveform Viewer, just set the format of 'string_signal' // to ASCII! // initial begin $dumpfile ("test_string_signal.vcd"); $dumpvars (0,test); end
endmodule ////////////////////////////////////////////////////////////// ////////Module name :test ////////Function ////////Author ////////Date :used to test the sequence_detect.v///////////// :Xiaoming Chen :18/12/2002 ///////////// ///////////// /////////////
//////////////////////////////////////////////////////////////
`include "sequence_dectect.v" `timescale 1ns/100ps module reg reg wire [63:0] data; out_signal,current_bit; test; clk,rst;
assign current_bit=data[63];
endmodule ...
1.0
Introduction
2.0
3.0
4.0
Memories
5.0
Bus Models
1.0
Introduction
The testbench is typically not part of the design and does not result
perfect, but hopefully may provide ideas for designers just starting
code
is intended to be synthesizable!
2.0
Often, for the sake of the tester, you must enforce transitions to
Anyway,
initial begin
#1 foo1in = 0;
forever begin
foo1_input_count = foo1_input_count + 1;
end
end
fork // Generate periodic event for sending the sync forever #(1000000000.0 * RATE) ->send_sync; // convert RATE to nanoseconds
// Wait on send_sync event, and then send SYNC synchronized with clk forever begin @(send_sync); syncdata = syncdata + CMTS_FREQ * CMTS_RATE; $display ("... SYNC = %h at time %0t, Local Time = %h", syncdata, $time, local_time); @(posedge clk) #1; syncstb = 1; @(posedge clk) #1; syncstb = 0; end join end endtask
3.0
Here is some
/*
`define PARITY_OFF
1'b0
`define PARITY_ON
1'b1
`define PARITY_ODD
1'b0
`define PARITY_EVEN
1'b1
`define NSTOPS_1
1'b0
`define NSTOPS_2
1'b1
`define BAUD_9600
2'b00
`define BAUD_4800
2'b01
`define BAUD_2400
2'b10
`define BAUD_1200
2'b11
`define NBITS_7
1'b0
`define NBITS_8
1'b1
task send_serial;
input baud;
input paritytype;
input parityenable;
input nstops;
input nbits;
input baud_error_factor;
reg
nbits;
reg
parityenable;
reg
paritytype;
reg
nstops;
integer
baud_error_factor;
reg
[7:0] char;
reg
parity_bit;
integer
bit_time;
begin
char = inputchar;
parity_bit = 1'b0;
case (baud)
endcase
$display ("Sending character %h, at %0d baud (err=%0d), %0d bits, %0s parity, %0d stops",
1000000000/bit_time,
baud_error_factor,
(nbits == `NBITS_7) ? 7 : 8,
(nstops == `NSTOPS_1) ? 1 : 2
);
// Start bit
serial_character = 1'b0;
// Start bit.
#(bit_time);
serial_character = char[0];
#(bit_time);
end
if (paritytype == `PARITY_ODD)
serial_character = parity_bit;
#(bit_time);
end
serial_character = 1'b1;
// Stop bit.
#(bit_time);
#(bit_time);
end
endtask
status, etc.
// ****
//
//
task receive_serial_uart1;
input baud;
input paritytype;
input parityenable;
input nstops;
input nbits;
reg
nbits;
reg
parityenable;
reg
paritytype;
reg
nstops;
integer
bit_time;
reg
expected_parity;
begin
receive_serial_result_uart1 = 0;
receive_serial_character_uart1 = 0;
case (baud)
endcase
receive_serial_result_uart1 = `RECEIVE_RESULT_OK;
@(negedge uart1out);
#(bit_time/2);
else begin
#(bit_time);
end
if (nbits == `NBITS_7)
#(bit_time);
if (paritytype == `PARITY_EVEN)
(^receive_serial_character_uart1[7:0]);
else
(~(^receive_serial_character_uart1[7:0]));
if (expected_parity != uart1out)
end
else begin
if (uart1out != 1)
else
if (nstops) begin
#(bit_time);
if (uart1out != 1)
end
#(bit_time/2);
end
end
end
endtask
4.0
Memories
Memories, whether they are RAMs, ROMs or special memories like FIFOs
up to these memories.
Memories are an easy way for the embedded Verilog core processor to
// 32K of FLASH
[0:(1024*32 - 1)];
// 32K of SRAM
//*****
//
//
The ASIC's ca[20] is the active LO chip select for the FLASH.
//
The ASIC's ca[18] is the active LO chip select for the SRAM.
//
// Write to FLASH
end
else begin
FLASH_memory[ca[14:0]] = cb;
//
sa_test_status = `SA_TEST_DONE;
sa_test_result = cb;
end
end
end
// Write to SRAM
end
else begin
SRAM_memory[ca[14:0]] = cb;
end
end
end
//
2'b10: begin
$display ("Read from SRAM Address = %h, Data = %h", ca, SRAM_memory[ca[14:0]]);
end
2'b01: begin
$display ("Read from FLASH Address = %h, Data = %h", ca, FLASH_memory[ca[14:0]]);
end
2'b00: begin
end
endcase
end
else begin
end
end
task clear_SRAM;
begin
SRAM_memory[SRAM_address] = 0;
end
end
endtask
relocating along the way and maybe setting a hew header bytes too.
task copy_to_FLASH_boot;
integer n;
begin
temp_memory[original_address] = 0;
end
FLASH_memory[15'h0801] = 0;
FLASH_memory[15'h0802] = temp_memory[3]; // Entry point is same as the address in the reset vector
n = 0;
FLASH_address = 15'h0803;
original_address = 0;
FLASH_memory[FLASH_address] = temp_memory[original_address];
FLASH_address = FLASH_address + 1;
original_address = original_address + 1;
n = n + 1;
end
end
endtask
Also, test vectors are easily loaded into Verilog memories using the
$readmem statements.
from a file into a memory, clock out the vectors to your circuit, and
output vector set that you know is good (e.g. your "Golden" vectors),
5.0
Bus Models
If the
The following
'defines' for these and update them as you get better timing information.
with the bus model, and later test your peripheral with the real processor core.
#10;
#10;
task write_to_foobar;
begin
@(posedge clk);
#5;
// <----
address = address_arg;
/* t_valid for wrxxx is 8ns, we are already 5ns into cycle, so wait 3ns */
#3;
we <= 1'b1;
/* t_valid for wrdata is 20ns, We are 8ns into cycle, wait 12ns */
#12
/* Wait till the next rising edge, wait for a little bit of hold time. */
@(posedge clk40);
#1;
#1;
we
<= 1'b0;
#4;
end
endtask
task read_from_foobar;
// Let's just write to a global with the resulting data retrieved (! bad practice, I know....)
begin
@(posedge clk)
#5;
address = address_arg;
/* t_valid for rbxxx is 8ns, we are already 5ns into cycle, so wait 3ns */
#3;
rw <= 1'b1;
/* Wait till the next rising edge, wait for a little bit of hold time. */
@(posedge clk);
last_data_read = data;
/* Wrap it up.
Deassert rw.
rw <= 1'b0;
#1;
end
endtask
[7:0]
m,n; cin;
[7:0]
sum; cout;
cla_8bits tt (m,n,cin,cout,sum);
initial begin
end
always@(m or n or cin) begin #20 $display("a=%b end endmodule b=%b cin=%b cout=%b sum=%b",m,n,cin,cout,sum);
This circuit generates WE pulses. // // // // // // // // // // // // // // // // // // // // module wpulse ( reset, The we pulse always occurs. you write_enable signal.
needs to access an asynchronous SRAM in a single cycle and you wanted generate the WE pulse synchronous with your system clock.
Every clk cycle, generate an active low WE pulse. The delay from the clk rising edge to the falling edge of Likewise,
we is based on abits setting, which affects delay taps, etc. bbits controls the following rising edge of we.
two flip flops that generate two opposite poraity toggling levels. A delay chain is attached to each of these outputs. The abits and bbits
get the desired tap, and the final two delayed signals are XORed together to get the final we. None of this is very tuned, you would look at your But, this
cycle time and pick a delay chain that makes sense for that. shows the effect.
This sort of circuit is, of course, highly dependent but that's why its programable. You probably
clk; reset; abits; // bits to select which delay tap to use for first edge bbits; // bits to select which delay tap to use for pulse width we;
reg
p1, p2;
wire wire
adelout; bdelout;
// 2 flip-flops that are opposite polarity. // every cycles. // always @(posedge clk)
p1 <= (reset) | (~reset & ~p1); // reset to 1 always @(posedge clk) p2 <= (~reset & ~p2); // reset to 0
delay4 adel2 (.a(adel1out), .z(adel2out)); delay4 adel3 (.a(adel2out), .z(adel3out)); delay4 adel4 (.a(adel3out), .z(adel4out));
// Select the tap of the p1 and p2 delay chains we want based on abits assign adelout = abits[3] & adel1out | abits[2] & adel2out | abits[1] & adel3out | abits[0] & adel4out; assign bdelout = bbits[3] & bdel1out | bbits[2] & bdel2out | bbits[1] & bdel3out | bbits[0] & bdel4out;
// Final we pulse is just the XOR of the two chains. assign we = adelout ^ bdelout;
endmodule
// This is our delay cell. module delay4 (a, z); input a; output z; reg always @(a) z = #4 a; endmodule z;
// synopsys translate_off module testwpulse; reg reg reg [3:0] reg [3:0] wire clk; reset; abits; // bits to select which delay tap to use for first edge bbits; // bits to select which delay tap to use for pulse width we;
wpulse wpulse_inst ( .reset .clk .abits .bbits .we ); (abits), (bbits), (we) (reset), (clk),
abits = 4'b0010; // Shortest pulse, latest in the cycle. bbits = 4'b0001; #200;
abits = 4'b0100; // Shortest pulse, middle of the cycle. bbits = 4'b0010; #200;
abits = 4'b1000; // Early in cycle, but not quite the longest. bbits = 4'b0010; #200;
$finish; end
// Generate the 50MHz clock initial begin clk = 0; forever begin #10 clk = 1; #10 clk = 0; end end
`define WAVES `ifdef WAVES initial begin $dumpfile ("wpulse.vcd"); $dumpvars (0,testwpulse); end
`endif endmodule
I have the VHDL code for all the components, but I don't know how to make the main code, relating all this components, can anyone help me, please? adder library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity additionneur is port(accum,offset,Q:in std_logic_vector (17 downto 0); C0,S :out std_logic_vector (17 downto 0) ); end additionneur; architecture Behavioral of additionneur is component demi_additionneur port(accum,offset:in std_logic_vector (17 downto 0); R,S:out std_logic_vector (17 downto 0) ); end component; signal S1,S2,S3:std_logic_vector(17 downto 0); Begin instance1:demi_additionneur port map(accum,offset,S1,S2); instance2:demi_additionneur port map(S2,Q,S3,S); C0<= S1 or S3; end Behavioral; half-adder library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity demi_additionneur is port(accum,offset:in std_logic_vector (17 downto 0); R,S:out std_logic_vector (17 downto 0) ); end demi_additionneur; architecture Behavioral of demi_additionneur is begin S<=accum xor offset; R<=accum and offset; end Behavioral; latch library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity bascule is port( D:in std_logic_vector (17 downto 0); clk:in std_logic; reset: in std_logic; Q:out std_logic_vector (17 downto 0) ); end bascule; architecture Behavioral of bascule is begin process (clk,reset) begin if (reset='1') then Q<="000000000000000000"; elsif (clk'event and clk='1') then Q<=D ; end if;
end process; end Behavioral; cosineROM library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity cosrom is port ( Entree: in std_logic_vector(17 downto 0); output: out std_logic_vector(7 downto 0) ); end cosrom; architecture Behavioral of cosrom is type cosROM_Array is array (0 to 256) of std_logic_vector(6 downto 0); constant Table : cosROM_Array := ( 0 => "1000011", 1 => "1111111", 2 => "1111001", 3 => "1111111", 4 => "1111100", 5 => "1111111", 6 => "1111111", 7 => "1111111", 8 => "1111111", 9 => "1111111", 10 => "1111111", 11 => "1111111", 12 => "1111111", 13 => "1111111", 14 => "1111111", 15 => "1111111", 16 => "1111111", 17 => "1111111", 18 => "1111111", 19 => "1111111", 20 => "1111111", 21 => "1111111", 22 => "1111111", 23 => "1111111", 24 => "1111111", 25 => "1111111", 26 => "1111110", 27 => "1111110", 28 => "1111110", 29 => "1111110", 30 => "1111110", 31 => "1111110", 32 => "1111110", 33 => "1111110", 34 => "1111101", 35 => "1111101", 36 => "1111101", 37 => "1111101", 38 => "1111101", 39 => "1111100", 40 => "1111100", 41 => "1111100", 42 => "1111100", 43 => "1111100", 44 => "1111011", 45 => "1111011", 46 => "1111011", 47 => "1111011", 48 => "1111010", 49 => "1111010", 50 => "1111010", 51 => "1111010", 52 => "1111010", 53 => "1111010", 54 => "1111001", 55 => "1111001", 56 => "1111001", 57 => "1111001", 58 => "1111001", 59 => "1111000", 60 => "1111000", 61 => "1111000", 62 => "1110111", 63 => "1110111", 64 => "1110111", 65 => "1110111", 66 => "1110110", 67 => "1110110", 68 => "1110110", 69 => "1110101", 70 => "1110101", 71 => "1110101", 72 => "1110100", 73 => "1110100", 74 => "1110100", 75 => "1110010", 76 => "1110010", 77 => "1110010", 78 => "1110001", 79 => "1110001", 80 => "1110001", 81 => "1110000", 82 => "1110000", 83 => "1101110", 84 => "1101110",
85 => "1101101", 86 => "1101101", 87 => "1101101", 88 => "1101100", 89 => "1101100", 90 => "1101011", 91 => "1101011", 92 => "1101010", 93 => "1101010", 94 => "1101010", 95 => "1101001", 96 => "1101001", 97 => "1101000", 98 => "1101000", 99 => "1100111", 100 => "1100111", 101 => "1100110", 102 => "1100110", 103 => "1100110", 104 => "1100101", 105 => "1100101", 106 => "1100100", 107 => "1100100", 108 => "1100011", 109 => "1100011", 110 => "1100010", 111 => "1100010", 112 => "1100001", 113 => "1100001", 114 => "1100000", 115 => "1100000", 116 => "1011111", 117 => "1011111", 118 => "1011110", 119 => "1011110", 120 => "1011101", 121 => "1011101", 122 => "1011100", 123 => "1011100", 124 => "1011011", 125 => "1011011", 126 => "1011010", 127 => "1011001", 128 => "1011000", 129 => "1011000", 130 => "1010111", 131 => "1010111", 132 => "1010100", 133 => "1010100", 134 => "1010011", 135 => "1010010", 136 => "1010010", 137 => "1010001", 138 => "1010001", 139 => "1010000", 140 => "1001111", 141 => "1001111", 142 => "1001110", 143 => "1001110", 144 => "1001101", 145 => "1001100", 146 => "1001100", 147 => "1001011", 148 => "1001010", 149 => "1001010", 150 => "1001001", 151 => "1001000", 152 => "1001000", 153 => "1000111", 154 => "1000111", 155 => "1111111", 156 => "1000110", 157 => "1000101", 158 => "1000101", 159 => "1000100", 160 => "1000011", 161 => "1000011", 162 => "1000010", 163 => "1111101", 164 => "1000001", 165 => "1000001", 166 => "1000000", 167 => "0111111", 168 => "0111110", 169 => "0111110", 170 => "0111101", 171 => "0111100", 172 => "0111100", 173 => "0111011", 174 => "0111010", 175 => "0111010", 176 => "0111001", 177 => "0111000", 178 => "0110111", 179 => "0110110", 180 => "0110101", 181 => "0110101", 182 => "0110100", 183 => "0110011", 184 => "0110011", 185 => "0110010", 186 => "0110001", 187 => "0110000", 188 => "0110000",
189 => "0101111", 190 => "0101110", 191 => "0101101", 192 => "0101101", 193 => "0101100", 194 => "0101011", 195 => "0101010", 196 => "0101010", 197 => "0101001", 198 => "0101000", 199 => "0100111", 200 => "0100111", 201 => "0100110", 202 => "0100111", 203 => "0100111", 204 => "0100110", 205 => "0100101", 206 => "0100100", 207 => "0100100", 208 => "0100011", 209 => "0100010", 210 => "0100001", 211 => "0100001", 212 => "0100000", 213 => "0100001", 214 => "0100001", 215 => "0100000", 216 => "0011111", 217 => "0011110", 218 => "0011110", 219 => "0011101", 220 => "0011100", 221 => "0011011", 222 => "0011011", 223 => "0011010", 224 => "0011001", 225 => "0011000", 226 => "0011000", 227 => "0010111", 228 => "0010110", 229 => "0010101", 230 => "0010100", 231 => "0010100", 232 => "0010011", 233 => "0010010", 234 => "0010001", 235 => "0010001", 236 => "0010000", 237 => "0001111", 238 => "0001110", 239 => "0001101", 240 => "0001101", 241 => "0001100", 242 => "0001011", 243 => "0001010", 244 => "0001010", 245 => "0001001", 246 => "0001000", 247 => "0000111", 248 => "0000110", 249 => "0000110", 250 => "0000101", 251 => "0000100", 252 => "0000011", 253 => "0000010", 254 => "0000010", 255 => "0000001", 256 => "1111111" ); begin process(Entree) begin if (Entree >= "000000000" and Entree <= "100000000") then output <= '0' & Table (conv_integer(Entree)); elsif (Entree > "100000000" and Entree <= "1000000000") then output <= '1' & Table (512- conv_integer(Entree)); elsif (Entree > "1000000000" and Entree <= "1100000000") then output <= '1' & Table ( conv_integer(Entree)- 512); elsif (Entree > "11000000000" and Entree <= "10000000000") then output <= '0' & Table ( 1024 - conv_integer(Entree)); end if; end process; end Behavioral;