From 4b6e0102d20d9ab060ce930e4b846c8be446bb06 Mon Sep 17 00:00:00 2001 From: Vasil Zlatanov Date: Mon, 12 Dec 2016 21:51:10 +0000 Subject: public push --- part_3/mylib/add3_ge5.v | 11 ++++ part_3/mylib/bin2bcd_16.v | 97 ++++++++++++++++++++++++++++ part_3/mylib/counter_16.v | 24 +++++++ part_3/mylib/divider_5000.v | 31 +++++++++ part_3/mylib/divider_50000.v | 31 +++++++++ part_3/mylib/hex_to_7seg.v | 28 ++++++++ part_3/mylib/pwm.v | 28 ++++++++ part_3/mylib/spi2adc.v | 150 +++++++++++++++++++++++++++++++++++++++++++ part_3/mylib/spi2dac.v | 128 ++++++++++++++++++++++++++++++++++++ 9 files changed, 528 insertions(+) create mode 100644 part_3/mylib/add3_ge5.v create mode 100644 part_3/mylib/bin2bcd_16.v create mode 100644 part_3/mylib/counter_16.v create mode 100644 part_3/mylib/divider_5000.v create mode 100644 part_3/mylib/divider_50000.v create mode 100644 part_3/mylib/hex_to_7seg.v create mode 100644 part_3/mylib/pwm.v create mode 100644 part_3/mylib/spi2adc.v create mode 100644 part_3/mylib/spi2dac.v (limited to 'part_3/mylib') diff --git a/part_3/mylib/add3_ge5.v b/part_3/mylib/add3_ge5.v new file mode 100644 index 0000000..282dcac --- /dev/null +++ b/part_3/mylib/add3_ge5.v @@ -0,0 +1,11 @@ +module add3_ge5 (in,out); + + input [3:0] in; + output reg [3:0] out; + + always @ (in) + if (in >= 4'd5) + out <= in + 4'd3; + else + out <= in; +endmodule \ No newline at end of file diff --git a/part_3/mylib/bin2bcd_16.v b/part_3/mylib/bin2bcd_16.v new file mode 100644 index 0000000..fdfb655 --- /dev/null +++ b/part_3/mylib/bin2bcd_16.v @@ -0,0 +1,97 @@ +//------------------------------ +// Module name: bin2bcd_16 +// Function: Converts a 16-bit binary number to 5 digits BCD +// .... it uses a shift-and-add3 algorithm +// Creator: Peter Cheung +// Version: 1.0 +// Date: 18 Sept 2016 +//------------------------------ +// For more explanation of how this work, see +// ... instructions on wwww.ee.ic.ac.uk/pcheung/teaching/E2_experiment + +module bin2bcd_16 (B, BCD_0, BCD_1, BCD_2, BCD_3, BCD_4); + + input [15:0] B; // binary input number + output [3:0] BCD_0, BCD_1, BCD_2, BCD_3, BCD_4; // BCD digit LSD to MSD + + wire [3:0] w1,w2,w3,w4,w5,w6,w7,w8,w9,w10,w11,w12,w13; + wire [3:0] w14,w15,w16,w17,w18,w19,w20,w21,w22,w23,w24,w25; + wire [3:0] w26,w27,w28,w29; + wire [3:0] a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13; + wire [3:0] a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25; + wire [3:0] a26,a27,a28,a29; + + // Instantiate a tree of add3-if-greater than or equal to 5 cells + // ... input is w_n, and output is a_n + add3_ge5 A1 (w1,a1); + add3_ge5 A2 (w2,a2); + add3_ge5 A3 (w3,a3); + add3_ge5 A4 (w4,a4); + add3_ge5 A5 (w5,a5); + add3_ge5 A6 (w6,a6); + add3_ge5 A7 (w7,a7); + add3_ge5 A8 (w8,a8); + add3_ge5 A9 (w9,a9); + add3_ge5 A10 (w10,a10); + add3_ge5 A11 (w11,a11); + add3_ge5 A12 (w12,a12); + add3_ge5 A13 (w13,a13); + add3_ge5 A14 (w14,a14); + add3_ge5 A15 (w15,a15); + add3_ge5 A16 (w16,a16); + add3_ge5 A17 (w17,a17); + add3_ge5 A18 (w18,a18); + add3_ge5 A19 (w19,a19); + add3_ge5 A20 (w20,a20); + add3_ge5 A21 (w21,a21); + add3_ge5 A22 (w22,a22); + add3_ge5 A23 (w23,a23); + add3_ge5 A24 (w24,a24); + add3_ge5 A25 (w25,a25); + add3_ge5 A26 (w26,a26); + add3_ge5 A27 (w27,a27); + add3_ge5 A28 (w28,a28); + add3_ge5 A29 (w29,a29); + + // wire the tree of add3 modules together + assign w1 = {B[14:11]}; // wn is the input port to module An + assign w2 = {a1[2:0], B[10]}; + assign w3 = {1'b0, B[15], a1[3], a2[3]}; + assign w4 = {a2[2:0], B[9]}; + assign w5 = {a3[2:0], a4[3]}; + assign w6 = {a4[2:0], B[8]}; + assign w7 = {a5[2:0], a6[3]}; + assign w8 = {a6[2:0], B[7]}; + assign w9 = {1'b0, a3[3], a5[3], a7[3]}; + assign w10 = {a7[2:0], a8[3]}; + assign w11 = {a8[2:0], B[6]}; + assign w12 = {a9[2:0], a10[3]}; + assign w13 = {a10[2:0], a11[3]}; + assign w14 = {a11[2:0], B[5]}; + assign w15 = {a12[2:0], a13[3]}; + assign w16 = {a13[2:0], a14[3]}; + assign w17 = {a14[2:0], B[4]}; + assign w18 = {1'b0, a9[3], a12[3], a15[3]}; + assign w19 = {a15[2:0], a16[3]}; + assign w20 = {a16[2:0], a17[3]}; + assign w21 = {a17[2:0], B[3]}; + assign w22 = {a18[2:0], a19[3]}; + assign w23 = {a19[2:0], a20[3]}; + assign w24 = {a20[2:0], a21[3]}; + assign w25 = {a21[2:0], B[2]}; + assign w26 = {a22[2:0], a23[3]}; + assign w27 = {a23[2:0], a24[3]}; + assign w28 = {a24[2:0], a25[3]}; + assign w29 = {a25[2:0], B[1]}; + + // connect up to four BCD digit outputs + assign BCD_0 = {a29[2:0],B[0]}; + assign BCD_1 = {a28[2:0],a29[3]}; + assign BCD_2 = {a27[2:0],a28[3]}; + assign BCD_3 = {a26[2:0],a27[3]}; + assign BCD_4 = {1'b0, a18[3], a22[3], a26[3]}; +endmodule + + + + diff --git a/part_3/mylib/counter_16.v b/part_3/mylib/counter_16.v new file mode 100644 index 0000000..a52dc38 --- /dev/null +++ b/part_3/mylib/counter_16.v @@ -0,0 +1,24 @@ +`timescale 1ns / 100ps + +module counter_16 ( + clock, + enable, + count, + reset + ); + + parameter BIT_SZ = 16; + input clock; + input enable; + input reset; + output reg [BIT_SZ-1:0] count; + + + initial count = 0; + + always @ (posedge clock) + if (reset == 1'b0) + count <= 0; + else if (enable == 1'b0) + count <= count + 1'b1; +endmodule diff --git a/part_3/mylib/divider_5000.v b/part_3/mylib/divider_5000.v new file mode 100644 index 0000000..2e5e20e --- /dev/null +++ b/part_3/mylib/divider_5000.v @@ -0,0 +1,31 @@ +`timescale 1ns / 100ps + + +module divider_5000 ( + clock, + out + ); + + parameter BIT_SZ = 16; + input clock; + reg [BIT_SZ-1:0] count; + + initial count = 0; + + output reg out; + + + always @ (posedge clock) + begin + if (count < 16'd5000) + begin + count <= count + 1'b1; + out <= 1'b0; + end + else + begin + out <= 1'b1; + count <= 1'b0; + end + end +endmodule diff --git a/part_3/mylib/divider_50000.v b/part_3/mylib/divider_50000.v new file mode 100644 index 0000000..6ce09f9 --- /dev/null +++ b/part_3/mylib/divider_50000.v @@ -0,0 +1,31 @@ +`timescale 1ns / 100ps + + +module divider_50000 ( + clock, + out + ); + + parameter BIT_SZ = 16; + input clock; + reg [BIT_SZ-1:0] count; + + initial count = 0; + + output reg out; + + + always @ (posedge clock) + begin + if (count < 16'd50000) + begin + count <= count + 1'b1; + out <= 1'b0; + end + else + begin + out <= 1'b1; + count <= 1'b0; + end + end +endmodule diff --git a/part_3/mylib/hex_to_7seg.v b/part_3/mylib/hex_to_7seg.v new file mode 100644 index 0000000..6b476e3 --- /dev/null +++ b/part_3/mylib/hex_to_7seg.v @@ -0,0 +1,28 @@ +module hex_to_7seg (out,in); + output [6:0] out; + input [3:0] in; + + reg [6:0] out; + + always @ (*) + case (in) + 4'h0: out = 7'b1000000; + 4'h1: out = 7'b1111001; + 4'h2: out = 7'b0100100; + 4'h3: out = 7'b0110000; + 4'h4: out = 7'b0011001; + 4'h5: out = 7'b0010010; + 4'h6: out = 7'b0000010; + 4'h7: out = 7'b1111000; + 4'h8: out = 7'b0000000; + 4'h9: out = 7'b0011000; + 4'hA: out = 7'b0001000; + 4'hB: out = 7'b0000011; + 4'hC: out = 7'b1000110; + 4'hD: out = 7'b0100001; + 4'hE: out = 7'b0000110; + 4'hF: out = 7'b0001110; + endcase +endmodule + + \ No newline at end of file diff --git a/part_3/mylib/pwm.v b/part_3/mylib/pwm.v new file mode 100644 index 0000000..6dce0a5 --- /dev/null +++ b/part_3/mylib/pwm.v @@ -0,0 +1,28 @@ +module pwm (clk, data_in, load, pwm_out); + + input clk; + input [9:0] data_in; + input load; + output pwm_out; + + reg [9:0] d; + reg [9:0] count; + reg pwm_out; + + always @ (posedge clk) + if (load == 1'b1) d <= data_in; + + initial count = 10'b0; + + always @ (posedge clk) begin + count <= count + 1'b1; + if (count > d) + pwm_out <= 1'b0; + else + pwm_out <= 1'b1; + + end + + + +endmodule \ No newline at end of file diff --git a/part_3/mylib/spi2adc.v b/part_3/mylib/spi2adc.v new file mode 100644 index 0000000..3878f71 --- /dev/null +++ b/part_3/mylib/spi2adc.v @@ -0,0 +1,150 @@ +//------------------------------ +// Module name: spi2adc +// Function: SPI interface for MCP3002 ADC +// Creator: Peter Cheung +// Version: 1.1 +// Date: 24 Jan 2014 +//------------------------------ + +module spi2adc (sysclk, start, channel, data_from_adc, data_valid, + sdata_to_adc, adc_cs, adc_sck, sdata_from_adc); + + input sysclk; // 50MHz system clock of DE0 + input start; // Pulse to start ADC, minimum wide = clock period + input channel; // channel 0 or 1 to be converted + output [9:0] data_from_adc; // 10-bit ADC result + output data_valid; // High indicates that converted data valid + output sdata_to_adc; // Serial commands send to adc chip + output adc_cs; // chip select - low when converting + output adc_sck; // SPI clock - active during conversion + input sdata_from_adc; // Converted serial data from ADC, MSB first + +//-------------Input Ports----------------------------- +// All the input ports should be wires + wire sysclk, start, sdata_from_adc; + +//-------------Output Ports----------------------------- +// Output port can be a storage element (reg) or a wire + reg [9:0] data_from_adc; + reg adc_cs; + wire sdata_to_adc, adc_sck, data_valid; + +//-------------Configuration parameters for ADC -------- + parameter SGL=1'b1; // 0:diff i/p, 1:single-ended + parameter MSBF=1'b1; // 0:LSB first, 1:MSB first + +// --- Submodule: Generate internal clock at 1 MHz ----- + reg clk_1MHz; // 1Mhz clock derived from 50MHz + reg [4:0] ctr; // internal counter + parameter TIME_CONSTANT = 5'd24; // change this for diff clk freq + initial begin + clk_1MHz = 0; // don't need to reset - don't care if it is 1 or 0 to start + ctr = 5'b0; // ... to start. Initialise to make simulation easier + end + + always @ (posedge sysclk) // + if (ctr==0) begin + ctr <= TIME_CONSTANT; + clk_1MHz <= ~clk_1MHz; // toggle the output clock for squarewave + end + else + ctr <= ctr - 1'b1; +// ---- end internal clock generator ---------- + +// ---- Detect start is asserted with a small state machine + // .... FF set on positive edge of start + // .... reset when adc_cs goes high again + reg [1:0] sr_state; + parameter IDLE = 2'b00,WAIT_CSB_FALL = 2'b01, WAIT_CSB_HIGH = 2'b10; + reg adc_start; + + initial begin + sr_state = IDLE; + adc_start = 1'b0; // set while sending data to ADC + end + + always @ (posedge sysclk) + case (sr_state) + IDLE: if (start==1'b0) sr_state <= IDLE; + else begin + sr_state <= WAIT_CSB_FALL; + adc_start <= 1'b1; + end + WAIT_CSB_FALL: if (adc_cs==1'b1) sr_state <= WAIT_CSB_FALL; + else sr_state <= WAIT_CSB_HIGH; + + WAIT_CSB_HIGH: if (adc_cs==1'b0) sr_state <= WAIT_CSB_HIGH; + else begin + sr_state <= IDLE; + adc_start <= 1'b0; + end + default: sr_state <= IDLE; + endcase +//------- End circuit to detect start and end of conversion + + +// spi controller designed as a state machine +// .... with 16 states (idle, and S1-S15 indicated by state value + + reg [4:0] state; + reg adc_done, adc_din, shift_ena; + + initial begin + state = 5'b0; adc_cs = 1'b1; adc_done = 1'b0; + adc_din = 1'b0; shift_ena <= 1'b0; + end + + always @(posedge clk_1MHz) begin + + // default outputs and state transition + adc_cs <= 1'b0; adc_done <= 1'b0; adc_din <= 1'b0; shift_ena <= 1'b0; + state <= state + 1'b1; + case (state) + 5'd0: begin + if (adc_start==1'b0) begin + state <= 5'd0; // still idle + adc_cs <= 1'b1; // chip select not active + end + else begin + state <= 5'd1; // start converting + adc_din <= 1'b1; // start bit is 1 + end + end + 5'd1: adc_din <= SGL; // SGL bit + 5'd2: adc_din <= channel; // CH bit + 5'd3: adc_din <= MSBF; // MSB first bit + 5'd4: shift_ena <= 1'b1; // start shifting data from adc + 5'd15: begin + shift_ena <= 1'b0; + adc_done <= 1'b1; + end + 5'd16: begin + adc_cs <= 1'b1; // last state - disable chip select + state <= 5'd0; // go back to idle state + end + default: + shift_ena <= 1'b1; // unspecified states are covered by default above + endcase + end // ... always + + // shift register for output data + reg [9:0] shift_reg; + initial begin + shift_reg = 10'b0; + data_from_adc = 10'b0; + end + + always @(negedge clk_1MHz) + if((adc_cs==1'b0)&&(shift_ena==1'b1)) // start shifting data_in + shift_reg <= {shift_reg[8:0],sdata_from_adc}; + + // Latch converted output data + always @(posedge clk_1MHz) + if(adc_done) + data_from_adc = shift_reg; + + // Assign outputs to drive SPI interface to DAC + assign adc_sck = !clk_1MHz & !adc_cs; + assign sdata_to_adc = adc_din; + assign data_valid = adc_cs; +endmodule \ No newline at end of file diff --git a/part_3/mylib/spi2dac.v b/part_3/mylib/spi2dac.v new file mode 100644 index 0000000..586a231 --- /dev/null +++ b/part_3/mylib/spi2dac.v @@ -0,0 +1,128 @@ +//------------------------------ +// Module name: spi2dac +// Function: SPI interface for MPC4911 DAC +// Creator: Peter Cheung +// Version: 2.0 +// Date: 8 Nov 2016 +//------------------------------ + +module spi2dac (sysclk, data_in, load, dac_sdi, dac_cs, dac_sck, dac_ld); + + input sysclk; // 50MHz system clock of DE1 + input [9:0] data_in; // input data to DAC + input load; // Pulse to load data to dac + output dac_sdi; // SPI serial data out + output dac_cs; // chip select - low when sending data to dac + output dac_sck; // SPI clock, 16 cycles at half sysclk freq + output dac_ld; + +//-------------Input Ports----------------------------- +// All the input ports should be wires + wire sysclk, load; + wire [9:0] data_in; + +//-------------Output Ports----------------------------- +// Output port can be a storage element (reg) or a wire + reg dac_cs, dac_ld; + wire dac_sck, dac_sdi; + + parameter BUF=1'b1; // 0:no buffer, 1:Vref buffered + parameter GA_N=1'b1; // 0:gain = 2x, 1:gain = 1x + parameter SHDN_N=1'b1; // 0:power down, 1:dac active + + wire [3:0] cmd = {1'b0,BUF,GA_N,SHDN_N}; // wire to VDD or GND + + // --- internal 1MHz symmetical clock generator ----- + reg clk_1MHz; // 1Mhz clock derived from 50MHz + reg [4:0] ctr; // internal counter + + parameter TC = 5'd24; // Terminal count - change this for diff clk freq + initial begin + clk_1MHz = 0; // don't need to reset - don't care if it is 1 or 0 to start + ctr = 5'b0; // ... Initialise when FPGA is configured + end + + always @ (posedge sysclk) + if (ctr==0) begin + ctr <= TC; + clk_1MHz <= ~clk_1MHz; // toggle the output clock for squarewave + end + else + ctr <= ctr - 1'b1; + // ---- end internal 1MHz symmetical clock generator ---------- + + // ---- FSM to detect rising edge of load and falling edge of dac_cs + // .... sr_state set on posedge of load + // .... sr_state reset when dac_cs goes high at the end of DAC output cycle + reg [1:0] sr_state; + parameter IDLE = 2'b00,WAIT_CSB_FALL = 2'b01, WAIT_CSB_HIGH = 2'b10; + reg dac_start; // set if a DAC write is detected + + initial begin + sr_state = IDLE; + dac_start = 1'b0; // set while sending data to DAC + end + + always @ (posedge sysclk) // state transition + case (sr_state) + IDLE: if (load==1'b1) sr_state <= WAIT_CSB_FALL; + WAIT_CSB_FALL: if (dac_cs==1'b0) sr_state <= WAIT_CSB_HIGH; + WAIT_CSB_HIGH: if (dac_cs==1'b1) sr_state <= IDLE; + default: sr_state <= IDLE; + endcase + + always @ (*) + case (sr_state) + IDLE: dac_start = 1'b0; + WAIT_CSB_FALL: dac_start = 1'b1; + WAIT_CSB_HIGH: dac_start = 1'b0; + default: dac_start = 1'b0; + endcase + + //------- End circuit to detect start and end of conversion state machine + + //------- spi controller FSM + // .... with 17 states (idle, and S1-S16 + // .... for the 16 cycles each sending 1-bit to dac) + reg [4:0] state; + + initial begin + state = 5'b0; dac_ld = 1'b0; dac_cs = 1'b1; + end + + always @(posedge clk_1MHz) // FSM state transition + case (state) + 5'd0: if (dac_start == 1'b1) // waiting to start + state <= state + 1'b1; + else + state <= 5'b0; + 5'd17: state <= 5'd0; // go back to idle state + default: state <= state + 1'b1; // default go to next state + endcase + + always @ (*) begin // FSM output + dac_cs = 1'b0; dac_ld = 1'b1; + case (state) + 5'd0: dac_cs = 1'b1; + 5'd17: begin dac_cs = 1'b1; dac_ld = 1'b0; end + default: begin dac_cs = 1'b0; dac_ld = 1'b1; end + endcase + end //always + // --------- END of spi controller FSM + + // shift register for output data + reg [15:0] shift_reg; + initial begin + shift_reg = 16'b0; + end + + always @(posedge clk_1MHz) + if((dac_start==1'b1)&&(dac_cs==1'b1)) // parallel load data to shift reg + shift_reg <= {cmd,data_in,2'b00}; + else // .. else start shifting + shift_reg <= {shift_reg[14:0],1'b0}; + + // Assign outputs to drive SPI interface to DAC + assign dac_sck = !clk_1MHz&!dac_cs; + assign dac_sdi = shift_reg[15]; +endmodule \ No newline at end of file -- cgit v1.2.3-54-g00ecf