//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 11:23:27 01/28/2010
// Design Name:
// Module Name: frequency_counter
// Project Name:
// Target Devices:
// Tool versions:
// Description: Verilog implementatino of the frequency counter reference
// design from Xilinx for Spartan 3E Starter Kit
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module frequency_counter(
output [7:0] led,
input [4:0] sw,
output strataflash_oe,
output strataflash_ce,
output strataflash_we,
inout [7:4] lcd_d,
output lcd_rs,
output lcd_rw,
output lcd_e,
input sma_clk,
input clk_50mhz
);
// signals for counting the test clock
reg [3:0] ab_switch_delay;
reg a_count_ce, b_count_ce;
reg [31:0] a_count, b_count;
reg a_count_rst, b_count_rst;
reg freq_for_measurement;
wire test_clk;
// signals for 1 second interrupt generation and couter switching
reg ab_switch;
reg [99:0] interrupt_delay;
reg [25:0] one_second_count;
reg one_second_pulse;
reg interrupt;
reg [7:0] source_control;
// signals for processor interconnect
reg [7:0] in_port;
wire [7:0] out_port;
wire write_strobe, read_strobe;
wire [7:0] port_id;
wire interrupt_ack;
wire [17:0] instruction;
wire [9:0] address;
// lcd wires
reg [7:0] lcd_reg;
wire lcd_drive;
wire lcd_output_data;
// led reg
reg [7:0] led_reg;
// ring osscillator instantiations
ring_osc logic_oscillator (.reset(source_control[6]),.osc_out(ring_oscillator));
ring_osc2 logic_oscillator2 (.reset(source_control[6]),.osc_out(ring_oscillator2));
// frequency selection mux - purely combinational
always@(sma_clk or clk_50mhz or ring_oscillator or ring_oscillator2)
if(source_control[1:0] == 2'b00)
freq_for_measurement = sma_clk;
else if(source_control[1:0] == 2'b01)
freq_for_measurement = clk_50mhz;
else if(source_control[1:0] == 2'b10)
freq_for_measurement = ring_oscillator2;
else
freq_for_measurement = ring_oscillator;
// global clock buffer the test clock
BUFG buffer_clkin(.O(test_clk), .I(freq_for_measurement));
// counter switch control
always@(posedge test_clk)
begin
ab_switch_delay <= {ab_switch_delay[2:0], ab_switch};
case(ab_switch_delay[3:1])
3'b000: begin
a_count_ce <= 1;
b_count_ce <= 0;
end
3'b111: begin
a_count_ce <= 0;
b_count_ce <= 1;
end
default: begin
a_count_ce <= 1;
b_count_ce <= 0;
end
endcase
end
// test counters
always@(posedge test_clk or posedge a_count_rst)
if(a_count_rst)
a_count <= 'b0;
else if(a_count_ce)
a_count <= a_count+1;
else
a_count <= a_count;
always@(posedge test_clk or posedge b_count_rst)
if(b_count_rst)
b_count <= 'b0;
else if(b_count_ce)
b_count <= b_count+1;
else
b_count <= b_count;
// one second interrupt generation and clock switching
/* always@(posedge clk_50mhz)
begin
// divide by 50,000,000 to generate pulse
if(one_second_count == 26'd49999999)
begin
one_second_count <= 'b0;
one_second_pulse <= 1'b1;
end
else
begin
one_second_count <= one_second_count + 1;
one_second_pulse <= 1'b0;
end
// delay 100 clock cycles before generating interrupt
interrupt_delay <= {interrupt_delay[98:0], one_second_pulse};
// interrupt generation
if (interrupt_ack == 1'b1)
interrupt <= 1'b0;
else if (interrupt_delay[99] == 1'b1)
interrupt <= 1'b1;
else
interrupt <= interrupt;
// counter selection switch toggle's each second
if (one_second_pulse == 1'b1)
ab_switch <= ~ab_switch;
end*/
always@(posedge clk_50mhz)
begin
// divide by 50,000,000 to generate pulse
if(one_second_count == 26'd49999999)
begin
one_second_count <= 'b0;
one_second_pulse <= 1'b1;
end
else
begin
one_second_count <= one_second_count + 1;
one_second_pulse <= 1'b0;
end
end
always@(posedge clk_50mhz)
begin
// delay 100 clock cycles before generating interrupt
interrupt_delay <= {interrupt_delay[98:0], one_second_pulse};
end
always@(posedge clk_50mhz)
begin
// interrupt generation
if (interrupt_ack == 1'b1)
interrupt <= 1'b0;
else if (interrupt_delay[99] == 1'b1)
interrupt <= 1'b1;
else
interrupt <= interrupt;
end
always@(posedge clk_50mhz)
begin
// counter selection switch toggle's each second
if (one_second_pulse == 1'b1)
ab_switch <= ~ab_switch;
else
ab_switch <= ab_switch;
end
// picoblaze instantiation
kcpsm3 processor (.address(address),
.instruction(instruction),
.port_id(port_id),
.write_strobe(write_strobe),
.out_port(out_port),
.read_strobe(read_strobe),
.in_port(in_port),
.interrupt(interrupt),
.interrupt_ack(interrupt_ack),
.reset(reset),
.clk(clk_50mhz));
fc_ctrl program_rom (.address(address),
.instruction(instruction),
.proc_reset(proc_reset),
.clk(clk_50mhz));
// processor input ports
always@ (posedge clk_50mhz)
case(port_id[7:4])
// read A counter
4'b0000: in_port <= a_count[7:0];
4'b0001: in_port <= a_count[15:8];
4'b0010: in_port <= a_count[23:16];
4'b0011: in_port <= a_count[31:24];
// read B counter
4'b0100: in_port <= b_count[7:0];
4'b0101: in_port <= b_count[15:8];
4'b0110: in_port <= b_count[23:16];
4'b0111: in_port <= b_count[31:24];
// read slide switches
4'b1000: in_port <= {3'b000, ab_switch, sw};
// read LC Ddata at address 90 hex
4'b1001: in_port <= {lcd_d, 4'b0000};
// original design used a dont care condition
// I've decided to let it retain its value.
default: in_port <= in_port;
endcase
// output ports
always@ (posedge clk_50mhz)
if(write_strobe)
case(port_id[3:0])
// LED register at address 0x01
4'b0001: led_reg <= out_port;
// Counter reset controls at 0x02
4'b0010: begin
a_count_rst <= out_port[0];
b_count_rst <= out_port[1];
end
// LCD data/controls at 0x04
4'b0100: begin
lcd_reg <= out_port;
end
// Source selection and control at 0x08
4'b1000: source_control <= out_port;
endcase
// LCD controls
assign lcd_rw_control = lcd_reg[1];
assign lcd_drive = lcd_reg[3];
assign lcd_output_data = lcd_reg [7:4];
// LCD Outputs
assign lcd_e = lcd_reg[0];
assign lcd_rw = lcd_rw_control && lcd_drive;
assign lcd_rs = lcd_reg[2];
assign lcd_d = ((lcd_rw_control == 1'b0) && (lcd_drive == 1'b1)) ? lcd_output_data : 4'bZZZZ;
// LED assignment
//assign led = led_reg;
// Debug assignments
assign led[7]=led_reg[7]; //A counter
assign led[6]=led_reg[0]; //B counter
assign led[5]=a_count[10]; // should toggle at 8hz when enabled
assign led[4]=b_count[10]; // should toggle at 8hz when enabled
assign led[3]=one_second_count[24]; // should toggle very fast.
assign led[2]=one_second_pulse; // once per second
assign led[1]=interrupt_ack; //interrupt ack
assign led[0]=interrupt; //interrupt
// strataflash chip enable signals to disable onboard strataflash
assign strataflash_we = 1'b1;
assign strataflash_ce = 1'b1;
assign strataflash_oe = 1'b1;
endmodule