Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Outputting a variable square pulse.

Status
Not open for further replies.
the first step would be to do something like this:

Code:
process
  procedure send_one is
  begin
    dataout <= '1';
    wait for HIGH_TIME_ONE;
    dataout <= '0';
    wait for LOW_TIME_ONE;
  end procedure send_one;

  procedure send_zero is
  begin
    dataout <= '1';
    wait for HIGH_TIME_ZERO;
    dataout <= '0';
    wait for LOW_TIME_ZERO;
  end procedure send_zero;

begin
  
  --------------------
  --First init the bus
  -------------------
  send_one;
  send_one;

  -----------------------
  --send start of frame
  ------------------------
  send_one;
  send_zero;
  send_one;

  --etc

This way, it makes more sense, and you're not manually drawing the wave forms. It would be quite simple to make procedures to send SOF, EOF, or some specified data.
 

So I have decided to create a state machine instead to output the desired square waves instead. This way it will be a lot cleaner and more adaptable.
 

So I have decided to create a state machine instead to output the desired square waves instead. This way it will be a lot cleaner and more adaptable.

As its a testbench, there is no need for statemachines, flags, or any other logic. You can write as if you're writing C code.
 

Well I understand that it is a test bench so I will be using "wait for __ us" and such. But after examining the requirements I though that a state machine would be more suitable to my needs. I have written a majority of the code, but there are still a few problems that I need help with.

1. I need to create a data structure like so
{AA67}
{B47F34}
{23BF4F23}

2. I then need to create a process that will look at the data that I have above and set two different count variables...
framecount = 3 --since there are three data sources
datacount = 2, for the first line, 3 for the second line, 4 for the last line.

I will also be using a count called bitcount that will allow me to keep track of how many bits of data have been transmitted so far. Since I will be transmitting in 8 bit increments, when I the bitcount reaches 8 that means either start reading and transmitting the next 8 bits of data or if there is no more data in that line then start transmitting the end of data (eod in state machine).

3. Lastly I need write a process that can read the value of the data in the array.

Here is what I have so far... Any help would be appreciated, and thank you for all the valuable guidance so far...
Code:
-----------------------------------------------------------------------------
component pwm_rx_tb is
	port ();
end component pwm_rx_tb;

architecture behavioral of pwm_rx_tb is
	type state_type is ( prog_idle, sof, data_trans, datatrans_idle, trans_bit, bit0, bit1, end_trans_bit, eod, eof, ifs);
	
	signal current_state : state_type;
	signal last_state : state_type;
	signal databit: std_logic 
	signal txbit: std_logic;
	signal reset: std_logic;
	constant bitcount;
	constant datacount;
	constant framecount;
	
	
	
	
begin

	reset: process
		reset = '1';
		wait for 1 fs;
		reset = '0';
		wait;
	end process reset;
	
	init: process
	begin
		if (reset = '1')
			current_state <= prog_idle;
			last_state <= prod_idle;
		else if (reset = '0')
			wait;
		end if;
	end process init;
	
	dataread: process
	begin
	end process dataread;
		
	state_machine: process
	begin		
		state_transitions: case current_state is
			when prog_idle =>
				if (framecount = 0) then
					current_state <= prog_idle;
					last_state <= prog_idle
				elseif (framecount = 1) then
					current_state <= sof;
					last_state <= prog_idle;
				end if;
			when sof =>
				if (last_state /= prog_idle) then
					current_state <= prog_idle;
					last_state <= prog_idle;
				elseif (last_state = prog_idle) then
					txbit = '0';
					wait for 70 us;
					txbit = '1';
					wait for 30 us;
					txbit = '0';
					wait for 17 us;
					current_state <= data_trans;
					last_state <= sof;
				end if;
			when data_trans =>
				bitcount = 0;
				if (last_state /= sof) then
					current_state <= prog_idle;
					last_state <= prog_idle;
				elseif (last_state = sof) then
					current_state <= trans_bit;
					last_state <= data_trans;
				end if;
			when trans_bit =>
				if (last_state /= data_trans) then
					current_state <= prog_idle;
					last_state <= prog_idle;
				elseif (last_state = data_trans) then
					if (databit = '0') then
						current_state <= bit0;
						last_state <= trans_bit;
					elseif (databit = '1') then
						current_state <= bit1;
						last_state <= trans_bit;
					end if;
				end if;
			when bit0 =>
				if (last_state /= trans_bit) then
					current_state <= prog_idle;
					last_state <= prog_idle;
				elseif (last_state = trans_bit) then
					txbit = '1';
					wait for 15 us;
					txbit = '0';
					wait for 7 us;
					bitcount = bitcount + 1;
					if (bitcount < 8) then
						current_state <= trans_bit;
						last_state <= bit0;
					elseif (bitcount = 8) then
						current_state <= data_trans_idle;
						last_state <= bit0;
					end if;
				end if;
			when bit1 =>
				if (last_state /= trans_bit) then
					current_state <= prog_idle;
					last_state <= prog_idle;
				elseif (last_state = trans_bit) then
					txbit = '1';
					wait for 7 us;
					txbit = '0';
					wait for 15 us;
					bitcount = bitcount + 1;
					if (bitcount < 8) then
						current_state <= trans_bit;
						last_state <= bit1;
					elseif (bitcount = 8) then
						current_state <= data_trans_idle;
						last_state <= bit1;
					end if;
				end if;
			when data_trans_idle =>
				datacount = datacount - 1;
				if (datacount = 0) then
					current_state <= eod;
					last_state <= data_trans_idle;
				elseif (datacount /= 0) then
					current_state <= data_trans;
					last_state <= sof;
				end if;
			when eod =>
				wait for 47 us;
				current_state <= eof;
				last_state <= eod;
			when eof =>
				wait for 23 us;
				current_state <= ifs;
				last_state <= eof;
			when ifs =>
				wait for 24 us;
				framecount = framecount -1;
				if (framecount /= 0) then
					current_state <= sof
					last_state <= prog_idle;
				elseif (framecount = 0) then
					current_state <= prog_idle;
					last_state <= prog_idle;
				end if;
		end case state_transitions;
		
	end process state_machine;
	
end architecture behavioral;
 

Look into record types - they will do exactly the data structuring you want.
In your present code you have the same multiple driver errors you had before, but now because the state type is not a resolved type you wont just get 'X', it just wont compile at all. Like I have said previosly, you cannot drive a signal from multiple processes.

I find myself now about to say the opposite of what I would tell everyone else: You're thinking too much like a hardware engineer. You need to think more like a software guy when it comes to writing testbenches (though to be fair, you probably wont listen and just charge ahead with your own wacky scheme anyway).

I personally think you're jumping in at the deep end (and off a cliff) with what you're trying to do with VHDL. I highly recommend you start from basics, and instead of going full steam ahead, slow down, and build up your understanding, instead of just vomitting out huge chunks of code that will not work.
 

It was not my idea to design the testbench in this manner. Unfortunately I did not have much say in the matter. While I would very much like to go back and start from the basics, I find myself in a position where time is limited. Since I will be doing more VHDL in the future will be spending alot of time brushing up on the basics, but unfortunately I am not currently in the position to go back and start from scratch.

Having said this, I sincerely appreciate your help this far.
I will look into record types and try to implement that. Also, I am not quite sure what you meant when you said that state_type is not a resolved type. Would you mind explaining this?

Regards
 

Rolsolved types are types that have a resolution function that allow them to be driven from multiple sources. The only one in standard VHDL is the std_logic type. So that if you write this in code:

my_sl <= '1';
my_sl <= '0';

The simulator would show 'X'. It is designed like this to allow the modelling of tri-state buffers and a few other things (like pull up/down resisistors).

The outcome is, if you did the same thing with the type std_ulogic (unresolved logic), the compile will throw the error "multiple drivers on my_sl". The above will also throw an error when you get to synthesis in FPGA tools (due to FPGA fabric limitation), but will work fine in modelsim. You can only have 1 source driving any unresolved signal.

Because your state type is unresolved (like every type unless you define the resolution function), the compiler has no idea what to do when you drive it from two sources, hence the error.
 

Okay this makes sense. So is there a way for me to overcome this problem in simulation while maintaining my general code structure above?
 

Please excuse my lack of understanding but what exactly do you mean when you say use procedures. Are you saying that I should use them within the state machine?
 

We have already covered methods to make your life easier. To summurise:

This is a testbench - not logic
Dont write it like you would write logic.
Use procedures (like the many examples above) to produce the signals you need.

You're making this much harder that it needs to be (and all the code you have posted has had errors, showing how hard you're making it).

You can explicitly draw the waveform using procedural code like:

a <= '1';
wait for 70us;
a <= '0';
wait for 30 '0';

And you can wrap sections up in procedures, inside loops, to do all the data sending you need.
 

Okay I understand that and as much as I would like to just dump this code and start from scratch I do not really have a choice. I unfortunately have to write it as a state machine; those were the requirements. That being said, how would I be able to fix the unresolved signal problem while still keeping the code as a state machine?

Also, I looked at record types and saw that it would be very easy to input bits into these "arrays", but I want to create an array like
{
AA B4 D5
F4 E4 34 5F
4D
}

I would like to have the user using the testbench be able to enter hex characters and then convert these into bitstrings for transmission.

---------- Post added at 11:53 ---------- Previous post was at 11:51 ----------

Okay I understand that and as much as I would like to just dump this code and start from scratch I do not really have a choice. I unfortunately have to write it as a state machine; those were the requirements. That being said, how would I be able to fix the unresolved signal problem while still keeping the code as a state machine?

Also, I looked at record types and saw that it would be very easy to input bits into these "arrays", but I want to create an array like
{
AA B4 D5
F4 E4 34 5F
4D
}

I would like to have the user using the testbench be able to enter hex characters and then convert these into bitstrings for transmission.
 

to fix the resolution issue, make sure you only drive a signal from a single process.

a std_logic_vector is already a "bitstring" so you cab just loop through the bits on the data line.

for you state machine I suggest you have one state for each section, and use counters to keep track of where you are. but this ie turning into a real application rather than a testbench or model.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top